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

    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"

        <!-- 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

android:excludeFromRecents="true"	

在 Android 系统中,如果我们不想某个 Activity 出现在 “Recent screens” 中,可以设置这条属性:

2.3.packages\apps\Settings\src\com\android\settings\HomeSettings.java

    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  

    
    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();

    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.客户应用

罒.应用在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) {
			}
		}
	}
}

  

  

  

  

  

posted @ 2020-08-04 22:32  CrushGirl  阅读(802)  评论(0编辑  收藏  举报