关于Provision.apk

今天遇到一个应用无法打开的问题,跟踪代码发现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。

好复杂!

 

 

 

 


 

 


 

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值