Google开机向导解析

Google开机向导简介

以下涉及Google开机向导的代码,均来自于反编译自版本227.4976668的SetupWizard.apk。

Launcher

开机向导本质是个Launcher,查看其manifest XML文件可以发现,其MAIN activity声明了category.HOME,且优先级为 5

<activity
    android:directBootAware="true"
    android:excludeFromRecents="true"
    android:immersive="true"
    android:launchMode="singleTask"
    android:lockTaskMode="normal"
    android:name="com.google.android.setupwizard.SetupWizardActivity">
    <intent-filter android:priority="5">
        <action android:name="android.intent.action.MAIN"/>
        <category android:name="android.intent.category.HOME"/>
        <category android:name="android.intent.category.DEFAULT"/>
        ...
    </intent-filter>
</activity>

启动

当AMS准备好之后(systemReady),会调用startHomeActivityLocked()方法启动优先级最高的Launcher应用。当Google开机向导优先级最高时,就会启动com.google.android.setupwizard.SetupWizardActivity

进入Google开机向导后,首先判断系统是否需要进入开机向导,通过以下三个参数的值:

  • Settings$Global.DEVICE_PROVISIONED
  • Settings$Secure.USER_SETUP_COMPLETE
  • System property: ro.setupwizard.mode (默认配置为OPTIONAL)

其中DEVICE_PROVISIONED用来标识是否走完开机向导。
USER_SETUP_COMPLETEro.setupwizard.mode是为多用户系统服务的,所知不多,暂不深入分析。

DEVICE_PROVISIONED为0,表示需要正常进入开机向导流程。

Wizard script

Google开机向导定义了一个wizard script的XML格式,用来描述开机向导的流程,格式如下:

<?xml version="1.0" encoding="utf-8"?>
<WizardScript wizard:version="2"
  xmlns:wizard="http://schemas.android.com/apk/res/com.google.android.setupwizard">
    <WizardAction wizard:uri="intent:#Intent;action=com.android.setupwizard.OEM_PRE_SETUP;end" id="oem_pre_setup" />
    <WizardAction wizard:uri="intent:#Intent;action=com.android.setupwizard.WELCOME;end" id="welcome">
        <result wizard:resultCode="101" wizard:action="check_user_unlock_qr" wizard:name="start_qr_provision" />
        <result wizard:resultCode="111" wizard:action="check_user_unlock_dpm_user_complete" wizard:name="dpm_user_complete" />
        <result wizard:action="check_user_unlock" />
    </WizardAction>
    ...
</WizardScript>

如上,Google开机向导的每一步均以WizardAction标签表示,id作为该步骤的唯一标识,内容可以是intent uri,也可以是另一个script uri;下一步的走向则由result标签决定,根据resultCode的不同,会走到不同的流程。

Google开机向导启动后,需要解析该wizard script,WizardAction标签的内容解析为WizardAction类对象,
所解析出来的这些WizardAction对象存在WizardScript对象的一个列表中:

public class WizardAction implements Parcelable {
    private final WizardBranchArray mBranches;    // 对应"result"标签,继承"SparseArray","resultCode"为key
    private final String mId;   // 对应`id`标签
    private final int mIndex;   // Action列表中的位置
    private final String mScriptUri;    // 所属script uri
    private final String mUri;    // Intent uri
    ...
}

First intent

获取到WizardAction列表之后,需要取出第一个可用的action,新建一个WizardStack对象,将第一个action放到栈顶,并构建相应的intent,跳转到该页面,如此便到了用户可见的第一个页面。

com.google.android.wizardmanager.WizardManager:

private static Intent buildIntent(Context context, Intent originalIntent, WizardStack stack, Callback callback) {
    WizardAction action = stack.peek();   // 获取栈顶的WizardAction
    Intent wizardIntent = action.getIntent();   // 由wizard script中的intent uri转化而来
    if (wizardIntent == null) {
        return null;
    }

    wizardIntent.putExtras(originalIntent);
    // 启动下一个界面时必须传入当前的WizardStack对象引用与当前的WizardAction对象引用
    Bundle args = new Bundle();
    WizardBundleHelper.putParcelableAsByteArray(args, "stack", stack);
    WizardBundleHelper.putParcelableAsByteArray(args, "action", action);
    wizardIntent.putExtra("wizardBundle", args);
    return wizardIntent;
}

Next intent

进入wizard script定义的第一个页面之后,怎么跳转到下一个页面呢?

Google 开机向导通过构建一个action为com.android.wizard.NEXT的nextIntent,并跳转到nextIntent。Android原生提供了帮助类WizardManagerHelper来构建next intent。Next intent中必不可少的参数是wizardBundle,如上代码所示,wizardBundle对应的参数包含了WizardStack对象引用与当前的WizardAction对象引用,如果缺少该参数,Google开机向导将不会执行下一步操作,直接返回,导致流程无法进行下去。而resultCode则用来标识下一步的action,从wizard script示例中可以看到,每个resultCode对应一个id,通过传入resultCode可以指定下一步的action,没有resultCode则执行默认的action。

com.android.setupwizardlib.util.WizardManagerHelper:

public static Intent getNextIntent(Intent originalIntent, int resultCode, Intent data) {
    Intent intent = new Intent("com.android.wizard.NEXT");
    intent.putExtra("wizardBundle", originalIntent.getBundleExtra("wizardBundle"));
    ...
    intent.putExtra("com.android.setupwizard.ResultCode", resultCode);
    ...
    return intent;
}

退出Google开机向导

Google开机向导启动时候做了很多初始化操作,例如调用StatusBarManager.disable()来禁用状态栏,具体可查看com.google.android.setupwizard.lifecycle包下面的一些实现。

相应的,在结束时应当将这些初始化操作复原,这些复原操作都是在退出时进行的。在Google开机向导的wizard script中可以看到最后的action是com.android.setupwizard.EXIT,查看对应的activity com.google.android.setupwizard.SetupWizardExitActivity

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  ...
    FrpHelper.get(this).removeFrpNotification();
    boolean isDeferredSetup = WizardManagerHelper.isDeferredSetupWizard(getIntent());
    ExitHelper.get(this).finishSetup(isDeferredSetup);
    ExitHelper.get(this).launchExitIntent(this, isDeferredSetup);
    ExitHelper.get(this).finishAllAppTasks(this);
}

可以看到,Google开机向导实现了一个工具类ExitHelper处理退出的一些操作。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,194评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,058评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,780评论 0 346
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,388评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,430评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,764评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,907评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,679评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,122评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,459评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,605评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,270评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,867评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,734评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,961评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,297评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,472评论 2 348

推荐阅读更多精彩内容