How do multi-user split users synchronously install the installed applications in the primary user? This problem is caused by a problem encountered in recent work. The background of the problem is as follows:
After the system is set to open wechat avatar, the mobile phone installs and sets the third-party input method (such as Sogou input method) as the current input method. After opening wechat, it is found that the set third-party input method (Sogou input method) is used in the main wechat, while the input method used in wechat avatar is the system default Baidu input method. The two input methods are not synchronized.
Under the traction of this problem background, the analysis found that the third-party input method (Sogou comfortable hair) was not installed under the separated user.
Let's take a look at how to create separate users first?
Where is the code interface for creating separated users?
See:
frameworks/base/core/java/android/os/UserManager.java
/** 2910 * Similar to {@link #createProfileForUser(String, String, int, int, String[])} 2911 * except bypassing the checking of {@link UserManager#DISALLOW_ADD_MANAGED_PROFILE}. 2912 * 2913 * @see #createProfileForUser(String, String, int, int, String[]) 2914 * @hide 2915 */ 2916 @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS, 2917 Manifest.permission.CREATE_USERS}) 2918 public UserInfo createProfileForUserEvenWhenDisallowed(String name, 2919 @NonNull String userType, @UserInfoFlag int flags, @UserIdInt int userId, 2920 String[] disallowedPackages) { 2921 try { 2922 return mService.createProfileForUserEvenWhenDisallowedWithThrow(name, userType, flags, 2923 userId, disallowedPackages); 2924 } catch (ServiceSpecificException e) { 2925 return null; 2926 } catch (RemoteException re) { 2927 throw re.rethrowFromSystemServer(); 2928 } 2929 }
Parameters passed in:
Name: the name of the separated user to be created
userType: the user type created. Usermanager is used here USER_ TYPE_ PROFILE_ Managed, separated user type
flags: Specifies the UserInfo flag of the user attribute. For example: UserInfo FLAG_ DISABLED
userId: primary user id
disallowedPackages: it is not allowed to install all application packages and package name collection under the new separated user (here, only system applications can be filtered, and installed third-party applications cannot be filtered; because during the process of creating a new user, synchronous installation will be carried out for system applications and only system applications during initialization)
In the above method, a new separated user is created, all system applications in disallowedPackages are filtered out, and the system applications are synchronously installed in the new user directory (the follow-up code analysis is omitted here, and the specific implementation needs to be followed up and checked by the students themselves. Later, we will introduce them in detail when we have time). For the synchronous installation of system applications, the final specific implementation code is shown in:
frameworks/base/services/core/java/com/android/server/pm/Settings.java
void createNewUserLI(@NonNull PackageManagerService service, @NonNull Installer installer, 4176 @UserIdInt int userHandle, @Nullable Set<String> userTypeInstallablePackages, 4177 String[] disallowedPackages) { 4178 final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing", 4179 Trace.TRACE_TAG_PACKAGE_MANAGER); 4180 t.traceBegin("createNewUser-" + userHandle); 4181 String[] volumeUuids; 4182 String[] names; 4183 int[] appIds; 4184 String[] seinfos; 4185 int[] targetSdkVersions; 4186 int packagesCount; 4187 final boolean skipPackageWhitelist = userTypeInstallablePackages == null; 4188 synchronized (mLock) { 4189 Collection<PackageSetting> packages = mPackages.values(); 4190 packagesCount = packages.size(); 4191 volumeUuids = new String[packagesCount]; 4192 names = new String[packagesCount]; 4193 appIds = new int[packagesCount]; 4194 seinfos = new String[packagesCount]; 4195 targetSdkVersions = new int[packagesCount]; 4196 Iterator<PackageSetting> packagesIterator = packages.iterator(); 4197 for (int i = 0; i < packagesCount; i++) { 4198 PackageSetting ps = packagesIterator.next(); 4199 if (ps.pkg == null) { 4200 continue; 4201 } 4202 final boolean shouldMaybeInstall = ps.isSystem() && 4203 !ArrayUtils.contains(disallowedPackages, ps.name) && 4204 !ps.getPkgState().isHiddenUntilInstalled(); 4205 final boolean shouldReallyInstall = shouldMaybeInstall && 4206 (skipPackageWhitelist || userTypeInstallablePackages.contains(ps.name)); 4207 // Only system apps are initially installed. Only system applications are installed during initialization 4208 ps.setInstalled(shouldReallyInstall, userHandle); 4209 // If userTypeInstallablePackages is the *only* reason why we're not installing, 4210 // then uninstallReason is USER_TYPE. If there's a different reason, or if we 4211 // actually are installing, put UNKNOWN. 4212 final int uninstallReason = (shouldMaybeInstall && !shouldReallyInstall) ? 4213 UNINSTALL_REASON_USER_TYPE : UNINSTALL_REASON_UNKNOWN; 4214 ps.setUninstallReason(uninstallReason, userHandle); 4215 if (!shouldReallyInstall) { 4216 writeKernelMappingLPr(ps); 4217 } 4218 // Need to create a data directory for all apps under this user. Accumulate all 4219 // required args and call the installer after mPackages lock has been released 4220 volumeUuids[i] = ps.volumeUuid; 4221 names[i] = ps.name; 4222 appIds[i] = ps.appId; 4223 seinfos[i] = AndroidPackageUtils.getSeInfo(ps.pkg, ps); 4224 targetSdkVersions[i] = ps.pkg.getTargetSdkVersion(); 4225 } 4226 } 4227 t.traceBegin("createAppData"); 4228 final int flags = StorageManager.FLAG_STORAGE_CE | StorageManager.FLAG_STORAGE_DE; 4229 try { 4230 installer.createAppDataBatched(volumeUuids, names, userHandle, flags, appIds, seinfos, 4231 targetSdkVersions); 4232 } catch (InstallerException e) { 4233 Slog.w(TAG, "Failed to prepare app data", e); 4234 } 4235 t.traceEnd(); // createAppData 4236 synchronized (mLock) { 4237 applyDefaultPreferredAppsLPw(userHandle); 4238 } 4239 t.traceEnd(); // createNewUser 4240 } 4241
The rest are other third-party applications. What should I do if I want to install them synchronously to a new separated user?
See details:
/frameworks/base/core/java/android/content/pm/PackageManager.java
/** 6120 * If there is already an application with the given package name installed 6121 * on the system for other users, also install it for the specified user. 6122 * @hide 6123 * 6124 * @deprecated use {@link PackageInstaller#installExistingPackage()} instead. 6125 */ 6126 @Deprecated 6127 @RequiresPermission(anyOf = { 6128 Manifest.permission.INSTALL_EXISTING_PACKAGES, 6129 Manifest.permission.INSTALL_PACKAGES, 6130 Manifest.permission.INTERACT_ACROSS_USERS_FULL}) 6131 @UnsupportedAppUsage 6132 public abstract int installExistingPackageAsUser(@NonNull String packageName, 6133 @UserIdInt int userId) throws NameNotFoundException; 6134
For specific implementation, see:
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
/** 13304 * @hide 13305 */ 13306 @Override 13307 public int installExistingPackageAsUser(String packageName, int userId, int installFlags, 13308 int installReason, List<String> whiteListedPermissions) { 13309 return installExistingPackageAsUser(packageName, userId, installFlags, installReason, 13310 whiteListedPermissions, null); 13311 }
When using, you can directly call the installExistingPackageAsUser(packageName,userId) method in PM, where:
packageName: the name of the application package to be installed (e.g. the third-party application already installed in the main user, Sogou input method)
userId: the user id of the separated user. Here, you can pass the userId of the separated user created by using the createprofileforuserevenwhendiallowed() method in UM
installExistingPackageAsUser(packageName,userId): this method is used to install the installed applications on the primary user on the child user uerId. In the specific implementation method, you can view the installation status of the application with the modified package name packageName under the separated user
At this point, you can create a separated user and synchronously install the installed applications of the main user into the new separated user. Finally, through this method, after the mobile phone sets the input method as the installed third-party input method, you can realize that the input method used in the main wechat and wechat separation is the set third-party input method~
PS: all codes produce the word android 11 source code. For non android 11 source code, the class location of the implementation method may be different