Android Framework-FallbackHome和Provision

852 阅读3分钟

android 在开机启动后的代码里 ,并不会直接启动Launcher页面,而是会判断经过开机引导和FallbackHome

简单理解 开机引导>FallbackHome>Launcher

//services/core/java/com/android/server/wm/RootWindowContainer.javastartHomeOnTaskDisplayArea() {
  //省略。。。
  
        Intent homeIntent = null;
        ActivityInfo aInfo = null;
        if (taskDisplayArea == getDefaultTaskDisplayArea()) {
            homeIntent = mService.getHomeIntent();
            aInfo = resolveHomeActivity(userId, homeIntent);
        } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {
            Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea);
            aInfo = info.first;
            homeIntent = info.second;
        }
        homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
        homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
       //省略..
        mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
                taskDisplayArea);
}
  

开机向导

在android 12 下 是 在 packages/apps/Provision 下,新买手机后 一步步设置的界面。

public class DefaultActivity extends Activity {
​
   private void finishSetup() {
        setProvisioningState();//设置引导完成标志
        disableSelfAndFinish();//关闭自己
    }
  
  
   private void disableSelfAndFinish() {
     
        PackageManager pm = getPackageManager();
        ComponentName name = new ComponentName(this, DefaultActivity.class);
       
        pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.DONT_KILL_APP);
       
        finish();
    }
  
}
<application>
        <activity android:name="DefaultActivity"
             android:excludeFromRecents="true"
             android:exported="true">
            <intent-filter android:priority="1">
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.HOME"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.SETUP_WIZARD"/>
            </intent-filter>
        </activity>

FallbackHome

Android N 以后 增加的一个页面,在当设备已开机但用户尚未解锁设备时,就会显示FallbackHome

public class FallbackHome extends Activity {
  
   protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mReceiver);
        if (!mFinished) {
           
            finishFallbackHome();
        }
    }
  
  //创建的时候做了监听 监听解锁
   protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
    registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
   }
 
  
  //接收消息发送,再次递归调用maybeFinish
  private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            maybeFinish();
        }
    };
  
   private void maybeFinish() {
       //检查是否已经解锁
        if (getSystemService(UserManager.class).isUserUnlocked()) {
           //判断是否能够响应lanucher
            final Intent homeIntent = new Intent(Intent.ACTION_MAIN)
                    .addCategory(Intent.CATEGORY_HOME);
            final ResolveInfo homeInfo = getPackageManager().resolveActivity(homeIntent, 0);
            if (Objects.equals(getPackageName(), homeInfo.activityInfo.packageName)) {
                //如果是当前包名也就是 FallbackHome 那么就延迟500ms 看看lauchner起来了么
                mHandler.sendEmptyMessageDelayed(0, 500);
            } else {
                
                getSystemService(PowerManager.class).userActivity(
                        SystemClock.uptimeMillis(), false);
                finish();
            }
        }
    }
​
  
     //关闭自己 并从堆栈移除
      private void finishFallbackHome() {
        getSystemService(PowerManager.class).userActivity(SystemClock.uptimeMillis(), false);
        finishAndRemoveTask();
        mFinished = true;
    }
}
   <activity android:name=".FallbackHome"
                  android:excludeFromRecents="true"
                  android:label=""
                  android:screenOrientation="nosensor"
                  android:taskAffinity="com.android.settings.FallbackHome"
                  android:exported="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>

Launcher

 <activity
            android:name="com.android.launcher3.Launcher"
            android:launchMode="singleTask"
            android:clearTaskOnLaunch="true"
            android:stateNotNeeded="true"
            android:windowSoftInputMode="adjustPan"
            android:screenOrientation="unspecified"
            android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|density"
            android:resizeableActivity="true"
            android:resumeWhilePausing="true"
            android:taskAffinity=""
            android:exported="true"
            android:enabled="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.MONKEY"/>
                <category android:name="android.intent.category.LAUNCHER_APP" />
            </intent-filter>
            <meta-data
                android:name="com.android.launcher3.grid.control"
                android:value="${packageName}.grid_control" />
        </activity>

下面是我个人的理解,三者都做了符合android.intent.action.MAINandroid.intent.category.HOME匹配规则,而Provisionpriority为1 ,FallbackHome-900.Launcher 未设置。正常情况下是 Provision -> Launcher->FallbackHome。但是启动的顺序和这个关系不大。但是也确保了万一基于广播的启动顺序。

但是 在FallbackHomeProvision的xml里 设置了 android:excludeFromRecents="true"

该属性可以让页面在直启模式下运行。在解锁之前就可以启动了 FallbackHome但是在启动后,优先级就会远远低于Launcher

Provision在完成后会设置 调用 finishSetup() ,完成设置向导,避免再次启动,调用disableSelfAndFinish()PackageManager 中移除自己,并关闭。

FallbackHome 构建后,监听解锁,触发解锁后,会进入maybeFinish(),进行判断Laucher3是否已经启动,符合条件后 调用关闭自己,如果不符合条件 则继续等待500ms后再次查询是否符合条件。

简单的理解,Provision负责处理设备的初始配置和系统初始化,这些操作对于设备的安全性和功能性至关重要,需要在用户界面呈现之前完成。一旦 Provision 的任务完成,系统才会继续启动流程,包括 FallbackHome 和其他用户可见的应用和服务。

FallbackHome可以在直启动模式下 启动,在该模式下匹配到的就是自己,是一个简单的展示页面,主要用来过度 启动和Launcher的过程和失败页面。FallbackHomeATMSsystemReady()里面会调用startHomeActivityLocked()。这里回去匹配符合getHomeIntent()标准的页面。在最初能匹配到的是FallbackHome,在FallbackHome不断轮训监听的过程中,查看是否已经解锁,在发现已经解锁后,关闭自己,这会才真正的拉起Launcher

FallbackHome请求finish()自己,当然会请求执行onPasue()方法: ActivityManagerService.activityPaused() ,

-->ActivityStack.activityPausedLocked(),

-->ActivityStack.completePauseLocked(),

—-> ActivityStack.finishCurrentActivityLocked(),

-->ActivityStackSupervisor.resumeFocusedStackTopActivityLocked(),

最后调用到了ActivityManagerService.startHomeActivityLocked()

再次查询就启动了Launcher