Android DPC模式多开 APP

embedded/2024/9/20 3:58:08/ 标签: android

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>


http://www.ppmy.cn/embedded/113328.html

相关文章

马匹行为识别系统源码分享

马匹行为识别检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

身份证阅读器API模式 VUE Dorado7

VUE 新框架 // 身份证扫描 readIdCard(type) {// 1.连接axios.get(http://localhost:19196/openDevice).then(res > {if (res.data.resultFlag 0) {// 2.读卡axios.get(http://localhost:19196/readCard).then((res) > {if (res.data.resultFlag 0) {// this.$message…

大模型入门3:理解LLAMA

LLama在transformers库中的代码&#xff0c;以及各部分原理Llama3.1技术报告LLama 33b 微调尝试 Model a stack of DecoderBlocks(SelfAttention, FeedForward, and RMSNorm) decoder block 整体结构&#xff1a;最大的区别在pre-norm x -> norm(x) -> attention() -…

图解Redis 02 | String数据类型的原理及应用场景

介绍 在 Redis 中&#xff0c;String 是一种重要的数据类型&#xff0c;是最基本的 key-value 结构&#xff0c;在这个结构中&#xff0c; value 是一个字符串。value 所能容纳的数据最大长度为512M。 需要注意的是&#xff0c;这里的字符串不只指文本数据&#xff0c;它还可…

【Kubernetes】常见面试题汇总(十六)

目录 48.简述 Kubernetes PodsecurityPolicy 机制能实现哪些安全策略&#xff1f; 49.简述 Kubernetes 网络模型&#xff1f; 50.简述 Kubernetes CNl 模型&#xff1f; 48.简述 Kubernetes PodsecurityPolicy 机制能实现哪些安全策略&#xff1f; 在 PodSecurityPolicy 对象…

LSTM文本预测(Pytorch版)

任务&#xff1a;基于 flare 文本数据&#xff0c;建立 LSTM 模型&#xff0c;预测序列文字 1.完成数据预处理&#xff0c;将文字序列数据转化为可用于LSTM输入的数据 2.查看文字数据预处理后的数据结构&#xff0c;并进行数据分离操作 3.针对字符串输入&#xff08;" fla…

【基于C++的产品入库管理系统】

基于C的产品入库管理系统可以用来跟踪产品的入库、出库和库存情况。这种系统通常包括产品信息的录入、查询、更新以及库存管理等功能。下面是一个简化的产品入库管理系统的设计方案及其代码示例。 系统设计概览 产品管理&#xff1a;包括产品的基本信息&#xff08;如名称、规…

个人电脑可以当服务器用吗?

服务器和普通电脑的主要区别体现在以下几个方面&#xff1a; 1.CPU处理性能 服务器的CPU配置通常是多核的&#xff0c;普通电脑的CPU往往只包含单个核心&#xff0c;因此在数据处理能力上远远不如服务器。 2.安全性能 服务器具备更高的可靠性、安全性、容错能力和安全保护能…

【计算机网络 - 基础问题】每日 3 题(一)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…

JVM垃圾回收算法

JVM垃圾回收算法是Java虚拟机中自动管理内存的关键机制&#xff0c;它通过智能识别和回收无用对象&#xff0c;有效防止内存泄露&#xff0c;提升系统性能&#xff0c;是Java语言高效、稳定运行的基石。让我们一同探索这一神奇算法&#xff0c;感受它如何为Java世界注入活力&am…

程序化自动交易,合约量化交易软件用哪个比较好

炒股自动化&#xff1a;申请官方API接口&#xff0c;散户也可以 python炒股自动化&#xff08;0&#xff09;&#xff0c;申请券商API接口 python炒股自动化&#xff08;1&#xff09;&#xff0c;量化交易接口区别 Python炒股自动化&#xff08;2&#xff09;&#xff1a;获取…

面试真题-TCP的三次握手

TCP的基础知识 TCP头部 面试题&#xff1a;TCP的头部是多大&#xff1f; TCP&#xff08;传输控制协议&#xff09;的头部通常是固定的20个字节长&#xff0c;但是根据TCP选项&#xff08;Options&#xff09;的不同&#xff0c;这个长度可以扩展。TCP头部包含了许多关键的字…

力扣100题——贪心算法

概述 贪心算法&#xff08;Greedy Algorithm&#xff09;是一种在解决问题时&#xff0c;按照某种标准在每一步都选择当前最优解&#xff08;局部最优解&#xff09;的算法。它期望通过一系列局部最优解的选择&#xff0c;最终能够得到全局最优解。 贪心算法的核心思想 贪心算…

Nginx实用篇:实现负载均衡、限流与动静分离

Nginx实用篇&#xff1a;实现负载均衡、限流与动静分离 | 原创作者/编辑&#xff1a;凯哥Java | 分类&#xff1a;Nginx学习系列教程 Nginx 作为一款高性能的 HTTP 服务器及反向代理解决方案&#xff0c;在互联网架构中扮演着至关重要的角色。它…

如何搭建一个ip池用来做数据抓取用

在当今的数据驱动时代&#xff0c;数据抓取成为了获取网络信息的重要手段。然而&#xff0c;频繁的数据抓取活动可能会触发网站的安全机制&#xff0c;导致IP被封禁。为了维持数据抓取的持续性和稳定性&#xff0c;构建一个有效的IP池变得至关重要。本文将详细介绍如何搭建一个…

好用的XML解析库——fast-xml-parser

有时候需要在前台用到xml的解析&#xff0c;并且可能需要解析后再重新生成xml字符串&#xff0c;这个时候就可以用到fast-xml-parser了。 优点 使用简单&#xff0c;主要有两个对象&#xff0c;分别是XMLParser和XMLBuilder。 主要需要关注的属性有 ignoreAttributes 和 supp…

ASR(自动语音识别)识别文本效果的打分总结

ASR(自动语音识别)识别文本效果的打分总结 1. 词错误率(WER, Word Error Rate)2. 字正确率(W.Corr, Word Correct)3. 编辑距离(Edit Distance)4. 特定错误率5. 句子错误率(SER, Sentence Error Rate)6. 基于模型的评估方法对于ASR(自动语音识别)识别文本效果的打分…

HtmlRender - c++实现的html生成类

HtmlRender 在CppTinParser/render.hpp中定义和实现。 使用c实现的简易Html编辑类。 简介 目前&#xff0c;c有几个Html解析器&#xff0c;而少见便捷规范的html生成器&#xff0c;HtmlRender则提供了一个简单的、规范的html内容生成器。用c实现html内容生成器&#xff0c;…

vue3项目实现全局国际化

本文主要梳理vue3项目实现全项目格式化&#xff0c;例如在我前面文章使用若依创建vue3的项目中&#xff0c;地址&#xff1a;若依搭建vue3项目在导航栏中切换&#xff0c;页面中所有的组件的默认语言随之切换&#xff0c;使用的组件库依旧是element-plus&#xff0c;搭配vue-i1…

Java应用压测工具JMeter

目录 1、下载JMeter 2、配置环境变量 3、配置语音 4、使用 1、下载JMeter Apache JMeter - Apache JMeter™ 千万别下载这个&#xff0c;会报错、 千万别下载这个&#xff0c;会报错、 千万别下载这个&#xff0c;会报错 下载这个&#xff0c;失败多下载几次 2、配置环…