android 用户空间切换流程

news2024/12/26 22:33:59

在Android开发中,创建和切换用户是一个重要的功能,特别是在需要多用户支持的应用中,下面讲述一下用户切换的流程。

一、CarUserManager.java

准备创建新用户,可以减少真正创建用户的时间

 @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
              Manifest.permission.CREATE_USERS})
      public @NonNull UserInfo preCreateUser(@NonNull String userType)
              throws UserOperationException {
         try {
             return mService.preCreateUserWithThrow(userType);
          } catch (ServiceSpecificException e) {
             throw UserOperationException.from(e);
          } catch (RemoteException re) {
              throw re.rethrowFromSystemServer();
         }
      }

用户类型一般有车主、亲情、访客、临时还有一个system空间


51      @AddedIn(PlatformVersion.TIRAMISU_0)
52      public static final @UserIdInt int USER_SYSTEM = UserHandle.USER_SYSTEM;
55      @AddedIn(PlatformVersion.TIRAMISU_0)
56      public static final int FLAG_PRIMARY = UserInfo.FLAG_PRIMARY;
57      @AddedIn(PlatformVersion.TIRAMISU_0)
58      public static final int FLAG_ADMIN = UserInfo.FLAG_ADMIN;
59      @AddedIn(PlatformVersion.TIRAMISU_0)
60      public static final int FLAG_GUEST = UserInfo.FLAG_GUEST;
72      public static final int FLAG_EPHEMERAL = UserInfo.FLAG_EPHEMERAL;

创建用户需要MANAGE_USERS跟Manifest.permission.CREATE_USERS权限,默认是会创建车主或者临时空间

    @Deprecated
674      @AddedInOrBefore(majorVersion = 33, softRemovalVersion = 35, hardRemovalVersion = 37)
675      @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
676              android.Manifest.permission.CREATE_USERS})
677      public AsyncFuture<UserCreationResult> createUser(@Nullable String name,
678              int flags) {
679          AndroidFuture<UserCreationResult> future = new AndroidFuture<>();
680          UserCreationRequest.Builder userCreationRequestBuilder = new UserCreationRequest.Builder();
681          if (name != null) {
682              userCreationRequestBuilder.setName(name);
683          }
684
685          if ((flags & UserManagerHelper.FLAG_ADMIN) == UserManagerHelper.FLAG_ADMIN) {
686              userCreationRequestBuilder.setAdmin();
687          }
688
689          if ((flags & UserManagerHelper.FLAG_EPHEMERAL) == UserManagerHelper.FLAG_EPHEMERAL) {
690              userCreationRequestBuilder.setEphemeral();
691          }
692
693          createUser(userCreationRequestBuilder.build(), Runnable::run, future::complete);
694          return new AndroidAsyncFuture<>(future);
695      }

这里会调用CarUserService的createUser去创建用户

public void createUser(@NonNull UserCreationRequest userCreationRequest,
711              @NonNull @CallbackExecutor Executor executor,
712              @NonNull ResultCallback<UserCreationResult> callback) {
713        ...
742              mService.createUser(userCreationRequest, HAL_TIMEOUT_MS, resultCallbackImpl);
743         ...
751      }

切换用户

 @SystemApi
545      @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
546              android.Manifest.permission.CREATE_USERS})
547      @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0,
548              minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0)
549      public void switchUser(@NonNull UserSwitchRequest userSwitchRequest,
550              @NonNull @CallbackExecutor Executor executor,
551              @NonNull ResultCallback<UserSwitchResult> callback) {
552          int uid = myUid();
553          int targetUserId = userSwitchRequest.getUserHandle().getIdentifier();
571              mService.switchUser(targetUserId, HAL_TIMEOUT_MS, resultCallbackImpl);
572 
580      }

退出用户

  @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
607              android.Manifest.permission.CREATE_USERS})
608      @AddedInOrBefore(majorVersion = 33)
609      public AsyncFuture<UserSwitchResult> logoutUser() {
610          int uid = myUid();
                 ...
629              mService.logoutUser(HAL_TIMEOUT_MS, resultCallbackImpl);
                 ...
638      }

删除用户

   public UserRemovalResult removeUser(@UserIdInt int userId) {
834           ...
836           removeUser(userRemovalRequest, Runnable::run, userRemovalResultCallback);
              ...
853      }

     @SystemApi
781      @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS,
782              android.Manifest.permission.CREATE_USERS})
783      @ApiRequirements(minCarVersion = ApiRequirements.CarVersion.UPSIDE_DOWN_CAKE_0,
784              minPlatformVersion = ApiRequirements.PlatformVersion.TIRAMISU_0)
785      public void removeUser(@NonNull UserRemovalRequest userRemovalRequest,
786              @NonNull @CallbackExecutor Executor executor,
787              @NonNull ResultCallback<UserRemovalResult> callback) {
788              ...
802              mService.removeUser(userRemovalRequest.getUserHandle().getIdentifier(),
803                      resultCallbackImpl);
804               ...
812      }

监听用户切换

 @RequiresPermission(anyOf = {INTERACT_ACROSS_USERS, INTERACT_ACROSS_USERS_FULL})
864      @AddedInOrBefore(majorVersion = 33)
865      public void addListener(@NonNull @CallbackExecutor Executor executor,
866              @NonNull UserLifecycleListener listener) {
867          addListenerInternal(executor, /* filter= */null, listener);
868      }


  public interface UserLifecycleListener {
1486          /**
1487           * Called to notify the given {@code event}.
1488           */1489          @AddedInOrBefore(majorVersion = 33)
1490          void onEvent(@NonNull UserLifecycleEvent event);
1491      }

用户切换返回 UserLifecycleEvent的状态有,可以在返回的各个状态去做对应处理

  /**
1371           * Gets the event type.
1372           *
1373           * @return either {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STARTING},
1374           * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_SWITCHING},
1375           * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKING},
1376           * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_UNLOCKED},
1377           * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPING} or
1378           * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_STOPPED} for all apps;
1379           * for apps {@link CarPackageManager#getTargetCarVersion() targeting car version}
1380           * {@link CarVersion.VERSION_CODES#TIRAMISU_1} or higher, it could be new types
1381           * added on later releases, such as
1382           * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_CREATED},
1383           * {@link CarUserManager#USER_LIFECYCLE_EVENT_TYPE_REMOVED} and possibly others.
1384           *
1385           */
二、CarUserService
  1. 权限检查,每次会判断是否有ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION中的权限,没有权限会直接抛异常,

2875      private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
              UserManagerHelper.FLAG_MANAGED_PROFILE2877             
               | UserManagerHelper.FLAG_PROFILE2878              
               | UserManagerHelper.FLAG_EPHEMERAL2879
               | UserManagerHelper.FLAG_RESTRICTED2880
               | UserManagerHelper.FLAG_GUEST2881              
               | UserManagerHelper.FLAG_DEMO2882              
               | UserManagerHelper.FLAG_FULL;
             
2898      private static void checkManageOrCreateUsersPermission(int creationFlags) {
2899          if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
2900              if (!hasManageOrCreateUsersPermission()) {
2901                  throw new SecurityException("You either need " + MANAGE_USERS + " or "2902                          + CREATE_USERS + "permission to create a user with flags "2903                          + creationFlags);
2904              }
2905          } else if (!hasManageUsersPermission()) {
2906              throw new SecurityException("You need " + MANAGE_USERS + " permission to create a user"
2907                      + " with flags " + creationFlags);
2908          }
2909      }

检查是否是系统应用跟是否有root权限

2911      private static boolean hasManageUsersPermission() {
2912          final int callingUid = Binder.getCallingUid();
2913          return isSameApp(callingUid, Process.SYSTEM_UID)
2914                  || callingUid == Process.ROOT_UID2915 
                      || hasPermissionGranted(MANAGE_USERS, callingUid);
2916      }
  1. 权限满足才会去创建用户,创建空间先生成NewUserResponse请求,里面有用户名、用户类型等,会先调用UserManager去创建用户,拿到UserHandler后会去判断是否支持User HAL,再调用UserHalService去创建用户,创建失败或者异常会调用removeCreatedUser去删除UserManager创建的newUser。

1299      @Override
1300      public void createUser(@NonNull UserCreationRequest userCreationRequest, int timeoutMs,1301              ResultCallbackImpl<UserCreationResult> callback) {
1302          String name = userCreationRequest.getName();
1303          String userType = userCreationRequest.isGuest() ? UserManager.USER_TYPE_FULL_GUEST1304                  : UserManager.USER_TYPE_FULL_SECONDARY;
1305          int flags = 0;
1306          flags |= userCreationRequest.isAdmin() ? UserManagerHelper.FLAG_ADMIN : 0;
1307          flags |= userCreationRequest.isEphemeral() ? UserManagerHelper.FLAG_EPHEMERAL : 0;
1308  
1309          createUser(name, userType, flags, timeoutMs, callback, /* hasCallerRestrictions= */ false);
1310      }
1311  
1381      private void handleCreateUser(@Nullable String name, @NonNull String userType,
1382              int flags, int timeoutMs, @NonNull ResultCallbackImpl<UserCreationResult> callback,
1383              @NonNull UserHandle callingUser, boolean hasCallerRestrictions) {
              //当前是访客没必要切换
1384          if (userType.equals(UserManager.USER_TYPE_FULL_GUEST) && flags != 0) {
1385              // Non-zero flags are not allowed when creating a guest user.
1386              String internalErroMessage = String
1387                      .format(ERROR_TEMPLATE_INVALID_FLAGS_FOR_GUEST_CREATI

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2266053.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git基本操作快速入门(30min)

Git基本操作快速入门&#xff08;30min&#xff09; 文章目录 Git基本操作快速入门&#xff08;30min&#xff09;1. 建立本地仓库2. 本地仓库链接到远端仓库3. 将本地仓库推送到远端4. Git常用命令 作为一名程序员&#xff0c;使用Github来进行代码的版本管理是必修课&#xf…

汽车IVI中控开发入门及进阶(42):OpenVG

概览: OpenVG是一个无版权、跨平台的API,它为高级用户界面和矢量图形库(如SVG)提供了一个低级硬件加速接口。OpenVG主要针对需要便携式加速高质量矢量图形以获得引人注目的用户界面和文本的消费电子产品、手持设备、可穿戴设备和汽车设备,同时使硬件加速能够在非常低的功…

[1111].集成开发工具Pycharm安装与使用

所有博客大纲 后端学习大纲 Python大纲 1.下载&#xff1a; 官方下载地址 2.安装&#xff1a; 1.双击exe文件&#xff0c;然后下一步选择安装目录 2.选择桌面快捷方式及安装&#xff1a; 3.安装完成 3.启动&#xff1a; 4.设置&#xff1a; 4.1.设置运行时环境&#xff1a;…

Windows11 安装 Ubuntu-20.04,同时安装配置 zsh shell,配置 git 别名(alias),大大提高开发效率

背景&#xff1a;家里配置了一台 Windows 电脑&#xff0c;有时候需要用到 vscode 开发测试一些代码&#xff0c;在使用过程中发现原生 windows 敲代码不是很友好&#xff0c;于是想到配置 wsl&#xff0c;安装 Ubuntu&#xff0c;并安装配置 zsh shell&#xff0c;同时配置 gi…

面试场景题系列:设计限流器

首先看看使用API限流器的好处。 •预防由拒绝服务攻击(Denial of Service&#xff0c;DoS)引起的资源耗尽问题。大型科技公司发布的所有API几乎都强制执行某种形式的限流操作。例如&#xff0c;推特限制每个用户每3小时最多发300条推文。谷歌文档API的默认限制是每个用户每60秒…

Node.js 工具:在 Windows 11 中配置 Node.js 的详细步骤

一、概述 记录时间 [2024-12-25] 本文讲述如何在 Windows 11 中进行 Node.js 工具的安装和配置。 以下是详细的步骤和说明。 二、安装 Node.js 1. 官网下载 通过官网&#xff0c;下载 Node.js&#xff0c;上面有好几种下载方式&#xff0c;文中下载的是 zip 压缩包。 如图&…

DevOps实战:用Kubernetes和Argo打造自动化CI/CD流程(2)

DevOps实战&#xff1a;用Kubernetes和Argo打造自动化CI/CD流程&#xff08;2&#xff09; 背景 架构图 正片开始之前&#xff0c;请一定先熟悉上面的架构图&#xff0c;跟着我的步骤&#xff0c;一步一步执行成功&#xff0c;相信后续根据自己特定的需求定制CI/CD。 需求 …

【Java 学习】详细讲解---包和导包、Scanner类、输入源

1. 包 1.1 什么是包&#xff1f; 举个例子&#xff0c;你和你的同学有不同的家庭&#xff0c;你们都有自己的爸爸妈妈&#xff0c;都有自己的家。在自己的家中你们可以按照自己爱好摆放东西&#xff0c;都互不干扰。但是&#xff0c;假如你们的家都在一起&#xff0c;你们就不…

EasyExcel停更,FastExcel接力

11月6日消息&#xff0c;阿里巴巴旗下的Java Excel工具库EasyExcel近日宣布&#xff0c;将停止更新&#xff0c;未来将逐步进入维护模式&#xff0c;将继续修复Bug&#xff0c;但不再主动新增功能。 EasyExcel以其快速、简洁和解决大文件内存溢出的能力而著称&#xff0c;官方…

Python PDF批量加密工具

Python PDF批量加密工具 1.简介&#xff1a; ‌一个Python写的PDF批量加密工具。PDF批量加密‌是一种保护PDF文件安全性的方法&#xff0c;通过为多个PDF文件设置相同的密码&#xff0c;防止未经授权的用户访问这些文件。批量加密可以大大提高工作效率&#xff0c;特别是在处…

项目2路由交换

背景 某学校为满足日常教学生活需求&#xff0c;推动数字校园的建设&#xff0c;学校有办公楼和学生宿舍楼和服务器集群三块区域&#xff0c;请合理规划IP地址和VLAN&#xff0c;实现企业内部能够互联互通现要求外网能通过公网地址访问服务器集群&#xff0c;学生和老师能正常…

知识梳理笔记--Kerberos 协议

Kerberos 协议概述 Kerberos 是一种计算机网络认证协议&#xff0c;旨在为不安全的网络提供强认证服务。它通过中心化的身份验证系统&#xff08;即 Key Distribution Center&#xff0c;KDC&#xff09;来确保通信双方的身份验证和数据加密。Kerberos 协议主要用于确保计算机系…

9个用于测试自动化的最佳AI测试工具(2024)

选择一款优质的基于生成式AI人工智能的测试工具能够确保测试过程的准确性和效率&#xff0c;从而加速整个软件测试周期。相反&#xff0c;设计不佳的测试工具可能无法发现错误&#xff0c;并可能存在安全问题。它们可能产生误报或漏报&#xff0c;误导开发与测试团队&#xff0…

uni-app 跨端开发精美开源UI框架推荐

&#x1f380;&#x1f380;&#x1f380;uni-app 跨端开发系列 &#x1f380;&#x1f380;&#x1f380; 一、uni-app 组成和跨端原理 二、uni-app 各端差异注意事项 三、uni-app 离线本地存储方案 四、uni-app UI库、框架、组件选型指南 五、uni-app 蓝牙开发 六、uni-app …

【1224】数据结构(sizeof/数组的长度定义/读取字符串函数/线性表长度/左值右值/静态变量/指针与引用)

1.对一维整型数组a的正确说明是 #define SIZE 10 (换行) int a[SIZE];说法是否正确&#xff1f; 正确 数组的SIZE可以用宏定义&#xff0c;但不能用变量 2.如有定义&#xff1a;char str[20];&#xff0c;能将从键盘输入的字符串“How are you”保存到 str 数组的语句是&#x…

强化特种作业管理,筑牢安全生产防线

在各类生产经营活动中&#xff0c;特种作业由于其操作的特殊性和高风险性&#xff0c;一直是安全生产管理的重点领域。有效的特种作业管理体系涵盖多个关键方面&#xff0c;从作业人员的资质把控到安全设施的配备维护&#xff0c;再到特种设备的精细管理以及作业流程的严格规范…

(六)循环神经网络_基本的RNN

一、提出背景 前馈神经网络不考虑数据之间的关联性&#xff0c;网络的输出只和当前时刻网络的输入相关。然而&#xff0c;现实问题中存在着很多序列型的数据&#xff08;文本、语音以及视频等&#xff09;。 例如&#xff1a;室外的温度是随着气候的变化而周期性的变化的&…

Dockerfile的用法

Dockerfile的用法 示例 `Dockerfile`使用 `Dockerfile` 创建 Docker 镜像`Dockerfile` 指令详解其他常用指令总结Dockerfile 是一个文本文件,包含了用于创建 Docker 镜像的一系列指令。这些指令描述了镜像的基础、所安装的软件、文件的复制、环境变量的设置以及其他配置。下面…

60.基于SSM的个人网站的设计与实现(项目 + 论文)

项目介绍 本站是一个B/S模式系统&#xff0c;个人网站是在MySQL中建立数据表保存信息&#xff0c;运用SSMVue框架和Java语言编写。并按照软件设计开发流程进行设计实现充分保证系统的稳定性。系统具有界面清晰、操作简单&#xff0c;功能齐全的特点&#xff0c;使得基于SSM的网…

B端UI设计规范是什么?

一、B端UI设计规范是什么&#xff1f; B端UI设计规范是一套针对企业级应用界面设计的全面规则和标准&#xff0c;旨在确保产品界面的一致性、可用性和用户体验。 二、B端UI设计规范要素说明 B端UI设计的基本要素包括设计原则、主题、布局、颜色、字体、图标、按钮和控件、交互…