安卓编译: 3.framework层定制修改(二)-DPC多开APP

7 阅读3分钟

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

/data1/rom/android/asop/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;
            }
        }

修改创建profile的任务

/data1/rom/android/asop/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

/data1/rom/android/asop/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;
    }

修改 mUserManager.getMaxSupportedUsers

/data1/rom/android/asop/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));
    }

修改 UserManagerService canAddMoreProfilesToUser getMaxUsersOfTypePerParent

/data1/rom/android/asop/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;
    }

修改 Settings createNewUserLI :

/data1/rom/android/asop/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);
                }
                

修改 setProfileEnabled 和 setUserProvisioningState:

/data1/rom/android/asop/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);
        }
    }

删除不需要的APP

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

/data1/rom/android/asop/frameworks/base/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java

    @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定义如下:

/data1/rom/android/asop/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>