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

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();  // 这里改成 getLastManagedProfile
            if (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 builds
    return 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 calling
        getActiveAdminForCallerLocked(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.kler.cn/a/307620.html

相关文章:

  • Ubuntu中使用纯命令行进行Android开发
  • 深入理解 source 和 sh、bash 的区别
  • 基于VUE实现语音通话:边录边转发送语言消息、 播放pcm 音频
  • flink cdc 应用
  • 数据库的性能优化 -- SQL性能优化
  • 通过Python 调整Excel行高、列宽
  • 安全区域边界等保测评
  • 安全隔离上网的有效途径:沙盒
  • QT开发:深入详解QtCore模块事件处理,一文学懂QT 事件循环与处理机制
  • SQL使用IN进行分组统计时如何将不存在的字段显示为0
  • CISP-PTE CMS sqlgun靶场渗透测试
  • 学习笔记 韩顺平 零基础30天学会Java(2024.9.16)
  • 神经网络_使用tensorflow对fashion mnist衣服数据集分类
  • uniapp js修改数组某个下标以外的所有值
  • 2024.09.08 校招 实习 内推 面经
  • python Open3D 验证安装崩溃
  • 论文内容分类与检测系统源码分享
  • String 72变 ---------各种字符串处理方法
  • WSL挂载U盘或移动硬盘
  • 一起对话式学习-机器学习02——机器学习方法三要素
  • Apache-wed服务器环境的安装
  • 智能工厂的设计软件 单一面问题分析方法的“独角兽”程序
  • JVM面试真题总结(七)
  • 总结对象相关知识
  • Go语言并发编程之select语句详解
  • 【相机方案(2)】V4L2 支持相机图像直接进入GPU内存吗?DeepStream 确实可以将图像数据高效地放入GPU内存进行处理!