Android 多用戶

下面幾篇介紹的不錯,推薦看看html

 

https://www.jianshu.com/p/3ad2163f7d34   Android 9.x 多用戶機制 1 #Profile user建立過程java

https://www.jianshu.com/p/12dd5408943a   Android 9.x多用戶機制 2 #Profile User啓動過程android

https://www.jianshu.com/p/4aaa181a44ec   Android9.x多用戶機制#Profile user 桌面圖標顯示過程shell

 

多用戶相關 adb 命令:微信

查看支持最多用戶數app

adb shell pm get-max-userside

查詢系統全部用戶
adb shell pm list usersui

建立新用戶
adb shell pm create-user user_namethis

移除指定id用戶
adb shell pm remove-user user_idspa

 

 

 安裝應用到某個用戶 

adb install –user USER_ID name.apk 

 

多用戶切換:

adb shell am switch-user USER_ID

//通常0是本機機主,10或者11 或及之後 都是新用戶

 

切換到userid 12的用戶

 

 

 

 


 

 

https://www.itcodemonkey.com/article/6169.html   Android 多用戶 —— 從入門到應用分身 (上)

 

// 第一步,創新新用戶:
$ adb shell pm craete-user 'test-user'

// 第二步,得道新用戶的userId:
$ adb shell dumpsys user 
  ...
  UserInfo{10:test-user:0} serialNo=1001
  ...
// 得道UserId = 10

// 第三步, 啓動新用戶:
$ adb shell am start-user 10

// 第四步, 將新用戶切到前臺來:
$ adb shell am switch-user 10

// 第五步, 校驗切換用戶成功:
$ adb shell dumpsys activity a | grep 'Hist '
      * Hist #0: ActivityRecord{8636857 u10 com.meizu.flyme.launcher/.Launcher t1100001}

// 看到桌面"com.meizu.flyme.launcher/.Launcher"運行在"u10"即運行在userId=10的用戶下, 說明新用戶正處與前臺.

// ps: 如切回主用戶不贅述, 可自行查詢 "adb shell pm / am"命令.

 

 

安裝應用到 影子用戶

// 首先要獲取影子用戶的userID:
$ adb shell dumpsys user
  ...
  UserInfo{10:FlymeParallelSpace:30} serialNo=10
  ...

// UserInfo{10:FlymeParallelSpace:30}表示:
//  userId=10, 
//  userName="FlymeParallelSpace", 
//  flags=0x30
因而咱們獲得影子用戶的UserId


// 如微信已經安裝了, 使用adb命令重安裝到影子用戶:
$ adb shell pm install -r --user 10 `adb shell pm path com.tencent.mm | awk -F':' '{print $2}'`
// "--user 10" 指定安裝userId爲10.


// 或者調用API:
//   PMS.installExistingPackageAsUser()
//   PMS.installPackageAsUser()

 

 

分別啓動主用戶和影子用戶下的微信

// 首先找到微信的首頁Activity:
$ adb shell dumpsys package com.tencent.mm | grep "android.intent.action.MAIN:" -A 5 
      android.intent.action.MAIN:
        8f8990c com.tencent.mm/.ui.LauncherUI filter 3d82835
          Action: "android.intent.action.MAIN"
          Category: "android.intent.category.LAUNCHER"
          Category: "android.intent.category.MULTIWINDOW_LAUNCHER"
          AutoVerify=false
 // 獲得首頁Activity爲"com.tencent.mm/.ui.LauncherUI"


 //因而啓動影子用戶下的微信爲:
 $ adb shell am start --user 10 com.tencent.mm/.ui.LauncherUI
 // "--user 10"爲指定userId爲10, 不指定則默認爲主用戶, 即userId=0爲默認.
 // ps: 並非全部可指定userId的命令都這樣設定.
 //     如 "am force-stop"命令是默認狀況下殺全部用戶下進程, 而非僅殺主用戶下進程.



// 啓動主用戶下微信:
$ adb shell am start --user 0 com.tencent.mm/.ui.LauncherUI
 或:
$ adb shell am start com.tencent.mm/.ui.LauncherUI


檢查微信進程:
$ adb shell ps | grep com.tencent.mm
u10_a110 19794 11620 2157444 185912 SyS_epoll_ 00eb0ce428 S com.tencent.mm
u10_a110 19882 11620 1832116 121932 SyS_epoll_ 00eb0ce428 S com.tencent.mm:push
u0_a110   19989 11620 2151704 194924 SyS_epoll_ 00eb0ce428 S com.tencent.mm
u0_a110   20072 11620 1830048 122600 SyS_epoll_ 00eb0ce428 S com.tencent.mm:push

 

能夠看到,微信出現兩組進程組, 一組在u0_a110用戶下, 一組在u10_a110用戶下。且觀察界面能夠看到他們同時運行在同一個桌面下。基於多用戶, 咱們很容易將建立了任意應用(微信)的分身乃至多開(多建立幾個影子用戶便可)。

 

 

adb shell ps | grep u10
u10_a26   20491 11620 1274140 99920 SyS_epoll_ 00eb0ce428 S com.meizu.flyme.input
u10_a35   20507 11623 1987644 138320 SyS_epoll_ 75ce5b88a0 S com.android.systemui
u10_system 20599 11623 1822584 112340 SyS_epoll_ 75ce5b88a0 S com.meizu.flyme.xtemui
u10_a35   20630 11623 1805016 98724 SyS_epoll_ 75ce5b88a0 S com.android.systemui:recents
u10_a97   20826 11623 1808060 112752 SyS_epoll_ 75ce5b88a0 S com.meizu.flyme.weather
u10_a3    20839 11623 1800452 120916 SyS_epoll_ 75ce5b88a0 S android.process.acore
u10_a12   24815 11623 1777532 77556 SyS_epoll_ 75ce5b88a0 S android.process.media

  


 

 

https://blog.csdn.net/stephen8341/article/details/43196519   android多用戶下應用安裝詳解三(特殊需求實現)

https://blog.csdn.net/stephen8341/article/details/43195621   android多用戶下應用安裝詳解二(開機讀取流程)

https://blog.csdn.net/stephen8341/article/details/43192015   android多用戶下應用安裝詳解一(新應用安裝狀況)

Android P

Settings.java

 /**
     * Creates a new {@code PackageSetting} object.
     * Use this method instead of the constructor to ensure a settings object is created
     * with the correct base.
     */
    static @NonNull PackageSetting createNewSetting(String pkgName, PackageSetting originalPkg,
            PackageSetting disabledPkg, String realPkgName, SharedUserSetting sharedUser,
            File codePath, File resourcePath, String legacyNativeLibraryPath, String primaryCpuAbi,
            String secondaryCpuAbi, long versionCode, int pkgFlags, int pkgPrivateFlags,
            UserHandle installUser, boolean allowInstall, boolean instantApp,
            boolean virtualPreload, String parentPkgName, List<String> childPkgNames,
            UserManagerService userManager,
            String[] usesStaticLibraries, long[] usesStaticLibrariesVersions) {
        final PackageSetting pkgSetting;
        if (originalPkg != null) {
            if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
                    + pkgName + " is adopting original package " + originalPkg.name);
            pkgSetting = new PackageSetting(originalPkg, pkgName /*realPkgName*/);
            pkgSetting.childPackageNames =
                    (childPkgNames != null) ? new ArrayList<>(childPkgNames) : null;
            pkgSetting.codePath = codePath;
            pkgSetting.legacyNativeLibraryPathString = legacyNativeLibraryPath;
            pkgSetting.parentPackageName = parentPkgName;
            pkgSetting.pkgFlags = pkgFlags;
            pkgSetting.pkgPrivateFlags = pkgPrivateFlags;
            pkgSetting.primaryCpuAbiString = primaryCpuAbi;
            pkgSetting.resourcePath = resourcePath;
            pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;
            // NOTE: Create a deeper copy of the package signatures so we don't
            // overwrite the signatures in the original package setting.
            pkgSetting.signatures = new PackageSignatures();
            pkgSetting.versionCode = versionCode;
            pkgSetting.usesStaticLibraries = usesStaticLibraries;
            pkgSetting.usesStaticLibrariesVersions = usesStaticLibrariesVersions;
            // Update new package state.
            pkgSetting.setTimeStamp(codePath.lastModified());
        } else {
            pkgSetting = new PackageSetting(pkgName, realPkgName, codePath, resourcePath,
                    legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
                    null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
                    parentPkgName, childPkgNames, 0 /*sharedUserId*/, usesStaticLibraries,
                    usesStaticLibrariesVersions);
            pkgSetting.setTimeStamp(codePath.lastModified());
            pkgSetting.sharedUser = sharedUser;
            // If this is not a system app, it starts out stopped.
            if ((pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0) {
                if (DEBUG_STOPPED) {
                    RuntimeException e = new RuntimeException("here");
                    e.fillInStackTrace();
                    Slog.i(PackageManagerService.TAG, "Stopping package " + pkgName, e);
                }
                List<UserInfo> users = getAllUsers(userManager);
                final int installUserId = installUser != null ? installUser.getIdentifier() : 0;
                if (users != null && allowInstall) {
                    for (UserInfo user : users) {
                        // By default we consider this app to be installed
                        // for the user if no user has been specified (which
                        // means to leave it at its original value, and the
                        // original default value is true), or we are being
                        // asked to install for all users, or this is the
                        // user we are installing for.
                        final boolean installed = installUser == null
                                || (installUserId == UserHandle.USER_ALL
                                    && !isAdbInstallDisallowed(userManager, user.id))
                                || installUserId == user.id;
                        pkgSetting.setUserState(user.id, 0, COMPONENT_ENABLED_STATE_DEFAULT,
                                installed,
                                true /*stopped*/,
                                true /*notLaunched*/,
                                false /*hidden*/,
                                false /*suspended*/,
                                null /*suspendingPackage*/,
                                null /*dialogMessage*/,
                                null /*suspendedAppExtras*/,
                                null /*suspendedLauncherExtras*/,
                                instantApp,
                                virtualPreload,
                                null /*lastDisableAppCaller*/,
                                null /*enabledComponents*/,
                                null /*disabledComponents*/,
                                INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED,
                                0, PackageManager.INSTALL_REASON_UNKNOWN,
                                null /*harmfulAppWarning*/);
                    }
                }
            }
            if (sharedUser != null) {
                pkgSetting.appId = sharedUser.userId;
            } else {
                // Clone the setting here for disabled system packages
                if (disabledPkg != null) {
                    // For disabled packages a new setting is created
                    // from the existing user id. This still has to be
                    // added to list of user id's
                    // Copy signatures from previous setting
                    pkgSetting.signatures = new PackageSignatures(disabledPkg.signatures);
                    pkgSetting.appId = disabledPkg.appId;
                    // Clone permissions
                    pkgSetting.getPermissionsState().copyFrom(disabledPkg.getPermissionsState());
                    // Clone component info
                    List<UserInfo> users = getAllUsers(userManager);
                    if (users != null) {
                        for (UserInfo user : users) {
                            final int userId = user.id;
                            pkgSetting.setDisabledComponentsCopy(
                                    disabledPkg.getDisabledComponents(userId), userId);
                            pkgSetting.setEnabledComponentsCopy(
                                    disabledPkg.getEnabledComponents(userId), userId);
                        }
                    }
                }
            }
        }
        return pkgSetting;
    }

 

PackageManagerService.java

 final boolean createNewPackage = (pkgSetting == null);
        if (createNewPackage) {
            final String parentPackageName = (pkg.parentPackage != null)
                    ? pkg.parentPackage.packageName : null;
            final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
            final boolean virtualPreload = (scanFlags & SCAN_AS_VIRTUAL_PRELOAD) != 0;
            // REMOVE SharedUserSetting from method; update in a separate call
            pkgSetting = Settings.createNewSetting(pkg.packageName, originalPkgSetting,
                    disabledPkgSetting, realPkgName, sharedUserSetting, destCodeFile,
                    destResourceFile, pkg.applicationInfo.nativeLibraryRootDir,
                    pkg.applicationInfo.primaryCpuAbi, pkg.applicationInfo.secondaryCpuAbi,
                    pkg.mVersionCode, pkg.applicationInfo.flags, pkg.applicationInfo.privateFlags,
                    user, true /*allowInstall*/, instantApp, virtualPreload,
                    parentPackageName, pkg.getChildPackageNames(),
                    UserManagerService.getInstance(), usesStaticLibraries,
                    pkg.usesStaticLibrariesVersions);
        }

 

 


UserMS.java

userInfo.lastLoggedInFingerprint = Build.FINGERPRINT;   //記錄上一次指紋信息,能夠用於ota?

    /**
     * Called right before a user is started. This gives us a chance to prepare
     * app storage and apply any user restrictions.
     */
    public void onBeforeStartUser(int userId) {
        UserInfo userInfo = getUserInfo(userId);
        if (userInfo == null) {
            return;
        }
        final int userSerial = userInfo.serialNumber;
        // Migrate only if build fingerprints mismatch
        boolean migrateAppsData = !Build.FINGERPRINT.equals(userInfo.lastLoggedInFingerprint);
        mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_DE);
        mPm.reconcileAppsData(userId, StorageManager.FLAG_STORAGE_DE, migrateAppsData);  // 

        if (userId != UserHandle.USER_SYSTEM) {
            synchronized (mRestrictionsLock) {
                applyUserRestrictionsLR(userId);
            }
        }
    }
相關文章
相關標籤/搜索