android 用户空间切换流程

在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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

小程序app封装公用顶部筛选区uv-drop-down

参考ui:DropDown 下拉筛选 | 我的资料管理-uv-ui 是全面兼容vue32、nvue、app、h5、小程序等多端的uni-app生态框架 样式示例&#xff1a; 封装公用文件代码 dropDownTemplete <template><!-- 顶部下拉筛选区封装公用组件 --><view><uv-drop-down ref&…

3 JDK 常见的包和BIO,NIO,AIO

JDK常见的包 java.lang:系统基础类 java.io:文件操作相关类&#xff0c;比如文件操作 java.nio:为了完善io包中的功能&#xff0c;提高io性能而写的一个新包 java.net:网络相关的包 java.util:java辅助类&#xff0c;特别是集合类 java.sql:数据库操作类 IO流 按照流的流向分…

Uniapp 手机基座调试App 打包成Apk文件,并上传到应用商店

1.Uniapp手机基座调试App。 1.1 以下是我另一篇文章 讲解 uniapp连接手机基座调试App、 Hbuildx使用SUB运行到手机基座测试_hbuilder基座-CSDN博客 2.打包本地的uniapp项目为apk文件。 打包的方式有很多种&#xff0c;我们可以选择本地打包和远程云端打包两种方式。 我们在打包…

vue调试工具 Vue.jsDevtools

文件下载 Vue.js Devtools 通过网盘分享的文件&#xff1a;ddebf336f8a44293bd4db9d0f287bc1c.crx 链接: https://pan.baidu.com/s/1uS3a49CwW-B000p5GwUQmQ 提取码: ko89 下载完了 &#xff0c;拖入chrome里&#xff0c;打开详情配置. 打开红框中的开关 重启浏览器&#xff…

数智化时代医院临床试验人才培养的创新路径与实践探索

一、引言 1.1 研究背景与意义 在当今数实化与智能化技术飞速发展的时代&#xff0c;医疗行业正经历着深刻的变革&#xff0c;数智化医院已成为未来发展的重要趋势。临床试验作为药物研发、医疗器械验证以及医疗技术创新的关键环节&#xff0c;对于推动医学进步、提高医疗质量…

产品更新 | 一网联千策:华望M-Cowork平台上的SysML模型协同管理

华望产品更新速递 功能介绍 | 协同平台M-Cowork的强大功能 ◆在线SysML建模与预览 ◆版本控制和基线管理 ◆可追溯的审签流程 ◆全面的系统管理 产品亮点 | 进一步了解协同平台M-Cowork ◆M-Cowork的管理功能 ◆M-Cowork的预览功能 ◆M-Cowork的审签流程 前言 在系统工…

纯相位全息图优化算法综述

◀ 背景引入 ▶ 近年来&#xff0c;得益于光学、电子和计算机等各项技术的进步以及新算法的不断提出&#xff0c;计算全息技术飞速发展。由于现有液晶空间光调制器对于纯相位全息图具有更高的调制能力与衍射效率&#xff0c;纯相位全息图优化算法一直以来都是研究热点。目前&…

Unity复刻胡闹厨房复盘 模块一 新输入系统订阅链与重绑定

本文仅作学习交流&#xff0c;不做任何商业用途 郑重感谢siki老师的汉化教程与代码猴的免费教程以及搬运烤肉的小伙伴 版本&#xff1a;Unity6 模板&#xff1a;3D 核心 渲染管线&#xff1a;URP ------------------------------…

CentOS 7 安装、测试和部署FastDFS

目录 FastDFS环境搭建 安装 libfastcommon 库 安装FastDFS 查看编译后的文件 FastDFS配置 FastDFS启动 启动tracker服务 启动storage服务 查看storage是否已经注册到了tracker下 查看存储文件的目录 FastDFS重启 FastDFS关闭 使用fdfs_test进行测试 修改client.co…

通用导出任何对象列表数据的excel工具类

在工作中经常会遇到列表数据的导出&#xff0c;每次需要的时候都要去开发一次&#xff0c;且数据不断在变化&#xff0c;于是就有了下述的工具类&#xff0c;可传入各种实体对象的List&#xff0c;最终以指定格式导出excel&#xff0c;废话不多说&#xff0c;上代码~ 控制层代…

前端:改变鼠标点击物体的颜色

需求&#xff1a; 需要改变图片中某一物体的颜色&#xff0c;该物体是纯色&#xff1b; 鼠标点击哪个物体&#xff0c;哪个物体的颜色变为指定的颜色&#xff0c;利用canvas实现。 演示案例 代码Demo <!DOCTYPE html> <html lang"en"><head>&l…

AI口播数字人系统快速搭建方法来袭!零经验小白也能学会!

随着AI口播数字人的身影在短视频和直播中的出现频率持续升高&#xff0c;越来越多的创业者都察觉到了AI口播数字人系统所蕴含着的巨大潜在用户规模和广阔收益前景&#xff0c;并打听起了AI口播数字人系统怎么搭建相关的各种消息。 毕竟&#xff0c;根据当前的使用情况来看&…

中小学生心理健康测评系统:精准洞察,助力成长!

随着社会的发展&#xff0c;中小学生的心理健康问题日益受到关注。国家出台了一系列政策&#xff0c;强调要加强学生心理健康教育。然而&#xff0c;在实际的校园环境中&#xff0c;中小学生面临着各种各样的心理挑战&#xff0c;课程增多、难度加大&#xff0c;考试频繁&#…

2024年12月英语六级CET6写作与翻译笔记

目录 1 写作 1.1 大学为学生提供了探索各种可能性 1.2 自律在个人成长中的重要性 1.3 切实可行的目标 2 翻译 2.1 洋山港(Yangshan Port) 2.2 中国航天事业 2.3 北斗卫星导航系统 1 写作 1.1 大学为学生提供了探索各种可能性 1.2 自律在个人成长中的重要性 1.3 切实可…

Unity性能优化 --- 减少OverDraw

OverDraw(过度绘制)就是GPU多次重复绘制同一像素点的操作。在Unity 中渲染的图像由数百万个像素组成&#xff0c;如果这些像素被多次绘制&#xff0c;那么会造成GPU极大的性能损耗。例如下图多个物体叠加放在一起 注&#xff1a;棕色越深的地方&#xff0c;过度绘制的次数越多。…

PostgreSQL 的历史

title: PostgreSQL 的历史 date: 2024/12/23 updated: 2024/12/23 author: cmdragon excerpt: PostgreSQL 是一款功能强大且广泛使用的开源关系型数据库管理系统。其历史可以追溯到1986年,当时由加州大学伯克利分校的一个研究团队开发。文章将深入探讨 PostgreSQL 的起源、…

python学opencv|读取图像(二十一)使用cv2.circle()绘制圆形进阶

【1】引言 前序已经掌握了使用cv2.circle()绘制圆形的基本操作&#xff0c;相关链接为&#xff1a; python学opencv|读取图像&#xff08;二十&#xff09;使用cv2.circle()绘制圆形-CSDN博客 由于圆形本身绘制起来比较简单&#xff0c;因此可以自由操作的空间也就大&#x…

大数据-256 离线数仓 - Atlas 数据仓库元数据管理 正式安装 启动服务访问 Hive血缘关系导入

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; Java篇开始了&#xff01; 目前开始更新 MyBatis&#xff0c;一起深入浅出&#xff01; 目前已经更新到了&#xff1a; Hadoop&#xff0…

保险科技“数智化+”赋能险企高质量发展

文 / 太保科技有限公司人工智能服务事业群资深产品经理 娄昕盛 中国太平洋保险(集团)股份有限公司数智研究院人工智能首席专家 徐国强 中国太平洋保险(集团)股份有限公司数智研究院执行院长 王磊 近年来,保险科技正处在“数字化+”向“数智化+”发展的过渡阶段,…

AI科研助手开发总结:向量与数据权应用(二)

一、前言 继上篇文章&#xff1a;AI科研助手开发总结&#xff1a;向量与数据权限的应用&#xff08;一&#xff09; 本章根据向量库内存储数据及权限&#xff0c;向量库统一维护和管理数据权限方案讨论。 二、方案分析-基于向量Fields 2.1 思路 结合橙语AI科研助手的业务场…