Android DPC模式多开 APP

ops/2024/9/24 13:57:53/

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/ops/111932.html

相关文章

启动windows更新/停止windows更新,在配置更新中关闭自动更新的方法

在Windows操作系统中&#xff0c;启动或停止Windows更新&#xff0c;以及调整“配置更新”的关闭方法&#xff0c;涉及多种途径&#xff0c;这里将详细阐述几种常用的专业方法。 启动Windows更新 1.通过Windows服务管理器&#xff1a; -打开“运行”对话框&#xff08;…

谷歌在在线展示广告技术上的垄断,Meta无法有效竞争

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

【WPF】Popup的使用

WPF&#xff08;Windows Presentation Foundation&#xff09;中的Popup控件用于创建弹出窗口&#xff0c;如工具提示、上下文菜单等。Popup控件本身并不直接显示任何内容&#xff0c;它需要一个子元素来显示实际的内容。 以下是一个简单的XAML示例&#xff0c;展示如何创建一…

变量常量标识符 Day5

1. 变量 1.1 变量的概念 变量是计算机内存中的一块存储单元&#xff0c;是存储数据的基本单元变量的组成包括&#xff1a;数据类型、变量名、值&#xff0c;后文会具体描述变量的本质作用就是去记录数据的&#xff0c;比如说记录一个人的身高、体重、年龄&#xff0c;就需要去…

photozoom classic 9解锁码2024年最新25位解锁码

photozoom classic 9 破解版顾及比恐龙还要稀有&#xff0c;我曾经和你一样一直再找&#xff0c;找了好几个月&#xff0c;也没有找到真的破解版&#xff0c;下载很多次&#xff0c; 都是病毒插件之类的 我昨天下了几次&#xff0c;没有一个不附带插件病毒木马的.......&#x…

PHP环境搭建

PHP环境搭建是一个涉及多个组件配置的过程&#xff0c;主要包括安装Apache服务器&#xff08;或其他Web服务器&#xff09;、PHP解释器以及数据库&#xff08;如MySQL&#xff09;等。以下是一个详细的PHP环境搭建教程&#xff0c;旨在帮助初学者逐步完成环境的配置。 一、前期…

什么是机器学习力场

机器学习力场&#xff08;Machine Learning Force Fields, MLFF&#xff09;方法是一类将机器学习技术应用于分子动力学&#xff08;Molecular Dynamics, MD&#xff09;模拟的技术。它通过使用机器学习算法拟合原子之间的相互作用能量和力场&#xff0c;使得在不牺牲精度的前提…

实现实时Web应用,使用AJAX轮询、WebSocket、还是SSE呢??

文章目录 短轮询&#xff08;Short Polling&#xff09;长轮询&#xff08;Long Polling&#xff09;Comet “服务器推” &#xff08;这玩意现在用的很少了&#xff0c;了解一下即可&#xff09;WebSocket原理&#xff1a;方法&#xff1a;事件&#xff1a; SSE原理事件 总结 …