Android 初始化Setup Wizard——Provision

今天說說Provision這個APK,可能很多朋友都不知道有這個APK存在。Provision的作用很簡單,就是一個系統初始化引導程序,原生的Android裏面Provision只做了一件事,就是寫入一個DEVICE_PROVISIONED標記。不過這個標記作用很大,這個標記只會在系統全新升級(雙清)的時候寫入一次,代表了Android系統升級準備完成,可以正常工作。

  之所以會關注DEVICE_PROVISIONED這個標記,是因爲我在升級系統的時候遇到一個問題。系統在不格式化/data/分區的情況下(不進行雙清操作)有可能會導致一個問題,機器的Home鍵按了沒反應。

1、Provision程序

  首先說說一下Provision,Provision在系統源碼packages/apps下面,我們先看看Provision的配置:

複製代碼
    <application>
        <activity android:name="DefaultActivity"
                android:excludeFromRecents="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" />
            </intent-filter>
        </activity>
    </application>
複製代碼

  從上面代碼可以看到兩個比較有意思的地方,第一:Provision配置了category.HOME屬性,做系統開發的朋友應該都瞭解,category.HOME是桌面程序的標記,簡單點說就是Launcher程序纔會配置的標記。

  第二:priority=1,配置了優先級,也就是說它的優先級比我們原生的Launcher優先級還要高,它會在Launcher啓動前就運行起來。

複製代碼

//Edited by mythou
//http://www.cnblogs.com/mythou/

public class DefaultActivity extends Activity 
{
    @Override
    protected void onCreate(Bundle icicle) 
    {
        super.onCreate(icicle);

        // Add a persistent setting to allow other apps to know the device has been provisioned.
        Settings.Secure.putInt(getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 1);

        // remove this activity from the package manager.
        PackageManager pm = getPackageManager();
        ComponentName name = new ComponentName(this, DefaultActivity.class);
        pm.setComponentEnabledSetting(name, PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
            PackageManager.DONT_KILL_APP);

        // terminate the activity.
        finish();
    }
}
複製代碼

上面就是Provision的全部源碼,Provision只有一個Activity,而且做的事情不多。主要做了兩件事:

  • 設置DEVICE_PROVISIONED標記
  • 禁止Provision自己的Activity組件

整個Provision程序只做了這兩件事,DEVICE_PROVISIONED就是我們上面說的系統升級完標記。這個標記是保存在:

保存在settings.db裏面,準確來說是settings.db的secure表裏面。

2、禁止組件

  上面說了Provision其中一個功能,寫入一個標記。除了寫入標記,還有一個禁止本身Activity組件的功能。先簡單介紹一下禁止組件的API。

void setComponentEnabledSetting (ComponentName componentName, int newState, int flags)
  • componentName:組件名稱
  • newState:組件新的狀態,可以設置三個值,分別是如下:
  •   不可用狀態:COMPONENT_ENABLED_STATE_DISABLED
  •   可用狀態:COMPONENT_ENABLED_STATE_ENABLED
  •   默認狀態:COMPONENT_ENABLED_STATE_DEFAULT
  • flags:行爲標籤,值可以是DONT_KILL_APP或者0。 0說明殺死包含該組件的app

禁止組件功能後,系統的package信息會記錄下來,有關係統的package信息都是保存在/data/system/

複製代碼

//Edited by mythou
//http://www.cnblogs.com/mythou/

<package name="com.android.provision" codePath="/system/app/Provision.apk" nativeLibraryPath="/data/data/com.android.provision/lib" 
flags="1" ft="11b7e237e00" it="11b7e237e00" 
ut="11b7e237e00" version="15" userId="10005">
<sigs count="1">
<cert index="1" />
</sigs>
<disabled-components>
<item name="com.android.provision.DefaultActivity" />
</disabled-components>
</package>
複製代碼

  上面就是記錄了package裏面被禁止的組件信息。當然,package.xml裏面還包含了應用包所有信息,這個可以自己看一下。

  這個組件只會運行一次,所以我們如果沒有格式化/data目錄,這個組件就會被禁止。所以會導致一個問題,就是我們的DEVICE_PROVISIONED標記不會再次寫入。

  如果你遇到了機器Home鍵沒有作用,可以檢查一下DEVICE_PROVISIONED標記是否正常。

3、結語

  今天主要是說說原生的Provision作用,其實我們可以在Provision裏面做一些升級後需要完成的事情,比如我們在電阻屏上需要進行座標校準。就可以在Provision裏面首先運行座標校準,因爲它會在Launcher之前運行。

  這問題也查了很久,除了Provision外,還分析了Home鍵的詳細處理機制。後面有空再分析一下Home鍵的處理機制。

Edited by mythou

原創博文,轉載請標明出處:http://www.cnblogs.com/mythou/p/3425570.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章