Android多用户原理及流程分析

本文详细分析了Android系统的多用户切换流程,从创建用户、切换用户、启动用户到解锁用户,揭示了其中涉及的AMS、PMS、WMS等关键组件的工作原理。在流程中,多处加锁保证数据安全,且发现应用层注册的binder接口可能影响切换效率。解决方案建议采用监听多用户广播的方式来实现异步回调,确保系统的流畅运行。
摘要由CSDN通过智能技术生成

一、 问题描述

ActivityManager.getService().registerUserSwitchObserver这个API的回调是一个阻塞式接口,也就是说框架那边遍历注册的observer,依次回调,每个observer执行完后框架才会回调下一个,直到全部执行结束,才会以安全的状态切换多用户。

当任意一处回调出现了耗时严重、卡顿、ANR问题甚至超时,都会严重影响系统切换多用户的过程。


二、 流程分析

2.1 基本概念

多用户相关逻辑,由AMS委派给UserController类控制:

// 注册的IUserSwitchObserver接口保存在其中
private final RemoteCallbackList<IUserSwitchObserver> mUserSwitchObservers
        = new RemoteCallbackList<>();

UserController(Injector injector) {
   
    mInjector = injector;
    // 回调所使用的Handler在构造方法中赋值
    mHandler = mInjector.getHandler(this);
    mUiHandler = mInjector.getUiHandler(this);
    // User 0 is the first and only user that runs at boot.
    final UserState uss = new UserState(UserHandle.SYSTEM);
    // ...
}

/**
 * 这四个dispatch方法分别对应UserSwitchObserver的四个回调方法
 */
public boolean handleMessage(Message msg) {
   
    switch (msg.what) {
   
        case REPORT_USER_SWITCH_MSG:
            dispatchUserSwitch((UserState) msg.obj, msg.arg1, msg.arg2);
            break;
        case FOREGROUND_PROFILE_CHANGED_MSG:
            dispatchForegroundProfileChanged(msg.arg1);
            break;
        case REPORT_USER_SWITCH_COMPLETE_MSG:
            dispatchUserSwitchComplete(msg.arg1);
            break;
        case REPORT_LOCKED_BOOT_COMPLETE_MSG:
            dispatchLockedBootComplete(msg.arg1);
            break;
        // ...
    }
}

RemoteCallbackList由名字可知是跟binder相关:

// 保存的应用层注册的binder回调
public class RemoteCallbackList<E extends IInterface> {
   
    /*package*/ ArrayMap<IBinder, Callback> mCallbacks
            = new ArrayMap<IBinder, Callback>();
}

InjectorUserController的内部类:

static class Injector {
   
    private final ActivityManagerService mService;
    private UserManagerService mUserManager;
    private UserManagerInternal mUserManagerInternal;

    Injector(ActivityManagerService service) {
   
        mService = service;
    }

    protected Handler getHandler(Handler.Callback callback) {
   
        return new Handler(mService.mHandlerThread.getLooper(), callback);
    }

    protected Handler getUiHandler(Handler.Callback callback) {
   
        return new Handler(mService.mUiHandler.getLooper(), callback);
    }
}

mService.mHandlerThread是AMS中用于执行业务的子线程:

public ActivityManagerService(Context systemContext, ActivityTaskManagerService atm) {
   
    mInjector = new Injector();
    mHandlerThread = new ServiceThread(TAG,
            THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
    mHandlerThread.start();
    mHandler = new MainHandler(mHandlerThread.getLooper());
    mUiHandler = mInjector.getUiHandler(this);
    // ...
}

下面分析多用户切换整个过程,以首次创建子用户为例。


2.2 创建用户

选择新建子用户时,执行UserManager#createUser,在UserManagerService中经过权限校验,最后调用到了createUserInternalUnchecked方法:

private UserInfo createUserInternalUnchecked(...) {
   
    // ...
    // 分配UserId,从10开始
    userId = getNextAvailableId();
    // 以UserId为文件夹名创建子用户的系统数据根目录
    Environment.getUserSystemDirectory(userId).mkdirs();
    // ...
    // 写入用户配置文件数据
    writeUserLP(userData);
    writeUserListLP();
    // ...
    // 创建用户密钥
    final StorageManager storage = mContext.getSystemService(StorageManager
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值