今天說說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