关于Provision.apk

来源:互联网 发布:淘宝订单管理系统介绍 编辑:程序博客网 时间:2024/06/07 16:58

今天遇到一个应用无法打开的问题,跟踪代码发现app在onCreate的时候会检查

inKeyguardRestrictedInputMode() 这是KeyguardManager的方法

解释为:

    /**     * If keyguard screen is showing or in restricted key input mode (i.e. in     * keyguard password emergency screen). When in such mode, certain keys,     * such as the Home key and the right soft keys, don't work.     *     * @return true if in keyguard restricted input mode.     *     * @see android.view.WindowManagerPolicy#inKeyguardRestrictedKeyInputMode     */    public boolean inKeyguardRestrictedInputMode() {        try {            return mWM.inKeyguardRestrictedInputMode();        } catch (RemoteException ex) {            return false;        }    }


进一步追踪到:

    /**     * Given the state of the keyguard, is the input restricted?     * Input is restricted when the keyguard is showing, or when the keyguard     * was suppressed by an app that disabled the keyguard or we haven't been provisioned yet.     */    public boolean isInputRestricted() {        return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned();    }


发现最终决定于mUpdateMonitor.isDeviceProvisioned,再追:

    /**     * @return Whether the device is provisioned (whether they have gone through     *   the setup wizard)     */    public boolean isDeviceProvisioned() {        return mDeviceProvisioned;    }


那mDeviceProvisioned是怎么来的呢,再查:

    private boolean isDeviceProvisionedInSettingsDb() {        return Settings.Global.getInt(mContext.getContentResolver(),                Settings.Global.DEVICE_PROVISIONED, 0) != 0;    }

ok, 是读的数据库里面的Settings.Global.DEVICE_PROVISIONED 字段,那是谁会去改写这个呢,终于在Provision里面找到了:

Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);

看来只要Provision运行过了,这个字段就可以正确,最终发现果然是这个apk没有运行。

 

以前没怎么关注过这个apk,顿时来了兴趣。

 

看看他的Manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"        package="com.android.provision">    <original-package android:name="com.android.provision" />    <!-- For miscellaneous settings -->    <uses-permission android:name="android.permission.WRITE_SETTINGS" />    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />    <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></manifest>

居然是category.HOME, 换句话说它是个launcher,而且android:priority="1" ,那他应该会是我们常见的launcher才对啊,不过它没有UI,奇怪了。

再看看代码。

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.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);         Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 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();    }   }


原来它除了写Settings.Global.DEVICE_PROVISIONED 和Settings.Secure.USER_SETUP_COMPLETE 之外还会把 自己COMPONENT_ENABLED_STATE_DISABLED,

看来确实是系统启动之后先调的它,但是它把自己disable了,我们常见的launcher才会机会起来,ok,我猜是这样的。

那luncher是怎么起来的呢?貌似要去看framework了。let’s go!

找到了 ActivityManagerService里面有个startHomeActivityLocked,应该是它干的,至于为什么就比较复杂了,有机会详细追下。

其中我关注的代码;

 Intent intent = getHomeIntent();        ActivityInfo aInfo =            resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);

resolveActivityInfo 会根据intent返回一个ActivityInfo,就知道要启动哪个了。怎么resolve?

PackageManagerService给出了:

    public ResolveInfo resolveIntent(Intent intent, String resolvedType,            int flags, int userId) {        if (!sUserManager.exists(userId)) return null;        enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "resolve intent");        List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId);        return chooseBestActivity(intent, resolvedType, flags, query, userId);    }


queryIntentActivities 然后  chooseBestActivity , ok 明显了, 在Provision没有disable的时候,choose的就是它,要是disable了才轮到真正的launcher。

好复杂!

 

 

 

 


 

 


 

 

 

 

 

 

0 0
原创粉丝点击