总括
本文基于Android S 应用预测框架,导入了一个tensorflow模型并运行成功,意在调研下Android系统的应用预测流程。
背景介绍
Android 12的应用预测功能是其核心创新之一,旨在通过智能化技术优化用户交互体验。以下是基于官方技术逻辑的详细说明:
一、功能核心机制
-
数据收集与行为建模
Android 12通过机器学习模型持续分析用户行为数据,包括应用使用频率、时间段(如早晨查看新闻、通勤时使用娱乐应用)、场景(工作或休闲)等,构建动态的用户行为画像
- 数据类型:涵盖应用启动顺序、地理位置、设备使用模式等维度。
- 隐私保护:数据仅在本地处理,避免上传云端,符合Android隐私沙盒规范。
-
智能预测算法
系统采用多维度关联分析算法,不仅预测单个应用的启动概率,还识别应用间的关联性(例如打开邮件后可能启动日历或文档编辑器)
- 实时行为整合:结合用户当前操作(如插耳机可能触发音乐应用预加载)进行动态调整。
-
后台预加载技术
预测到用户可能使用的应用后,系统会在后台提前加载其核心组件(如主界面、常用功能模块),但不会完全启动应用进程以节省资源
- 资源调度优化:通过智能优先级管理,确保预加载不影响前台应用的流畅度或电池续航。
二、实际应用场景(官方示例)
-
高频场景预判
- 早晨例行操作:系统识别用户起床后常打开社交媒体或新闻应用,提前预加载,实现"点击即启动"
- 通勤娱乐需求:检测到用户连接蓝牙耳机或进入地铁区域时,自动预加载音乐、视频类应用。
-
工作流效率提升
- 在用户启动会议软件后,系统可能预加载文档协作工具(如Google Docs)或邮件客户端,减少多任务切换的等待时间
三、用户体验优化效果
-
启动速度提升
- 官方测试显示,预加载技术可将高频应用的启动时间缩短50%以上,部分场景下实现"瞬时响应"。
-
资源与能效平衡
- 通过动态资源分配,预加载仅占用闲置内存,并在检测到电量不足时自动降低预加载强度,确保续航不受显著影响。
代码实现
关于这部分网上的资料很少,未能找到相关的资料,本着按图索骥的原则,下载一套android 12源码分析一下,以下的分析基于android-12 r3.
一、AppPredictionManagerService
想要实现应用预测的功能,必须有一个系统服务来承担数据采集和预测启动的能力,本着这个思路去检索,发现了"AppPredictionManagerService"
- AppPredictionManagerService 在SystemServer的startOtherServices函数中启动
- 需要配置AppPredictionManagerService 绑定的客户端,默认无配置,则不会启动改服务
less
private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
// 省略部分代码
// App prediction manager service
if (deviceHasConfigString(context, R.string.config_defaultAppPredictionService)) {
t.traceBegin("StartAppPredictionService");
mSystemServiceManager.startService(APP_PREDICTION_MANAGER_SERVICE_CLASS);
t.traceEnd();
} else {
Slog.d(TAG, "AppPredictionService not defined by OEM");
}
}
xml
<!-- The package name for the system's app prediction service.
This service must be trusted, as it can be activated without explicit consent of the user.
Example: "com.android.intelligence/.AppPredictionService"
-->
<string name="config_defaultAppPredictionService" translatable="false"></string>
同样通过按图索骥的方式,检索到了客户端,模块名为AppPredictionService(com.android.apppredictionservice),这个模块默认不会编译到镜像里面,需要手动添加,代码修改如下:
bash
/code/Android12/build$ vi make/target/product/handheld_system_ext.mk +25
PRODUCT_PACKAGES += \
Launcher3QuickStep \
Provision \
Settings \
StorageManager \
SystemUI \
WallpaperCropper \
AppPredictionService \
xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.apppredictionservice">
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<application>
<service
android:name=".PredictionService"
android:exported="true">
<intent-filter>
<!-- This constant must match AppPredictionService.SERVICE_INTERFACE -->
<action android:name="android.service.appprediction.AppPredictionService" />
</intent-filter>
</service>
</application>
</manifest>
将config_defaultAppPredictionService配置成对应的名字:
bash
<string name="config_defaultAppPredictionService" translatable="false">com.android.apppredictionservice/.PredictionService</string>
好了所有的条件已经准备就绪,我们直接看下AppPredictionManagerService启动的时序图:
- 服务启动只是把我们配置的客户端service名字记了下来并没有发起连接动作,这里我们需要继续调查服务是怎么绑定上的

二、Launcher3
通过分析log发现,应用和AppPredictionManagerService建立session连接的时候才会触发服务绑定,通过分析代码和增加trace,创建session 这个动作是在Launcher3中作的,AOSP Launcher3代码量很大,这里我们只涉及到感兴趣的部分,研究Launcher3不是目的。
- 系统启动Launcher3时,Launcher3的onCreate方法中会调用到createPredictor
- 创建Predictor时,会创建PredictorSession,这个方法的实现在AppPredictionManagerService中,这其中涉及到RemoteService(我想它就是"AppPredictionService"在fwk中的代号)
- RemoteService会调用到binderservice最终拉起AppPredictionService(com.android.apppredictionservice)

三、AppPredictionService(com.android.apppredictionservice)
AppPredictionService模块就一个类,重点是这个框架,谷歌设计这个的本意是OEM可以自己扩展,目前基于AOSP释放的代码来分析。
- PredictionService onCreate方法中默认DEFAULT_PACKAGES赋值了五个应用:日历、相册、map、email、浏览器;
- 这五个应用就是预测应用的默认值,赋值完成后保存到本地sharedPreferences中;
xml
emulator_x86_64:/data/data/com.android.apppredictionservice # cd shared_prefs/
emulator_x86_64:/data/data/com.android.apppredictionservice/shared_prefs # cat mypref.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="third">com.android.camera2/com.android.camera.CameraLauncher</string>
<string name="fifth">com.android.deskclock/com.android.deskclock.DeskClock</string>
<string name="fourth">com.android.contacts/com.android.contacts.activities.PeopleActivity</string>
<string name="first">com.android.settings/com.android.settings.Settings</string>
<string name="second">com.android.quicksearchbox/com.android.quicksearchbox.SearchActivity</string>
</map>
- 当Laucnher3监控到有app动作时,会触发回调到系统中,系统会调用到AppPredictionService模块来更新target,更新完之后,AppPredictionService将packagelist返回给client,最终经过系统在传回到Launcher3中;
注:此图是简化版本工作流程,实际代码流程复杂。
- Launcher3会将更新的预测应用展示出来,并保存到本地sharedPreferences,如下图,第一行5个应用就是预测应用;

现有算法
AOSP释放出来的就是一个空壳子,这部分涉及到OEM定制不开源,所以自带的算法基本上就是个demo:
- 当触发感兴趣的事件时,更新预测list,当前list如果包含点击的应用则返回
- 如果不包含,直接删除最后一个,将该次的应用添加到第一个
ini
// Check if packageName already exists in existing list of appNames
for (String packageName:appNames) {
if (packageName.contains(target.getPackageName())) {
found = true;
break;
}
}
if (!found) {
appNames.remove(appNames.size() - 1);
appNames.add(0, mostRecentComponent);
for (int i = 0; i < appNameKeys.length; i++) {
editor.putString(appNameKeys[i], appNames.get(i));
}
editor.apply();
predictionList.remove(predictionList.size() - 1);
predictionList.add(0, event.getTarget());
Log.d(TAG, "onAppTargetEvent:: update predictions");
postPredictionUpdateToAllClients();
}
一、Try TensorFlow
why TensorFlow
AOSP 从2017年开始逐步支持tensorflow,到现在越来越完善。
- 2017年Google I/O大会首次宣布TensorFlow Lite作为轻量级解决方案,并于2017年11月15日正式发布开发者预览版
- 2022年,TensorFlow Lite通过Google Play服务集成,成为Android官方ML推理引擎,提供稳定的跨版本API支持
TensorFlow在Android上的核心优势
轻量化与高效性能
- TensorFlow Lite专为移动端优化,模型体积小(通过量化、剪枝等技术压缩),推理速度快,内存占用低
- 支持硬件加速(如Android Neural Networks API),在GPU或NPU上运行时性能提升显著
跨平台兼容性
- 模型可无缝部署到Android、iOS及嵌入式设备,且支持多种格式
- 通过Google Play服务内置二进制文件,减少APK体积,并保持与不同Android版本的兼容性
- 提供简洁的Java/Kotlin API和丰富的文档,降低开发门
- 支持异步加载模型,避免主线程阻塞,提升应用流畅度
隐私与离线能力
- 本地化推理无需依赖云端服务器,保护用户隐私,且在网络不佳时仍可运行
- 支持设备端训练(如通过Model Maker库),实现个性化模型微调
生态与工具链完善
- 提供模型转换工具(TFLite Converter)、调试工具及预训练模型库(如MobileNet),简化开发流程
- 与TensorFlow生态系统(如TF Hub、TF.js)深度集成,便于模型复用与扩展
二、导入尝试
我们本地通过tensorflow做一个模型,尝试将它部署到AppPredictionService
模块中:
行为模式模拟与预测
- 通过生成合成数据(当前应用+时间),预测用户在不同时间段可能打开的下一个应用
- 支持预测的包名包括日历、相机、通讯录等10个常见Android系统应用。
模型训练与部署
- 使用TensorFlow构建双输入神经网络,结合嵌入层处理应用名称的类别特征和时间数值特征。
- 最终将模型转换为TFLite格式(
app_predictor.tflite
),便于移动端低资源环境部。

导入模型
在APP bp文件中增加对tensorflow的依赖,将模型文件放到assert路径下,并配置依赖
css
android_app {
name: "AppPredictionService",
defaults: ["apppredictionservice_defaults"],
manifest: "AndroidManifest.xml",
srcs: [
":AppPredictionService-srcs",
],
static_libs: [
"tensorflowlite_java",
],
jni_libs: ["libtensorflowlite_jni"],
aaptflags: ["-0 .tflite"],
asset_dirs: ["assets"],
resource_dirs: [
],
}
在APP 中加载模型
ini
private static final String MODEL_FILE = "models/app_predictor.tflite";
try {
encoder = LabelEncoder.loadFromAssets(getAssets(), "models/label_encoder.txt");
String[] files = getAssets().list("models");
Log.d(TAG, "模型目录文件: " + Arrays.toString(files));
// 从 assets 加载模型
AssetFileDescriptor fileDescriptor = getAssets().openFd(MODEL_FILE);
FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
FileChannel fileChannel = inputStream.getChannel();
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
MappedByteBuffer buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
// 初始化解释器
Interpreter.Options options = new Interpreter.Options();
options.setUseNNAPI(false); // 禁用神经网络API
options.setUseXNNPACK(false); //禁用XNNPACK优化
tflite = new Interpreter(buffer, options);
validateModelInputs();
} catch (IOException e) {
Log.e(TAG, "Error loading model", e);
}
当launcher发生点击事件时,触发预测动作:
ini
private void predictNextApp(String currentApp, int hour) {
try {
// 1. 编码并验证输入
int encodedApp = encoder.encode(currentApp);
if (encodedApp < 0 || encodedApp >= encoder.getClassCount()) {
Log.e(TAG, "编码值越界: " + encodedApp);
return;
}
float normalizedHour = hour / 23.0f;
// 2. 创建输入缓冲区(假设模型期望形状为 [1, 1])
ByteBuffer appBuffer = createInt32Buffer(encodedApp); // 形状 [1, 1]
ByteBuffer hourBuffer = createFloat32Buffer(normalizedHour); // 形状 [1, 1]
// 3. 输入包装为 Object[]
Object[] inputs = new Object[]{appBuffer, hourBuffer};
// 4. 运行推理
float[][] output = new float[1][encoder.getClassCount()];
Map<Integer, Object> outputs = new HashMap<>();
outputs.put(0, output);
tflite.runForMultipleInputsOutputs(inputs, outputs);
// 6. 解析结果
int predictedId = argmax(output[0]);
String predictedApp = encoder.decode(predictedId);
Log.d(TAG, "预测结果: " + predictedApp);
} catch (Exception e) {
Log.e(TAG, "推理异常: " + e.getMessage(), e);
}
}
模拟器验验证可用:
yaml
04-01 22:43:12.112 1507 1507 D PredictionService: onAppTargetEvent com.android.dialer
04-01 22:43:12.112 1507 1507 D PredictionService: 预测结果: com.android.deskclock
代码路径
本文涉及到的源码基于Android 12, 涉及到的源码路径如下:
- App:
" packages/apps/OnDeviceAppPrediction "
" packages/apps/Launcher3 "
- Framework:
" frameworks/base/core/java/android/service/appprediction/ "
" frameworks/base/services/appprediction/java/com/android/server/appprediction/ "
" frameworks/base/core/java/android/app/prediction/ "
- Tensorflow
" external/tensorflow "