应用标签思路参考
目的:
基于pid维度建立1.应用使用资源标签例如sensor,gps,bluetooth,audio,NFC,camera, 麦克风等,2.应用状态标签例如是否可见,前台,后台,上传下载等,3.应用和系统关联的标签例如widget,画中画,悬浮窗,知通栏等,为应用冻结,关联启动,CPU锁托管,查杀应用,限制应用的IO等快稳省策略提供标签支撑。
原理:
1.建立native、systemserver和app的插桩机制,涉及AMS\WMS\AUDIO\CAMERA\GPS\SENSOR\BT\NOTIFICATION\VIDEO等插桩
2.基于位掩码操作例如|= 添加状态,&= ~ 清除状态,^ 检测变化管理20多个标签值,&的方式确定标签状态的值,可高效低内存获取应用的单个或多个标签状态
3.Python定期爬虫8万多应用类型数据库,并提供同进程和跨进程的单/批量查询与应用类型变化监听给桌面分类、游戏模式和统一资源调度
4.基于状态机建立IDLE-RUNNING-HIBERNATION的三态机制,分层过渡冻结前释放非关键资源减少误冻结概率
构建了uid~package~pid的关系,并建立pid维度的标签链
事件类型 | 触发场景 |
AUDIO_OUT | 应用使用/停止音频输出(播放音乐等) |
VIDEO | 应用使用/停止视频播放 |
VISIBLE | 应用切换到前台/后台 |
NOTIFICATION | 应用添加/移除状态栏通知 |
FLOATVIEW | 应用显示/关闭悬浮窗 |
AUDIO_IN | 应用启用/停用麦克风 |
BLUETOOTH | 应用连接/断开蓝牙设备 |
GPS | 应用请求/停止定位 |
APPWIDGET | 应用绑定/解绑桌面小部件 |
SENSOR | 应用使用传感器(加速度、陀螺仪等) |
CAMERA | 应用打开/关闭摄像头 |
FOREGROUND_SERVICE | 应用启动/停止前台服务 |
APP_STARTED | 应用进程启动或死亡 |
DOWNLOAD | 应用下载任务开始/完成/失败 |
VPN_STATE | VPN连接建立/断开 |
TTS_STATE | 应用连接/断开文本转语音引擎 |
RUNNING | 应用进程正在运行(非缓存) |
APPIDLE | 应用进入/退出省电空闲模式 |
HIBERNATION | 应用被冻结/解冻(Android 12+) |
标签的掩码使用
通过位掩码(Bitmask)管理多状态
(state & SOURCE_GPS) != 0, 说明这个应用在使用GPS,否则没有在使用GPS
(state & SOURCE_GROUP ) != 0 说明这个应用在使用资源 的某个或多个标签
protected void setState(int flag, int state) {
....
// 根据 enable 参数修改全局状态 mState(位掩码操作)
if (enable) {
mState |= flag; // 将对应flag的位设为1,即添加flag状态
} else {
mState &= ~flag; // 将对应flag的位设为0,即清除flag状态
}
...
}
public void notifyPidExit(int pid, String reason) {
if (AppRecordUtils.DEBUG) {
BlackviewTool.logD(TAG, "notifyPidExit:pid=" + pid + ",reason=" +reason);
}
mLastState = mState;
// 清除 STATE_PID 相关位
mState &= ~STATE_PID;
for (int idx = mPids.size() - 1; idx >= 0; idx--) {
ProcessRecord procState = mPids.valueAt(idx);
// 若 mNotification 为 true,则将 STATE_NOTIFICATION 标志位设为 1;否则保持 mState 不变
mState |= procState.mNotification ? STATE_NOTIFICATION : 0;
...
}
if (mState != mLastState) {
// ^ 检测变化
notifyStateChanged(pid, mLastState ^ mState, false);
}
}