Android 7.0 FallBackHome 、 directBootAware

5,378 阅读3分钟

FallBackHome 、 directBootAware

Android系统将系统中所有已经安装的APP信息都记录在

package-restrictions.xml中,

/data/system/users/0/package-restrictions.xml

  • /system/priv-app 特权app目录主要是底层app,mk文件中设置tag,如setting 、systemUI、TelephonyProvider

  • /system/app  系统app目录 ,主要是三方定制app,如launcher 、Email、Calendar

  • /data/app  普通应用,push  apk至该目录,reboot设备PM会自动扫描安装该目录下的app,正常的用户安装也是把apk文件存储在这个目录下面

framework中pm 下的 Settings.java   writePackageRestrictionsLPr()会对其进行操作

frameworks/base/services/core/java/com/android/server/pm/Settings.java


Android7.0下的DirectBoot模式特点

DirectBoot模式 设备开机后,通电未解锁的状态

存储空间

1.Credential encrypted storage,默认存储数据的地方,仅在用户解锁手机后可用。

2.Device encrypted storage,主要对应的就是Direct Boot使用的存储空间。在Direct Boot模式下和用户解锁手机后都可以使用的存储空间

应用运行

Direct Boot模式下app是无法运行的

要运行的话需要在AndroidManinfest.xml中设置 android:directBootAware="true"

系统把部分系统数据和已经注册了相关权限的Apps的数据保存在device-encrypted store 。其他的数据默认保存到credential-encrypted store。

当手机开机,首先进入一个Dierect Boot的模式,在这个模式下只可以访问device-encrypted store下的数据,无法访问credential-encrypted store下的数据。当用户解锁后就都可以访问了。

一般情况下,应用是无法在Direct Boot模式下运行的

如果需要某个app能够在Direct Boot模式下运行,需要注册相关APP的组件。通常需要在这个模式下运行的app:

  1. 计划通知的应用,例如Clock
  2. 重要的用户通知的应用,例如sms
  3. 提供无障碍服务的应用,例如Talkback
FallBackHome

Android 7.0在启动launcher之前会先启动FallBackHome,FallBackHome是在Setting中的一个Activity(透明Activity),配置了Home属性,Settings的android:directBootAware为true。所有只有FallbackHome可以在direct boot模式下启动。

    <application android:label="@string/settings_label"
            android:icon="@mipmap/ic_launcher_settings"
            ............
            android:directBootAware="true">
 
        <!-- Triggered when user-selected home app isn't encryption aware -->
        <activity android:name=".FallbackHome"
                  android:excludeFromRecents="true"
                  android:theme="@style/FallbackHome">
            <intent-filter android:priority="-1000">
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.HOME" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

FallbackHome中监听ACTION_USER_UNLOCKED广播,用来判断是否已经解锁。如果此时已经解锁,继续执行寻找Home界面,如果没有找到就发延迟消息500ms再找一次,如果找到Launcher就会将FallbackHome finish掉。

public class FallbackHome extends Activity {
    private static final String TAG = "FallbackHome";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Set ourselves totally black before the device is provisioned so that
        // we don't flash the wallpaper before SUW
        if (Settings.Global.getInt(getContentResolver(),
                Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
            setTheme(android.R.style.Theme_Black_NoTitleBar_Fullscreen);
        }

        registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
        maybeFinish();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mReceiver);
    }

    private BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            maybeFinish();
        }
    };

    private void maybeFinish() {
        if (getSystemService(UserManager.class).isUserUnlocked()) {
            final Intent homeIntent = new Intent(Intent.ACTION_MAIN)
                    .addCategory(Intent.CATEGORY_HOME);
            final ResolveInfo homeInfo = getPackageManager().resolveActivity(homeIntent, 0);
            if (Objects.equals(getPackageName(), homeInfo.activityInfo.packageName)) {
                Log.d(TAG, "User unlocked but no home; let's hope someone enables one soon?");
                mHandler.sendEmptyMessageDelayed(0, 500);
            } else {
                Log.d(TAG, "User unlocked and real home found; let's go!");
                finish();
            }
        }
    }

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            maybeFinish();
        }
    };
}

通过pm命令:

pm enable [–user USER_ID] PACKAGE_OR_COMPONENT恢复为激活状态

pm disable [–user USER_ID] PACKAGE_OR_COMPONENT修改为禁用状态

pm list packages -d查看禁用的列表 (返回的package name 的列表)

查package信息(打印出来的是清单文件信息)

dumpsys package 包名


用以下两个值来标示开机向导是否已完成的状态。

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

强制跳过开机向导

adb shell pm disable pkgName
adb shell settings put global device_provisioned 1
adb shell settings put secure user_setup_complete 1