引言
手机工厂测试需求,设计组合键开机快速进入工程测试apk,减少员工测试等待用时.
Android Framework层修改
确认是否是工程测试开机模式
屏蔽开机向导
开机扫描apk个数最小化
开机直接启动工程测试apk
1. 启动模式保存到系统属性值
代码路径:/frameworks/base/core/jni/AndroidRuntime.cpp
static void setFactoryMode(){
FILE *fp;
int FACTORY_MODE = 1;
int value;
if((fp=fopen("/sys/devices/platform/hq_boot_status/boot_status","rt"))==NULL){
ALOGE("[FACTORY_MODE] Can not open file");
return;
}
value = fgetc(fp);
ALOGE("[FACTORY_MODE] hq_boot_status = %d", value);
if(FACTORY_MODE == value){
int result = property_set("ro.hq.factorymode", "1");
if(result < 0){
ALOGE("[FACTORY_MODE] set prop failed!\n");
}
}
fclose(fp);
}
......
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
......
setFactoryMode();
......
}
startVm是启动Dalvik虚拟机方法,在里面添加setFactoryMode方法.
/sys/devices/platform/hq_boot_status/boot_status节点信息是驱动保存的开机启动方式id,组合键进入的话值为1.
int result = property_set("ro.hq.factorymode", "1") 写入属性值ro.hq.factorymode为1,后续给Android的java层调用.
2. PMS扫描安装指定的apk
代码路径:frameworks/base / services/core/java/com/android/server/pm/PackageManagerService.java
boolean isFactoryKitTest = getFactoryKitMode();
private List factoryPackages = new ArrayList() {{
add("android");
add("com.mediatek");
add("com.android.providers.telephony");
add("com.android.providers.applications");
add("com.android.defcontainer");
add("com.android.providers.settings");
add("com.android.keychain");
add("com.android.dialer");
add("com.android.packageinstaller");
add("com.google.android.packageinstaller");
add("com.android.settings");
add("com.android.phone");
add("com.android.systemui");
add("com.android.huaqin.factory");
add("com.android.bluetooth");
add("com.android.launcher3");
}};
private boolean getFactoryKitMode() {
int result = SystemProperties.getInt("ro.hq.factorymode", 0);
if (result == 1) {
return true;
}
return false;
}
......
private PackageParser.Package scanPackageLI(File scanFile, int parseFlags, int scanFlags,
long currentTime, UserHandle user) throws PackageManagerException {
......
if(isFactoryKitTest && !factoryPackages.contains(pkg.packageName)){
Slog.d(TAG, "Current in factory test mode, package: " + pkg.packageName + "not in factory application list,Skipping...");
return pkg;
}
......
}
创建动态数组factoryPackages,里面包含需要安装的APK包名,都是Android启动必须包含的apk或者是测试模式下需要用到的apk.
getFactoryKitMode方法去读取ro.hq.factorymode的值,确定是工程测试模式的化返回true.
scanPackageLI是安装apk的方法,在这里判断factoryPackages是否包含即将进入安装流程的apk,来确定是否继续.
3. AMS中改变home属性的category
代码位置:frameworks/base / services/core/java/com/android/server/am/ActivityManagerService.java
Intent getHomeIntent() {
Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
intent.setComponent(mTopComponent);
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
/*[FACTORY_TEST_BY_APK] modify start*/
//intent.addCategory(Intent.CATEGORY_HOME);
//changed for factorykit,if factory kit mode is set,start factory kit apk,otherwise,start HOME activity. 2013.08.09.yjf
int factorykitmode = 0;
factorykitmode = SystemProperties.getInt("ro.hq.factorymode", 0);
if(factorykitmode == 1)
{
intent.addCategory("android.category.factory.kit");
}
else
{
intent.addCategory(Intent.CATEGORY_HOME);
}
/*[FACTORY_TEST_BY_APK] modify end*/
}
return intent;
}
测试模式apk的categroy设置为android.category.factory.kit,代码intent.addCategory("android.category.factory.kit")将home属性的categroy指定为它,这样的话开机启动的应用就是会是我们的测试apk.