当前位置: 首页 > news >正文

Android DPC模式多开 APP

1、修改创建多个profile时超出限制

packages/apps/ManagedProvisioning/src/com/android/managedprovisioning/preprovisioning/PreProvisioningController.java

// PO preconditions
if (isProfileOwnerProvisioning()) {// If there is already a managed profile, first check it may be removed.// If so, setup the profile deletion dialog.int existingManagedProfileUserId = mUtils.alreadyHasManagedProfile(mContext);if (existingManagedProfileUserId > mUserManager.getMaxSupportedUsers()) { // 修改支持多个if (isRemovingManagedProfileDisallowed()) {mUi.showErrorAndClose(R.string.cant_replace_or_remove_work_profile,R.string.work_profile_cant_be_added_contact_admin,"Cannot remove existing work profile");} else {ComponentName mdmPackageName = mDevicePolicyManager.getProfileOwnerAsUser(existingManagedProfileUserId);String domainName = mDevicePolicyManager.getProfileOwnerNameAsUser(existingManagedProfileUserId);mUi.showDeleteManagedProfileDialog(mdmPackageName, domainName,existingManagedProfileUserId);}return;}
}

2、修改创建profile的任务:

packages/apps/ManagedProvisioning/src/com/android/managedprovisioning/provisioning/ProfileOwnerProvisioningController.java

private void setUpTasksManagedProfile() {if(Utils.alreadyHasManagedProfile() == -1) {addTasks(new CreateManagedProfileTask(mContext, mParams, this),new InstallExistingPackageTask(mParams.inferDeviceAdminPackageName(), mContext,mParams, this),new SetDevicePolicyTask(mContext, mParams, this),new ManagedProfileSettingsTask(mContext, mParams, this),new DisableInstallShortcutListenersTask(mContext, mParams, this),new StartManagedProfileTask(mContext, mParams, this),new CopyAccountToUserTask(mParentUserId, mContext, mParams, this));}else {addTasks(new CreateManagedProfileTask(mContext, mParams, this),new ManagedProfileSettingsTask(mContext, mParams, this),new DisableInstallShortcutListenersTask(mContext, mParams, this),new StartManagedProfileTask(mContext, mParams, this),new CopyAccountToUserTask(mParentUserId, mContext, mParams, this));}}

修改 markUserProvisioningStateInitiallyDone

packages/apps/ManagedProvisioning/src/com/android/managedprovisioning/finalization/UserProvisioningStateHelper.java

if (params.provisioningAction.equals(ACTION_PROVISION_MANAGED_PROFILE)) {// Managed profiles are a special case as two users are involved.managedProfileUserId = mUtils.getLastManagedProfile(mContext).getIdentifier();  // 这里改成 getLastManagedProfileif (userSetupCompleted) {// SUW on current user is complete, so nothing much to do beyond indicating we're// all done.newProfileState = STATE_USER_SETUP_FINALIZED;} else {// We're still in SUW, so indicate that a managed-profile was setup on current user,// and that we're awaiting finalization on both.newState = STATE_USER_PROFILE_COMPLETE;newProfileState = STATE_USER_SETUP_COMPLETE;}}
// 新增如下:public UserHandle getLastManagedProfile(Context context) {UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);int currentUserId = userManager.getUserHandle();UserInfo tmp;List<UserInfo> userProfiles = userManager.getProfiles(currentUserId);for (UserInfo profile : userProfiles) {if (profile.isManagedProfile()) {tmp = profile;}}if(tmp != null) return new UserHandle(tmp.id);return null;}

3、修改 mUserManager.getMaxSupportedUsers

frameworks/base/core/java/android/os/UserManager.java

@UnsupportedAppUsage
public static int getMaxSupportedUsers() {// Don't allow multiple users on certain buildsreturn 100;// if (android.os.Build.ID.startsWith("JVP")) return 1;// return SystemProperties.getInt("fw.max_users",//         Resources.getSystem().getInteger(R.integer.config_multiuserMaximumUsers));
}

4、修改 UserManagerService canAddMoreProfilesToUser  getMaxUsersOfTypePerParent

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

@VisibleForTesting
int getMaxUsersOfTypePerParent(String userType) {return UserManager.getMaxSupportedUsers();// final UserTypeDetails type = mUserTypes.get(userType);// if (type == null) {//     return 0;// }// return getMaxUsersOfTypePerParent(type);
}private static int getMaxUsersOfTypePerParent(UserTypeDetails userTypeDetails) {return UserManager.getMaxSupportedUsers();// final int defaultMax = userTypeDetails.getMaxAllowedPerParent();// if (!Build.IS_DEBUGGABLE) {//     return defaultMax;// } else {//     if (userTypeDetails.isManagedProfile()) {//         return SystemProperties.getInt("persist.sys.max_profiles", defaultMax);//     }// }// return defaultMax;
}

5、修改 Settings createNewUserLI :  

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

for (int i = 0; i < packagesCount; i++) {PackageSetting ps = packagesIterator.next();if (ps.pkg == null) {continue;}final boolean shouldMaybeInstall = ps.isSystem() &&!ArrayUtils.contains(disallowedPackages, ps.name) &&!ps.getPkgState().isHiddenUntilInstalled();final boolean shouldReallyInstall = (shouldMaybeInstall &&(skipPackageWhitelist || userTypeInstallablePackages.contains(ps.name))) || InExcludeList(ps.name); //设置要安装的包名列表// Only system apps are initially installed.ps.setInstalled(shouldReallyInstall, userHandle);// If userTypeInstallablePackages is the *only* reason why we're not installing,// then uninstallReason is USER_TYPE. If there's a different reason, or if we// actually are installing, put UNKNOWN.final int uninstallReason = (shouldMaybeInstall && !shouldReallyInstall) ?UNINSTALL_REASON_USER_TYPE : UNINSTALL_REASON_UNKNOWN;ps.setUninstallReason(uninstallReason, userHandle);if (!shouldReallyInstall) {writeKernelMappingLPr(ps);}

6、修改 setProfileEnabled 和 setUserProvisioningState:

frameworks/base/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java

@Override
public void setProfileEnabled(ComponentName who) {if (!mHasFeature) {return;}Objects.requireNonNull(who, "ComponentName is null");synchronized (getLockObject()) {// Check if this is the profile owner who is callinggetActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);final int userId = UserHandle.getCallingUserId();enforceManagedProfile(userId, "enable the profile");// Check if the profile is already enabled.// UserInfo managedProfile = getUserInfo(userId);// if (managedProfile.isEnabled()) {//     Slog.e(LOG_TAG,//             "setProfileEnabled is called when the profile is already enabled");//     return;// }for (UserInfo userInfo : mUserManager.getProfiles(callingUserId)) {if (!userInfo.isEnabled()) {mInjector.binderWithCleanCallingIdentity(() -> {int identifier = userInfo.id;mUserManager.setUserEnabled(identifier);UserInfo parent = mUserManager.getProfileParent(identifier);Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);intent.putExtra(Intent.EXTRA_USER, new UserHandle(identifier));UserHandle parentHandle = new UserHandle(parent.id);mLocalService.broadcastIntentToCrossProfileManifestReceiversAsUser(intent,parentHandle, /* requiresPermission= */ true);intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |Intent.FLAG_RECEIVER_FOREGROUND);mContext.sendBroadcastAsUser(intent, parentHandle);});}}}
}@Override
public void setUserProvisioningState(int newState, int userHandle) {if (!mHasFeature) {return;}if (userHandle != mOwners.getDeviceOwnerUserId() && !mOwners.hasProfileOwner(userHandle)&& getManagedUserId(userHandle) == -1) {// No managed device, user or profile, so setting provisioning state makes no sense.throw new IllegalStateException("Not allowed to change provisioning state unless a "+ "device or profile owner is set.");}synchronized (getLockObject()) {boolean transitionCheckNeeded = false; //改为false不检查// Calling identity/permission checks.if (isAdb()) {// ADB shell can only move directly from un-managed to finalized as part of directly// setting profile-owner or device-owner.if (getUserProvisioningState(userHandle) !=DevicePolicyManager.STATE_USER_UNMANAGED|| newState != DevicePolicyManager.STATE_USER_SETUP_FINALIZED) {throw new IllegalStateException("Not allowed to change provisioning state "+ "unless current provisioning state is unmanaged, and new state is "+ "finalized.");}transitionCheckNeeded = false;} else {// For all other cases, caller must have MANAGE_PROFILE_AND_DEVICE_OWNERS.enforceCanManageProfileAndDeviceOwners();}final DevicePolicyData policyData = getUserData(userHandle);if (transitionCheckNeeded) {// Optional state transition check for non-ADB case.checkUserProvisioningStateTransition(policyData.mUserProvisioningState, newState);}policyData.mUserProvisioningState = newState;saveSettingsLocked(userHandle);}
}

7、 删除不需要的APP

默认情况下创建完用户会安装 Contacts 、 Files 等APP,其定义在:

frameworks/base/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java

getNonRequiredApps

@NonNull
public Set<String> getNonRequiredApps(@NonNull ComponentName admin, int userId,@NonNull String provisioningAction) {final Set<String> nonRequiredApps = getLaunchableApps(userId);// Newly installed system apps are uninstalled when they are not required and are either// disallowed or have a launcher icon.//nonRequiredApps.removeAll(getRequiredApps(provisioningAction, admin.getPackageName())); //将需要的APP删除,即安装这些需要的APP,注释即不安装nonRequiredApps.removeAll(getSystemInputMethods(userId));                               //默认安装输入法nonRequiredApps.addAll(getDisallowedApps(provisioningAction));return nonRequiredApps;
}private Set<String> getRequiredApps(String provisioningAction, String dpcPackageName) {final Set<String> requiredApps = new ArraySet<>();requiredApps.addAll(getRequiredAppsSet(provisioningAction));requiredApps.addAll(getVendorRequiredAppsSet(provisioningAction));requiredApps.add(dpcPackageName);return requiredApps;
}private Set<String> getRequiredAppsSet(String provisioningAction) {final int resId;switch (provisioningAction) {case ACTION_PROVISION_MANAGED_USER:resId = R.array.required_apps_managed_user;break;case ACTION_PROVISION_MANAGED_PROFILE:resId = R.array.required_apps_managed_profile;break;case ACTION_PROVISION_MANAGED_DEVICE:resId = R.array.required_apps_managed_device;break;default:throw new IllegalArgumentException("Provisioning type "+ provisioningAction + " not supported.");}return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId)));
}private Set<String> getVendorRequiredAppsSet(String provisioningAction) {final int resId;switch (provisioningAction) {case ACTION_PROVISION_MANAGED_USER:resId = R.array.vendor_required_apps_managed_user;break;case ACTION_PROVISION_MANAGED_PROFILE:resId = R.array.vendor_required_apps_managed_profile;break;case ACTION_PROVISION_MANAGED_DEVICE:resId = R.array.vendor_required_apps_managed_device;break;default:throw new IllegalArgumentException("Provisioning type "+ provisioningAction + " not supported.");}return new ArraySet<>(Arrays.asList(mContext.getResources().getStringArray(resId)));
}

上述默认需安装的APP定义如下:

frameworks/base/core/res/res/values/required_apps_managed_profile.xml

<resources><!-- A list of apps to be retained in the managed profile.Takes precedence over the disallowed apps lists. --><string-array translatable="false" name="required_apps_managed_profile"><item>com.android.contacts</item><item>com.android.settings</item><item>com.android.providers.downloads</item><item>com.android.providers.downloads.ui</item><item>com.android.documentsui</item></string-array>
</resources>

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 力扣(leetcode)每日一题 1184 公交站间的距离
  • 为什么Node.js不适合CPU密集型应用?
  • 算法打卡:第十章 单调栈part01
  • 通过adb命令打开手机usb调试
  • Android Studio新建工程(Java语言环境)
  • 【建设方案】固定资产信息系统建设方案(功能清单列表2024word原件)
  • 9.12 TFTP通信
  • Leetcode面试经典150题-138.随机链表的复制
  • 构建“零工市场小程序”,服务灵活就业“大民生”
  • 2025年最新大数据毕业设计选题-基于Hive分析相关
  • 34.贪心算法1
  • STP 笔记
  • Village Exteriors Kit 中世纪乡村房屋场景模型
  • 【MySQL】MySQL中JDBC编程——MySQL驱动包安装——(超详解)
  • 探索人工智能的未来趋势
  • (三)从jvm层面了解线程的启动和停止
  • Android单元测试 - 几个重要问题
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • CentOS6 编译安装 redis-3.2.3
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • oldjun 检测网站的经验
  • SQLServer之索引简介
  • webgl (原生)基础入门指南【一】
  • 安装python包到指定虚拟环境
  • 翻译--Thinking in React
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 开源地图数据可视化库——mapnik
  • -- 数据结构 顺序表 --Java
  • 王永庆:技术创新改变教育未来
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • ​马来语翻译中文去哪比较好?
  • #!/usr/bin/python与#!/usr/bin/env python的区别
  • $(this) 和 this 关键字在 jQuery 中有何不同?
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (分布式缓存)Redis哨兵
  • (分类)KNN算法- 参数调优
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (牛客腾讯思维编程题)编码编码分组打印下标题目分析
  • (算法设计与分析)第一章算法概述-习题
  • (详细文档!)javaswing图书管理系统+mysql数据库
  • (转)Linux整合apache和tomcat构建Web服务器
  • .NET 5种线程安全集合
  • .NET Core日志内容详解,详解不同日志级别的区别和有关日志记录的实用工具和第三方库详解与示例
  • .net/c# memcached 获取所有缓存键(keys)
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)...
  • .one4-V-XXXXXXXX勒索病毒数据怎么处理|数据解密恢复
  • .php文件都打不开,打不开php文件怎么办
  • /bin/bash^M: bad interpreter: No such file or directory
  • /etc/skel 目录作用
  • @RequestMapping 的作用是什么?
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • [ Socket学习 ] 第一章:网络基础知识
  • [001-03-007].第07节:Redis中的事务