RK:主屏幕
Platform: RK3288
OS: Android 7.1
Kernel: 4.4.143
Android7.0 DirectBoot阻塞开机分析 宇落无痕 https://blog.csdn.net/fu_kevin0606/article/details/65437594
一.需求: 仿Android5.1 Settings.apk 上的 设置 主屏幕
问题点:a.动态显示 一级设置列表 主屏幕
b.二级设置列表 home 属性的list
二.Android 7.1 Setttings home识别个数异常
2.1.home属性的apk 有两个 Settings.apk Launcher.apk
1 2 3 4 5 | private int getHomeActivitiesCount() { final ArrayList<ResolveInfo> homeApps = new ArrayList<ResolveInfo>(); getPackageManager().getHomeActivities(homeApps); return homeApps.size(); } |
2.2.launcher启动流程增加了settings--->FallbackHome--->launcher
在启动Launcher之前会先启动一个FallbackHome,之后才会启动Launcher,而FallbackHome属于Settings中的一个透明的activity,
Settings的android:directBootAware=true,并且FallbackHome在category中配置了Home属性,而Launcher的
android:directBootAware=false,所以只有FallbackHome可以在direct boot模式下启动
补:Direct Boot模式下app是无法运行的要运行的话需要在AndroidManinfest.xml中设置 android:directBootAware="true"
1 2 3 4 5 6 7 8 9 10 | <!-- Triggered when user-selected home app isn't encryption aware --> <activity android:name= ".system.FallbackHome" android:excludeFromRecents= "true" android:theme= "@style/FallbackHome" > <intent-filter android:priority= "-1000" > <action android:name= "android.intent.action.MAIN" /> <category android:name= "android.intent.category.HOME" /> <category android:name= "android.intent.category.DEFAULT" /> </intent-filter> </activity> |
其中包括home属性,这样影响后续识别home属性的应用,这里介绍一个过滤的办法:
https://www.cnblogs.com/crushgirl/p/13437967.html
1 | android:excludeFromRecents= "true" |
在 Android 系统中,如果我们不想某个 Activity 出现在 “Recent screens” 中,可以设置这条属性:
2.3.packages\apps\Settings\src\com\android\settings\HomeSettings.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | private void buildHomeActivitiesList() { ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>(); ComponentName currentDefaultHome = mPm.getHomeActivities(homeActivities); Context context = getPrefContext(); mCurrentHome = null ; mPrefGroup.removeAll(); mPrefs = new ArrayList<HomeAppPreference>(); mHomeComponentSet = new ComponentName[homeActivities.size()]; int prefIndex = 0 ; boolean supportManagedProfilesExtra = getActivity().getIntent().getBooleanExtra(EXTRA_SUPPORT_MANAGED_PROFILES, false ); boolean mustSupportManagedProfile = hasManagedProfile() || supportManagedProfilesExtra; for ( int i = 0 ; i < homeActivities.size(); i++) { final ResolveInfo candidate = homeActivities.get(i); final ActivityInfo info = candidate.activityInfo; ComponentName activityName = new ComponentName(info.packageName, info.name); mHomeComponentSet[i] = activityName; try { Drawable icon = info.loadIcon(mPm); CharSequence name = info.loadLabel(mPm); HomeAppPreference pref; if (mustSupportManagedProfile && !launcherHasManagedProfilesFeature(candidate)) { pref = new HomeAppPreference(context, activityName, prefIndex, icon, name, this , info, false /* not enabled */ , getResources().getString(R.string.home_work_profile_not_supported)); } else { pref = new HomeAppPreference(context, activityName, prefIndex, icon, name, this , info, true /* enabled */ , null ); } //FLAG_EXCLUDE_FROM_RECENTS这里对应上述的属性 android:excludeFromRecents if ((info.flags & ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS) == 0 ){ mPrefs.add(pref); mPrefGroup.addPreference(pref); } if (activityName.equals(currentDefaultHome)) { mCurrentHome = pref; } prefIndex++; } catch (Exception e) { Log.v(TAG, "Problem dealing with activity " + activityName, e); } } if (mCurrentHome != null ) { if (mCurrentHome.isEnabled()) { getActivity().setResult(Activity.RESULT_OK); } new Handler().post( new Runnable() { public void run() { mCurrentHome.setChecked( true ); } }); } } |
三.Android5.1 设置主launcher
3.1.frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | private void setDefaultLauncher() { String packageName = SystemProperties.get( "persist.app.pkgName" , "com.android.launcher3" ); String className = SystemProperties.get( "persist.app.className" , "com.android.launcher3.Launcher" ); Slog.i(TAG, "defautl packageName = " + packageName + ", default className = " + className); if ((packageName != null && packageName.trim().length() > 1 ) && (className != null && className.trim().length() > 0 )) { IPackageManager pm = ActivityThread.getPackageManager(); ArrayList<IntentFilter> intentList = new ArrayList<IntentFilter>(); ArrayList<ComponentName> cnList = new ArrayList<ComponentName>(); mContext.getPackageManager().getPreferredActivities(intentList, cnList, null ); IntentFilter dhIF; for ( int i = 0 ; i < cnList.size(); i++) { dhIF = intentList.get(i); if (dhIF.hasAction(Intent.ACTION_MAIN) && dhIF.hasCategory(Intent.CATEGORY_HOME)) { mContext.getPackageManager().clearPackagePreferredActivities(cnList.get(i).getPackageName()); } } Intent intent = new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_HOME); List<ResolveInfo> list = new ArrayList<ResolveInfo>(); try { list = pm.queryIntentActivities(intent, intent.resolveTypeIfNeeded(mContext.getContentResolver()), PackageManager.MATCH_DEFAULT_ONLY,UserHandle.getCallingUserId()); } catch (RemoteException e) { throw new RuntimeException( "Package manager has died" , e); } IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_MAIN); filter.addCategory(Intent.CATEGORY_HOME); filter.addCategory(Intent.CATEGORY_DEFAULT); final int N = list.size(); ComponentName[] set = new ComponentName[N]; int bestMatch = 0 ; for ( int i = 0 ; i < N; i++) { ResolveInfo r = list.get(i); set[i] = new ComponentName(r.activityInfo.packageName,r.activityInfo.name); if (r.match > bestMatch) bestMatch = r.match; } ComponentName launcher = new ComponentName(packageName, className); try { pm.addPreferredActivity(filter, bestMatch, set, launcher,UserHandle.getCallingUserId()); } catch (RemoteException e) { throw new RuntimeException( "Package manager has died" , e); } } } |
3.2.setDefaultLauncher();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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 ; } setDefaultLauncher(); Intent intent = getHomeIntent(); ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId); if (aInfo != null ) { 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.instrumentationClass == null ) { intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); mStackSupervisor.startHomeActivity(intent, aInfo, reason); } } return true ; } |
3.3.客户应用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | 罒.应用在category中配置了Home属性 <category android:name= "android.intent.category.HOME" /> 罒.设置属性 3.3 . 1 setProperty( "persist.app.pkgName" , "com.android.launcher3" ); // 包名 setProperty( "persist.app.className" , "com.android.launcher3.Launcher" ); // 类名 RootCommand( "reboot" ); // 重启生效 3.3 . 2 . @SuppressWarnings ( "finally" ) public String getProperty(String key) { String value = "unknown" ; try { Class<?> c = Class.forName( "android.os.SystemProperties" ); Method get = c.getMethod( "get" , String. class , String. class ); value = (String) (get.invoke(c, key, "unknown" )); } catch (Exception e) { e.printStackTrace(); } finally { return value; } } public void setProperty(String key, String value) { try { Class<?> c = Class.forName( "android.os.SystemProperties" ); Method set = c.getMethod( "set" , String. class , String. class ); set.invoke(c, key, value); } catch (Exception e) { e.printStackTrace(); } } public void RootCommand(String cmd) { Process process = null ; DataOutputStream os = null ; DataInputStream is = null ; try { process = Runtime.getRuntime().exec( "su" ); os = new DataOutputStream(process.getOutputStream()); os.writeBytes(cmd + "\n" ); os.writeBytes( "exit\n" ); os.flush(); int aa = process.waitFor(); is = new DataInputStream(process.getInputStream()); byte [] buffer = new byte [is.available()]; is.read(buffer); String out = new String(buffer); } catch (Exception e) { e.printStackTrace(); } finally { try { if (os != null ) { os.close(); } if (is != null ) { is.close(); } process.destroy(); } catch (Exception e) { } } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】