現在產品有一個需求,在工廠測試的時候啓動時Android原生桌面launcher3,測試完畢後啓動我們產品默認的app。
所以自己在Android啓動 桌面的時候做一個屬性判斷,如果屬性
persist.defaulthome = false
就啓動launcher3, = true就啓動我們產品app。
這個屬性修改由我們產品測試apk 在產品測試完成之後修改。
SystemProperties.set("persist.defaulthome","true");
在Android 8.1 由於seLinux權限管理很嚴格,默認app 修改這個屬性一定會報 avc denied 錯誤,
所以第一步,添加persist.defaulthome 權限控制修改
device/mediatek/sepolicy/basic/non_plat/non_plat/property.te
添加
定義新的屬性聲明
type persist_defaulthome_prop, property_type;
device/mediatek/sepolicy/basic/non_plat/non_plat/property_contexts
定義persist.defaulthome 屬於persist_defaulthome_prop 這個域
persist.defaulthome u:object_r:persist_defaulthome_prop:s0
修改 系統app對於 persist_defaulthome操作權限
device/mediatek/sepolicy/basic/non_plat/system_app.te
allow system_app persist_defaulthome_prop:property_service set;
allow system_app persist_defaulthome_prop:file {getattr open read };
這樣我們的測試app 在測試完成之後,只要一行代碼就完成屬性修改
SystemProperties.set("persist.defaulthome","true");
Android啓動 最終會調用 startHomeActivityLocked 啓動默認桌面,所以通過這個函數來獲取屬性值最終選擇啓動的app。
文件 ActivityManagerService.java
private static final String DEFAULT_HOME = "persist.defaulthome";
boolean startHomeActivityLocked(int userId, String reason) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
&& mTopAction == null) {
// We are running in factory test mode, but unable to find
// the factory test app, so just sit around displaying the
// error message and don't try to start anything.
return false;
}
if(GetProvisioned()!=1){
PutProvisioned();
}
Intent intent = getHomeIntent();
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
//add start by blv --------------
Log.e("PPTV","start home!!!!!!!");
PackageManager pm = mContext.getPackageManager();
Intent newintent = new Intent(Intent.ACTION_MAIN);
newintent.addCategory(Intent.CATEGORY_HOME);
List<ResolveInfo> resolveInfoList = pm.queryIntentActivities(newintent, 0);
boolean defaultHome = SystemProperties.getBoolean(DEFAULT_HOME,false);
Log.e("PPTV","SystemProperties defaultHome is =======" + defaultHome);
if(resolveInfoList != null){
int size = resolveInfoList.size();
for(int i = 0; i < size; i++){
ResolveInfo rInfo = resolveInfoList.get(i);
if(defaultHome){
if(rInfo.activityInfo.name.equals("xxxxxxx")){
Log.e("PPTV","start custom home!!!!!!!");
aInfo = rInfo.activityInfo;
}
}else{
if(rInfo.activityInfo.name.equals("com.android.launcher3.Launcher")){
Log.e("PPTV","start default home!!!!!!!");
aInfo = rInfo.activityInfo;
}
}
}
}
// add end ----------
intent.setComponent(new ComponentName(
aInfo.applicationInfo.packageName, aInfo.name));
// Don't do this if the home app is currently being
// instrumented.
aInfo = new ActivityInfo(aInfo);
aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instr == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
// For ANR debugging to verify if the user activity is the one that actually
// launched.
final String myReason = reason + ":" + userId + ":" + resolvedUserId;
mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}