0. 摘要
- 需求接口:是否在使用camera boolean isUsingCameraPkg(String pkg)
- 需求接口:camera的使用时间 boolean getUseCameraTime(String pkg)
- Framewor中的Camera埋点方案
- CameraService.connectHelper:START_CAMERA
- CameraService.disconnect:START_CAMERA
- 管控接口:是否为高耗电camera boolean isHighPowerCamera(String pkg)
- 管控接口:是否可以管控camera boolean boolean killBgUsingCameraPkg
第三方Camera的功耗异常分级管控
- 第一级:灭屏Camera使用超过5分钟,wakeLock 持锁时长超过5分钟,弹出通知提醒
- 第二级:灭屏Camera使用超过5分钟,wakeLock 持锁时长超过5分钟,黑名单应用,应用分类为TYPE_SHOP、TYPE_MONEY、TYPE_NEWS_CLIENT、TYPE_BROWSER。则限制、冻结或kill
- 第三级:灭屏中国区的社交应用使用camera,非前台,灭屏Camera使用超过1小时,wakeLock 持锁时长超过5分钟,没有音频播放,则限制、冻结或kill
1. 需求接口
private HashMap<String, Long> mUsingCameraPkgs = new HashMap<>();
/**
* camera的使用时间
*/
public boolean isUsingCameraPkg(String pkg) {
Long start = mUsingCameraPkgs.get(pkg);
boolean result = false;
if(start != null) {
long time = SystemClock.uptimeMillis() - start;
long scroff = mIDeviceState.getScrOffUpTime();
Log.i("ScenarioService", "isUsingCameraPkg, pkg: " + pkg + ", time: " + time + ", start: " + start + ", scroff: " + scroff);
if(time >= 30_000 && scroff >= 30_000) {
result = true;
}
}
return result;
}
/**
* Camera的使用时间
*/
public long getUseCameraTime(String pkg) {
synchronized (mUsingCameraPkgs) {
long lastUseTime = mUsingCameraPkgs.get(pkg);
long useTime = SystemClock.elapsedRealtime() - lastUseTime;
Log.i(TAG, "getUseCameraTime, pkg: " + pkg + ", useTime: " + useTime + ", start: " + lastUseTime);
return useTime;
}
}
2. Framewor中的Camera埋点
frameworks/av/services/camera/libcameraservice/CameraService.cpp
- CameraService.connectHelper:START_CAMERA
- CameraService.disconnect:START_CAMERA
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
...
BasicClient::sCameraService->mPowerSdk.sendEventBrief(202,0,String16(String8::format("%s|%d|%s",cameraId.string(),clientPid,String8(clientPackageName).string())));//START_CAMERA = 202;
// Update shim paremeters for legacy clients
if (effectiveApiLevel == API_1) {
// Assume we have always received a Client subclass for API1
sp<Client> shimClient = reinterpret_cast<Client*>(client.get());
binder::Status CameraService::BasicClient::disconnect() {
...
mDisconnected = true;
String16 value(mClientPackageName);
sCameraService->mPowerSdk.sendEventBrief(141,0,String16(String8::format("%s|%d|%s",mCameraIdStr.string(),mClientPid,String8(value).string())));//END_CAMERA = 141;
}
3. 埋点数据处理
private HashMap<String, Long> mUsingCameraPkgs = new HashMap<>();
case ConstantEvent.END_CAMERA://id|pid|pkg
case ConstantEvent.START_CAMERA:
String pkg = split[2];
if (pkg == null) {
break;
}
if ("".equals(pkg)) {
break;
}
synchronized (mUsingCameraPkgs) {
if(event.getEventId() == ConstantEvent.START_CAMERA){
mUsingCameraPkgs.put(pkg, SystemClock.elapsedRealtime());
} else if(event.getEventId() == ConstantEvent.END_CAMERA){
mUsingCameraPkgs.remove(pkg);
} else {
// do nothing
}
}
break;
public boolean isUsingCameraPkg(String pkg) {
Long start = mUsingCameraPkgs.get(pkg);
boolean result = false;
if(start != null) {
long time = SystemClock.elapsedRealtime() - start;
long scroff = mDeviceService.getScrOffUpTime();
Log.i("ScenarioService", "isUsingCameraPkg, pkg: " + pkg + ", time: " + time + ", start: " + start + ", scroff: " + scroff);
if(time >= 30_000 && scroff >= 30_000) {
result = true;
}
}
return result;
}
4. 目的:第三方Camera的功耗异常分级管控
private static final ArrayList<String> CAMERA_BLACK_LIST = new ArrayList<String>() {
{
add("com.benqu.wuta");
add("com.qmx990880.app");
add("cn.nbcb.watermarkcamera");
add("com.IFF.BIO.HawkSpex");
add("com.ss.android.ugc.aweme");
add("om.ucamera.ucam");
add("com.tencent.karaoke");
add("com.dadaabc.zhuozan.dadaabcstudent");
}
};
/**
* 高耗电使用Camera:
* Camera使用超过5分钟,wakeLock 持锁时长超过5分钟
*/
private boolean isHighPowerCamera(String str) {
if (!mIScenario.isUsingCameraPkg(str) || !mIDeviceState.isScreenOff()) {
return false;
}
Log.i("AppWakelockAnalyzer", str + " using camera. duration:" + mStatsDuration);
return mStatsDuration >= 300_000;
}
/**
* 第三方Camera的功耗异常分级管控
* - 第一级:灭屏Camera使用超过5分钟,wakeLock 持锁时长超过5分钟,弹出通知提醒
* - 第二级:灭屏Camera使用超过5分钟,wakeLock 持锁时长超过5分钟,黑名单应用,应用分类为TYPE_SHOP、TYPE_MONEY、TYPE_NEWS_CLIENT、TYPE_BROWSER。则限制、冻结或kill
* - 第三级:灭屏中国区的社交应用使用camera,非前台,灭屏Camera使用超过1小时,wakeLock 持锁时长超过5分钟,没有音频播放,则限制、冻结或kill
*/
private boolean killBgUsingCameraPkg(String pkg, boolean isAllowKillSystemApp, int optimizeType) {
if (mIScenario.isUsingCameraPkg(pkg) && mIDeviceState.isScreenOff() && mStatsDuration >= 300_000) {
if (CAMERA_BLACK_LIST.contains(pkg) || isAllowKillSystemApp) {
Log.i("AppWakelockAnalyzer", pkg + " using camera after scroff, K_L it. duration:" + mStatsDuration);
return true;
} else {
if (optimizeType == ApplistMgr.TYPE_SMART_OPTIMIZE_APPS || optimizeType == ApplistMgr.TYPE_ALWAYS_OPTIMIZE_APPS ) {
int appType = mIAppType.getAppType(pkg);
if (appType == ConstantPower.TYPE_SHOP || appType == ConstantPower.TYPE_MONEY
|| appType == ConstantPower.TYPE_NEWS_CLIENT|| appType == ConstantPower.TYPE_BROWSER) {
Log.i("AppWakelockAnalyzer", pkg + " using camera after scroff , K_L it. type:" + appType);
return true;
} else if (mIAppManager.isTreatAsChinaProduct() && !isFrontApp(pkg)) {
if (appType != ConstantPower.IM) {
if (mIDeviceState.isTorchModeEnabled() || pkg.contains("flashlight")) {
Log.i("AppWakelockAnalyzer", pkg + " using camera after scroff , not K_L it, maybe flashlight is on");
return false;
}
Log.i("AppWakelockAnalyzer", pkg + " using camera after scroff , K_L it. type:" + appType);
return true;
} else if (mIScenario.getUseCameraTime(pkg) > 3600_000 && mStatsDuration > 300_000 && !mIDeviceState.isPlayingSoundByUid(mUid)) {
Log.i("AppWakelockAnalyzer", pkg + " IM using camera after scroff, K_L it. type:" + appType);
return true;
}
}
}
Log.i("AppWakelockAnalyzer", "not K_L pkg: " + pkg + " using camera bg stats duration : " + mStatsDuration + " optType:" + optimizeType);
}
}
return false;
}
|