PMS构造函数流程分析

2023-11-08 13:08
文章标签 分析 流程 构造函数 pms

本文主要是介绍PMS构造函数流程分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、相关代码文件

frameworks\base\services\core\java\com\android\server\pm\PackageManagerService.java

frameworks\base\services\core\java\com\android\server\pm\Settings.java

frameworks\base\services\core\java\com\android\server\pm\PackageSetting.java

frameworks\base\core\java\com\android\server\SystemConfig.java

frameworks\base\core\java\android\content\pm\PackageParser.java

 

PMS构造函数主要工作流程如下如:

1.mInstaller、mMetrics等的初始化

mFactoryTest = factoryTest;
mOnlyCore = onlyCore;
mMetrics = new DisplayMetrics();
mInstaller = installer;
 2.sUserManager、mPermissionManager、mSettings的初始化

sUserManager = new UserManagerService(context, this,
        new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
mPermissionManager = PermissionManagerService.create(context,
        new DefaultPermissionGrantedCallback() {
            @Override
            public void onDefaultRuntimePermissionsGranted(int userId) {
                synchronized(mPackages) {
                    mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
                }
            }
        }, mPackages /*externalLock*/);
mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages);
此处对权限管理、用户管理和settings进行了初始化

2.1、启动用户管理服务

代码通过读取/data/system/users路径下的目录和文件,将系统设置的默认用户信息读如内存中:

private UserManagerService(Context context, PackageManagerService pm,
        UserDataPreparer userDataPreparer, Object packagesLock, File dataDir) {
    mContext = context;
    mPm = pm;
    mPackagesLock = packagesLock;
    mHandler = new MainHandler();
    mUserDataPreparer = userDataPreparer;
    synchronized (mPackagesLock) {
        mUsersDir = new File(dataDir, USER_INFO_DIR);
        mUsersDir.mkdirs();
        // Make zeroth user directory, for services to migrate their files to that location
        File userZeroDir = new File(mUsersDir, String.valueOf(UserHandle.USER_SYSTEM));
        userZeroDir.mkdirs();
        FileUtils.setPermissions(mUsersDir.toString(),
                FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH | FileUtils.S_IXOTH,
                -1, -1);
        mUserListFile = new File(mUsersDir, USER_LIST_FILENAME);
        initDefaultGuestRestrictions();
        readUserListLP();
        sInstance = this;
    }
    mLocalService = new LocalService();
    LocalServices.addService(UserManagerInternal.class, mLocalService);
    mLockPatternUtils = new LockPatternUtils(mContext);
    mUserStates.put(UserHandle.USER_SYSTEM, UserState.STATE_BOOTING);
}
通过添加授权回调,将每次用户的授权情况都实时的通过setting写入到本地文件中:

mSettings.onDefaultRuntimePermissionsGrantedLPr(userId);
 
private final class MyHandler extends Handler {
    public MyHandler() {
        super(BackgroundThread.getHandler().getLooper());
    }
 
    @Override
    public void handleMessage(Message message) {
        final int userId = message.what;
        Runnable callback = (Runnable) message.obj;
        //写入到本地文件:/data/system/users/0/runtime-permissions.xml中
        writePermissionsSync(userId);
        if (callback != null) {
            callback.run();
        }
    }
}
Settings初始化将所有的用于存储package信息的路径文件都初始化:

Settings(File dataDir, PermissionSettings permission, Object lock) {
    mLock = lock;
    mPermissions = permission;
    mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
 
    mSystemDir = new File(dataDir, "system");
    mSystemDir.mkdirs();
    FileUtils.setPermissions(mSystemDir.toString(),
            FileUtils.S_IRWXU|FileUtils.S_IRWXG
            |FileUtils.S_IROTH|FileUtils.S_IXOTH,
            -1, -1);
    mSettingsFilename = new File(mSystemDir, "packages.xml");
    mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
    mPackageListFilename = new File(mSystemDir, "packages.list");
    FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);
 
    final File kernelDir = new File("/config/sdcardfs");
    mKernelMappingFilename = kernelDir.exists() ? kernelDir : null;
 
    // Deprecated: Needed for migration
    mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
    mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
}
3.mSettings添加uid

mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.se", SE_UID,
        ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
    SharedUserSetting s = mSharedUsers.get(name);
    if (s != null) {
        if (s.userId == uid) {
            return s;
        }
        PackageManagerService.reportSettingsProblem(Log.ERROR,
                "Adding duplicate shared user, keeping first: " + name);
        return null;
    }
    s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
    s.userId = uid;
    if (addUserIdLPw(uid, s, name)) {
        //加入列表中
        mSharedUsers.put(name, s);
        return s;
    }
    return null;
}
4.mPackageDexOptimizer、mDexManager初始化

mPackageDexOptimizer = new PackageDexOptimizer(installer, mInstallLock, context,
        "*dexopt*");
DexManager.Listener dexManagerListener = DexLogger.getListener(this,
        installer, mInstallLock);
mDexManager = new DexManager(mContext, this, mPackageDexOptimizer, installer, mInstallLock,
        dexManagerListener);
 5.初始化默认系统配置,各种白名单

SystemConfig systemConfig = SystemConfig.getInstance();
SystemConfig负责从system/etc目录中读取xml文件,将其中预置的应用或者设置读取到列表中保存,如feature列表,省点白名单,共享库,允许使用流量列表等

 

 // Group-ids that are given to all packages as read from etc/permissions/*.xml.
int[] mGlobalGids;
 
// These are the built-in uid -> permission mappings that were read from the
// system configuration files.
final SparseArray<ArraySet<String>> mSystemPermissions = new SparseArray<>();
 
// These are the built-in shared libraries that were read from the
// system configuration files.  Keys are the library names; strings are the
// paths to the libraries.
final ArrayMap<String, String> mSharedLibraries  = new ArrayMap<>();
 
// These are the features this devices supports that were read from the
// system configuration files.
final ArrayMap<String, FeatureInfo> mAvailableFeatures = new ArrayMap<>();
 
// These are the features which this device doesn't support; the OEM
// partition uses these to opt-out of features from the system image.
final ArraySet<String> mUnavailableFeatures = new ArraySet<>();
// These are the permission -> gid mappings that were read from the
// system configuration files.
final ArrayMap<String, PermissionEntry> mPermissions = new ArrayMap<>();
 
// These are the packages that are white-listed to be able to run in the
// background while in power save mode (but not whitelisted from device idle modes),
// as read from the configuration files.
final ArraySet<String> mAllowInPowerSaveExceptIdle = new ArraySet<>();
 
// These are the packages that are white-listed to be able to run in the
// background while in power save mode, as read from the configuration files.
final ArraySet<String> mAllowInPowerSave = new ArraySet<>();
 
// These are the packages that are white-listed to be able to run in the
// background while in data-usage save mode, as read from the configuration files.
final ArraySet<String> mAllowInDataUsageSave = new ArraySet<>();
 
// These are the packages that are white-listed to be able to run background location
// without throttling, as read from the configuration files.
final ArraySet<String> mAllowUnthrottledLocation = new ArraySet<>();
 
// These are the action strings of broadcasts which are whitelisted to
// be delivered anonymously even to apps which target O+.
final ArraySet<String> mAllowImplicitBroadcasts = new ArraySet<>();
 
// These are the package names of apps which should be in the 'always'
// URL-handling state upon factory reset.
final ArraySet<String> mLinkedApps = new ArraySet<>();
 
// These are the packages that are whitelisted to be able to run as system user
final ArraySet<String> mSystemUserWhitelistedApps = new ArraySet<>();
 
// These are the packages that should not run under system user
final ArraySet<String> mSystemUserBlacklistedApps = new ArraySet<>();
 
// These are the components that are enabled by default as VR mode listener services.
final ArraySet<ComponentName> mDefaultVrComponents = new ArraySet<>();
 
// These are the permitted backup transport service components
final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>();
 
// Package names that are exempted from private API blacklisting
final ArraySet<String> mHiddenApiPackageWhitelist = new ArraySet<>();
 
SystemConfig() {
    // Read configuration from system
    readPermissions(Environment.buildPath(
            Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);
 
    // Read configuration from the old permissions dir
    readPermissions(Environment.buildPath(
            Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);
 
    // Vendors are only allowed to customze libs, features and privapp permissions
    int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS;
    if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
        // For backward compatibility
        vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
    }
    readPermissions(Environment.buildPath(
            Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);
 
    // Allow ODM to customize system configs as much as Vendor, because /odm is another
    // vendor partition other than /vendor.
    int odmPermissionFlag = vendorPermissionFlag;
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);
 
    // Allow OEM to customize features and OEM permissions
    int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS;
    readPermissions(Environment.buildPath(
            Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);
 
    // Allow Product to customize system configs around libs, features, permissions and apps
    int productPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
            ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
    readPermissions(Environment.buildPath(
            Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
    readPermissions(Environment.buildPath(
            Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
}
6.初始化保护应用

mProtectedPackages = new ProtectedPackages(mContext);
7.初始化内部消息循环,加入watchdog

mHandlerThread = new ServiceThread(TAG,
        Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
mHandlerThread.start();
mHandler = new PackageHandler(mHandlerThread.getLooper());
mProcessLoggingHandler = new ProcessLoggingHandler();
Watchdog.getInstance().addThread(mHandler, WATCHDOG_TIMEOUT);
PMS中的应用安装、卸载等操作都是PackageHandler来实现异步操作的

8.将系统默认设置的共享库添加到pms中android共享库中

ArrayMap<String, String> libConfig = systemConfig.getSharedLibraries();
final int builtInLibCount = libConfig.size();
for (int i = 0; i < builtInLibCount; i++) {
    String name = libConfig.keyAt(i);
    String path = libConfig.valueAt(i);
    //PLATFORM_PACKAGE_NAME:android
    addSharedLibraryLPw(path, null, name, SharedLibraryInfo.VERSION_UNDEFINED,
            SharedLibraryInfo.TYPE_BUILTIN, PLATFORM_PACKAGE_NAME, 0);
}
 
private boolean addSharedLibraryLPw(String path, String apk, String name, long version,
        int type, String declaringPackageName, long declaringVersionCode) {
    LongSparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.get(name);
    if (versionedLib == null) {
        versionedLib = new LongSparseArray<>();
        mSharedLibraries.put(name, versionedLib);
        if (type == SharedLibraryInfo.TYPE_STATIC) {
            mStaticLibsByDeclaringPackage.put(declaringPackageName, versionedLib);
        }
    } else if (versionedLib.indexOfKey(version) >= 0) {
        return false;
    }
    SharedLibraryEntry libEntry = new SharedLibraryEntry(path, apk, name,
            version, type, declaringPackageName, declaringVersionCode);
    versionedLib.put(version, libEntry);
    return true;
}
9.初始化selinux策略

 SELinuxMMAC.readInstallPolicy();
SELinuxMMAC中通过读取位于/system/etc/selinux下的文件,获取系统默认的selinux policy

static {
    // Platform mac permissions.
    sMacPermissions.add(new File(
        Environment.getRootDirectory(), "/etc/selinux/plat_mac_permissions.xml"));
 
    // Vendor mac permissions.
    // The filename has been renamed from nonplat_mac_permissions to
    // vendor_mac_permissions. Either of them should exist.
    final File vendorMacPermission = new File(
        Environment.getVendorDirectory(), "/etc/selinux/vendor_mac_permissions.xml");
    if (vendorMacPermission.exists()) {
        sMacPermissions.add(vendorMacPermission);
    } else {
        // For backward compatibility.
        sMacPermissions.add(new File(Environment.getVendorDirectory(),
                                     "/etc/selinux/nonplat_mac_permissions.xml"));
    }
 
    // ODM mac permissions (optional).
    final File odmMacPermission = new File(
        Environment.getOdmDirectory(), "/etc/selinux/odm_mac_permissions.xml");
    if (odmMacPermission.exists()) {
        sMacPermissions.add(odmMacPermission);
    }
}
 
public static boolean readInstallPolicy() {
    synchronized (sPolicies) {
        if (sPolicyRead) {
            return true;
        }
    }
 
    // Temp structure to hold the rules while we parse the xml file
    List<Policy> policies = new ArrayList<>();
 
    FileReader policyFile = null;
    XmlPullParser parser = Xml.newPullParser();
 
    final int count = sMacPermissions.size();
    for (int i = 0; i < count; ++i) {
        final File macPermission = sMacPermissions.get(i);
        try {
            policyFile = new FileReader(macPermission);
            Slog.d(TAG, "Using policy file " + macPermission);
 
            parser.setInput(policyFile);
            parser.nextTag();
            parser.require(XmlPullParser.START_TAG, null, "policy");
 
            while (parser.next() != XmlPullParser.END_TAG) {
                if (parser.getEventType() != XmlPullParser.START_TAG) {
                    continue;
                }
 
                switch (parser.getName()) {
                    case "signer":
                        policies.add(readSignerOrThrow(parser));
                        break;
                    default:
                        skip(parser);
                }
            }
        //......
}
 
private static Policy readSignerOrThrow(XmlPullParser parser) throws IOException,
        XmlPullParserException {
 
    parser.require(XmlPullParser.START_TAG, null, "signer");
    Policy.PolicyBuilder pb = new Policy.PolicyBuilder();
 
    // Check for a cert attached to the signer tag. We allow a signature
    // to appear as an attribute as well as those attached to cert tags.
    String cert = parser.getAttributeValue(null, "signature");
    if (cert != null) {
        pb.addSignature(cert);
    }
 
    while (parser.next() != XmlPullParser.END_TAG) {
        if (parser.getEventType() != XmlPullParser.START_TAG) {
            continue;
        }
 
        String tagName = parser.getName();
        if ("seinfo".equals(tagName)) {
            String seinfo = parser.getAttributeValue(null, "value");
            pb.setGlobalSeinfoOrThrow(seinfo);
            readSeinfo(parser);
        } else if ("package".equals(tagName)) {
            readPackageOrThrow(parser, pb);
        } else if ("cert".equals(tagName)) {
            String sig = parser.getAttributeValue(null, "signature");
            pb.addSignature(sig);
            readCert(parser);
        } else {
            skip(parser);
        }
    }
 
    return pb.build();
}
10.解析package.xml等文件初始化settings中各列表

Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 

 boolean readLPw(@NonNull List<UserInfo> users) {
    //依次查找packages-backup.xml,如果该文件不存在,则查找packages.xml
       
        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
            String tagName = parser.getName();
            if (tagName.equals("package")) {
                readPackageLPw(parser);
            } else if (tagName.equals("permissions")) {
                mPermissions.readPermissions(parser);
            } else if (tagName.equals("permission-trees")) {
                mPermissions.readPermissionTrees(parser);
            } else if (tagName.equals("shared-user")) {
                readSharedUserLPw(parser);
            } else if (tagName.equals("preferred-packages")) {
                // no longer used.
            } else if (tagName.equals("preferred-activities")) {
                // Upgrading from old single-user implementation;
                // these are the preferred activities for user 0.
                readPreferredActivitiesLPw(parser, 0);
            } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
                // TODO: check whether this is okay! as it is very
                // similar to how preferred-activities are treated
                readPersistentPreferredActivitiesLPw(parser, 0);
            } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) {
                // TODO: check whether this is okay! as it is very
                // similar to how preferred-activities are treated
                readCrossProfileIntentFiltersLPw(parser, 0);
            } else if (tagName.equals(TAG_DEFAULT_BROWSER)) {
                readDefaultAppsLPw(parser, 0);
            } else if (tagName.equals("updated-package")) {
                readDisabledSysPackageLPw(parser);
            } else if (tagName.equals("cleaning-package")) {
                String name = parser.getAttributeValue(null, ATTR_NAME);
                String userStr = parser.getAttributeValue(null, ATTR_USER);
                String codeStr = parser.getAttributeValue(null, ATTR_CODE);
                if (name != null) {
                    int userId = UserHandle.USER_SYSTEM;
                    boolean andCode = true;
                    try {
                        if (userStr != null) {
                            userId = Integer.parseInt(userStr);
                        }
                    } catch (NumberFormatException e) {
                    }
                    if (codeStr != null) {
                        andCode = Boolean.parseBoolean(codeStr);
                    }
                    addPackageToCleanLPw(new PackageCleanItem(userId, name, andCode));
                }
            } else if (tagName.equals("renamed-package")) {
                String nname = parser.getAttributeValue(null, "new");
                String oname = parser.getAttributeValue(null, "old");
                if (nname != null && oname != null) {
                    mRenamedPackages.put(nname, oname);
                }
            } else if (tagName.equals("restored-ivi")) {
                readRestoredIntentFilterVerifications(parser);
            } else if (tagName.equals("last-platform-version")) {
                // Upgrade from older XML schema
                final VersionInfo internal = findOrCreateVersion(
                        StorageManager.UUID_PRIVATE_INTERNAL);
                final VersionInfo external = findOrCreateVersion(
                        StorageManager.UUID_PRIMARY_PHYSICAL);
 
                internal.sdkVersion = XmlUtils.readIntAttribute(parser, "internal", 0);
                external.sdkVersion = XmlUtils.readIntAttribute(parser, "external", 0);
                internal.fingerprint = external.fingerprint =
                        XmlUtils.readStringAttribute(parser, "fingerprint");
 
            } else if (tagName.equals("database-version")) {
                // Upgrade from older XML schema
                final VersionInfo internal = findOrCreateVersion(
                        StorageManager.UUID_PRIVATE_INTERNAL);
                final VersionInfo external = findOrCreateVersion(
                        StorageManager.UUID_PRIMARY_PHYSICAL);
 
                internal.databaseVersion = XmlUtils.readIntAttribute(parser, "internal", 0);
                external.databaseVersion = XmlUtils.readIntAttribute(parser, "external", 0);
 
            } else if (tagName.equals("verifier")) {
                final String deviceIdentity = parser.getAttributeValue(null, "device");
                try {
                    mVerifierDeviceIdentity = VerifierDeviceIdentity.parse(deviceIdentity);
                } catch (IllegalArgumentException e) {
                    Slog.w(PackageManagerService.TAG, "Discard invalid verifier device id: "
                            + e.getMessage());
                }
            } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
                final String enforcement = parser.getAttributeValue(null, ATTR_ENFORCEMENT);
                mReadExternalStorageEnforced =
                        "1".equals(enforcement) ? Boolean.TRUE : Boolean.FALSE;
            } else if (tagName.equals("keyset-settings")) {
                mKeySetManagerService.readKeySetsLPw(parser, mKeySetRefs);
            } else if (TAG_VERSION.equals(tagName)) {
                final String volumeUuid = XmlUtils.readStringAttribute(parser,
                        ATTR_VOLUME_UUID);
                final VersionInfo ver = findOrCreateVersion(volumeUuid);
                ver.sdkVersion = XmlUtils.readIntAttribute(parser, ATTR_SDK_VERSION);
                ver.databaseVersion = XmlUtils.readIntAttribute(parser, ATTR_DATABASE_VERSION);
                ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT);
            } else {
                Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: "
                        + parser.getName());
                XmlUtils.skipCurrentTag(parser);
            }
        }
 
        str.close();
 
    } catch (XmlPullParserException e) {
        mReadMessages.append("Error reading: " + e.toString());
        PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
        Slog.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
 
    } catch (java.io.IOException e) {
        mReadMessages.append("Error reading: " + e.toString());
        PackageManagerService.reportSettingsProblem(Log.ERROR, "Error reading settings: " + e);
        Slog.wtf(PackageManagerService.TAG, "Error reading package manager settings", e);
    }
 
   //......
    final int N = mPendingPackages.size();
 
    for (int i = 0; i < N; i++) {
        final PackageSetting p = mPendingPackages.get(i);
        final int sharedUserId = p.getSharedUserId();
        final Object idObj = getUserIdLPr(sharedUserId);
        if (idObj instanceof SharedUserSetting) {
            final SharedUserSetting sharedUser = (SharedUserSetting) idObj;
            p.sharedUser = sharedUser;
            p.appId = sharedUser.userId;
            addPackageSettingLPw(p, sharedUser);
        } else if (idObj != null) {
            String msg = "Bad package setting: package " + p.name + " has shared uid "
                    + sharedUserId + " that is not a shared uid\n";
            mReadMessages.append(msg);
            PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
        } else {
            String msg = "Bad package setting: package " + p.name + " has shared uid "
                    + sharedUserId + " that is not defined\n";
            mReadMessages.append(msg);
            PackageManagerService.reportSettingsProblem(Log.ERROR, msg);
        }
    }
    mPendingPackages.clear();
 
    if (mBackupStoppedPackagesFilename.exists()
            || mStoppedPackagesFilename.exists()) {
        // Read old file
        readStoppedLPw();
        mBackupStoppedPackagesFilename.delete();
        mStoppedPackagesFilename.delete();
        // Migrate to new file format
        writePackageRestrictionsLPr(UserHandle.USER_SYSTEM);
    } else {
        for (UserInfo user : users) {
            readPackageRestrictionsLPr(user.id);
        }
    }
 
    for (UserInfo user : users) {
        mRuntimePermissionsPersistence.readStateForUserSyncLPr(user.id);
    }
 
    /*
     * Make sure all the updated system packages have their shared users
     * associated with them.
     */
    final Iterator<PackageSetting> disabledIt = mDisabledSysPackages.values().iterator();
    while (disabledIt.hasNext()) {
        final PackageSetting disabledPs = disabledIt.next();
        final Object id = getUserIdLPr(disabledPs.appId);
        if (id != null && id instanceof SharedUserSetting) {
            disabledPs.sharedUser = (SharedUserSetting) id;
        }
    }
 
    mReadMessages.append("Read completed successfully: " + mPackages.size() + " packages, "
            + mSharedUsers.size() + " shared uids\n");
 
    writeKernelMappingLPr();
 
    return true;
}
通过读取文件packages-backup.xml或者packages.xml将系统中的所有应用相关信息都读入到内存中,packages.xml文件内容如下所示:

11.移除codepath已经不存在的应用

final int packageSettingCount = mSettings.mPackages.size();
for (int i = packageSettingCount - 1; i >= 0; i--) {
    PackageSetting ps = mSettings.mPackages.valueAt(i);
    if (!isExternal(ps) && (ps.codePath == null || !ps.codePath.exists())
            && mSettings.getDisabledSystemPkgLPr(ps.name) != null) {
        mSettings.mPackages.removeAt(i);
        mSettings.enableSystemPackageLPw(ps.name);
    }
}
 

PackageSetting enableSystemPackageLPw(String name) {
    PackageSetting p = mDisabledSysPackages.get(name);
    if(p == null) {
        Log.w(PackageManagerService.TAG, "Package " + name + " is not disabled");
        return null;
    }
    // Reset flag in ApplicationInfo object
    if((p.pkg != null) && (p.pkg.applicationInfo != null)) {
        p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
    }
    PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
            p.legacyNativeLibraryPathString, p.primaryCpuAbiString,
            p.secondaryCpuAbiString, p.cpuAbiOverrideString,
            p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags,
            p.parentPackageName, p.childPackageNames, p.usesStaticLibraries,
            p.usesStaticLibrariesVersions);
    mDisabledSysPackages.remove(name);
    return ret;
}
12.初始化系统文件路径,是否升级版本

final String bootClassPath = System.getenv("BOOTCLASSPATH");
final String systemServerClassPath = System.getenv("SYSTEMSERVERCLASSPATH");
File frameworkDir = new File(Environment.getRootDirectory(), "framework");
 
final VersionInfo ver = mSettings.getInternalVersion();
mIsUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
if (mIsUpgrade) {
    logCriticalInfo(Log.INFO,
            "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT);
}
 
// when upgrading from pre-M, promote system app permissions from install to runtime
mPromoteSystemApps =
        mIsUpgrade && ver.sdkVersion <= Build.VERSION_CODES.LOLLIPOP_MR1;
 
// When upgrading from pre-N, we need to handle package extraction like first boot,
// as there is no profiling data available.
mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;
 
mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
 

13.从M上级上来的系统app加入mExistingSystemPackages列表中,促使安装权限修改为运行时权限

  if (mPromoteSystemApps) {
    Iterator<PackageSetting> pkgSettingIter = mSettings.mPackages.values().iterator();
    while (pkgSettingIter.hasNext()) {
        PackageSetting ps = pkgSettingIter.next();
        if (isSystemApp(ps)) {
            mExistingSystemPackages.add(ps.name);
        }
    }
}
 

14.初始化mCacheDir目录

 mCacheDir = preparePackageParserCache(mIsUpgrade);
 private static File preparePackageParserCache(boolean isUpgrade) {
 
    if (SystemProperties.getBoolean("pm.boot.disable_package_cache", false)) {
        Slog.i(TAG, "Disabling package parser cache due to system property.");
        return null;
    }
 
    // The base directory for the package parser cache lives under /data/system/.
    final File cacheBaseDir = FileUtils.createDir(Environment.getDataSystemDirectory(),
            "package_cache");
    if (cacheBaseDir == null) {
        return null;
    }
    if (isUpgrade) {
        FileUtils.deleteContents(cacheBaseDir);
    }
    // Return the versioned package cache directory. This is something like
    // "/data/system/package_cache/1"
    File cacheDir = FileUtils.createDir(cacheBaseDir, PACKAGE_PARSER_CACHE_VERSION);
    if (cacheDir == null) {
        // Something went wrong. Attempt to delete everything and return.
        Slog.wtf(TAG, "Cache directory cannot be created - wiping base dir " + cacheBaseDir);
        FileUtils.deleteContentsAndDir(cacheBaseDir);
        return null;
    }
 
    if (Build.IS_USERDEBUG && Build.VERSION.INCREMENTAL.startsWith("eng.")) {
        Slog.w(TAG, "Wiping cache directory because the system partition changed.");
        File frameworkDir = new File(Environment.getRootDirectory(), "framework");
        if (cacheDir.lastModified() < frameworkDir.lastModified()) {
            FileUtils.deleteContents(cacheBaseDir);
            cacheDir = FileUtils.createDir(cacheBaseDir, PACKAGE_PARSER_CACHE_VERSION);
        }
    }
    return cacheDir;
}
15.依次扫描vendor、product、system下的app

 scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_VENDOR,
        0);
scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_PRODUCT,
        0);
 
mParallelPackageParserCallback.findStaticOverlayPackages();
 
// Find base frameworks (resource packages without code).
scanDirTracedLI(frameworkDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_NO_DEX
        | SCAN_AS_SYSTEM
        | SCAN_AS_PRIVILEGED,
        0);
 
// Collect privileged system packages.
final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
scanDirTracedLI(privilegedAppDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM
        | SCAN_AS_PRIVILEGED,
        0);
 
// Collect ordinary system packages.
final File systemAppDir = new File(Environment.getRootDirectory(), "app");
scanDirTracedLI(systemAppDir,
        mDefParseFlags
        | PackageParser.PARSE_IS_SYSTEM_DIR,
        scanFlags
        | SCAN_AS_SYSTEM,
        0);
app文件扫描安装流程如下:

扫描过程中重要实体类如下:PackageParser.Package,用于保存全部apk信息。

/**
 * Representation of a full package parsed from APK files on disk. A package
 * consists of a single base APK, and zero or more split APKs.
 */
public final static class Package implements Parcelable {
 
    public String packageName;
 
    // The package name declared in the manifest as the package can be
    // renamed, for example static shared libs use synthetic package names.
    public String manifestPackageName;
 
    /** Names of any split APKs, ordered by parsed splitName */
    public String[] splitNames;
 
    // TODO: work towards making these paths invariant
 
    public String volumeUuid;
 
    /**
     * Path where this package was found on disk. For monolithic packages
     * this is path to single base APK file; for cluster packages this is
     * path to the cluster directory.
     */
    public String codePath;
 
    /** Path of base APK */
    public String baseCodePath;
    /** Paths of any split APKs, ordered by parsed splitName */
    public String[] splitCodePaths;
 
    /** Revision code of base APK */
    public int baseRevisionCode;
    /** Revision codes of any split APKs, ordered by parsed splitName */
    public int[] splitRevisionCodes;
 
    /** Flags of any split APKs; ordered by parsed splitName */
    public int[] splitFlags;
 
    /**
     * Private flags of any split APKs; ordered by parsed splitName.
     *
     * {@hide}
     */
    public int[] splitPrivateFlags;
 
    public boolean baseHardwareAccelerated;
 
    // For now we only support one application per package.
    public ApplicationInfo applicationInfo = new ApplicationInfo();
 
    public final ArrayList<Permission> permissions = new ArrayList<Permission>(0);
    public final ArrayList<PermissionGroup> permissionGroups = new ArrayList<PermissionGroup>(0);
    public final ArrayList<Activity> activities = new ArrayList<Activity>(0);
    public final ArrayList<Activity> receivers = new ArrayList<Activity>(0);
    public final ArrayList<Provider> providers = new ArrayList<Provider>(0);
    public final ArrayList<Service> services = new ArrayList<Service>(0);
    public final ArrayList<Instrumentation> instrumentation = new ArrayList<Instrumentation>(0);
 
    public final ArrayList<String> requestedPermissions = new ArrayList<String>();
 
    public ArrayList<String> protectedBroadcasts;
 
    public Package parentPackage;
    public ArrayList<Package> childPackages;
 
    public String staticSharedLibName = null;
    public long staticSharedLibVersion = 0;
    public ArrayList<String> libraryNames = null;
    public ArrayList<String> usesLibraries = null;
    public ArrayList<String> usesStaticLibraries = null;
    public long[] usesStaticLibrariesVersions = null;
    public String[][] usesStaticLibrariesCertDigests = null;
    public ArrayList<String> usesOptionalLibraries = null;
    public String[] usesLibraryFiles = null;
 
    public ArrayList<ActivityIntentInfo> preferredActivityFilters = null;
 
    public ArrayList<String> mOriginalPackages = null;
    public String mRealPackage = null;
    public ArrayList<String> mAdoptPermissions = null;
 
    // We store the application meta-data independently to avoid multiple unwanted references
    public Bundle mAppMetaData = null;
 
    // The version code declared for this package.
    public int mVersionCode;
 
    // The major version code declared for this package.
    public int mVersionCodeMajor;
 
    // Return long containing mVersionCode and mVersionCodeMajor.
    public long getLongVersionCode() {
        return PackageInfo.composeLongVersionCode(mVersionCodeMajor, mVersionCode);
    }
 
    // The version name declared for this package.
    public String mVersionName;
 
    // The shared user id that this package wants to use.
    public String mSharedUserId;
 
    // The shared user label that this package wants to use.
    public int mSharedUserLabel;
 
    // Signatures that were read from the package.
    @NonNull public SigningDetails mSigningDetails = SigningDetails.UNKNOWN;
 
    // For use by package manager service for quick lookup of
    // preferred up order.
    public int mPreferredOrder = 0;
 
    // For use by package manager to keep track of when a package was last used.
    public long[] mLastPackageUsageTimeInMills =
            new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
 
    // // User set enabled state.
    // public int mSetEnabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
    //
    // // Whether the package has been stopped.
    // public boolean mSetStopped = false;
 
    // Additional data supplied by callers.
    public Object mExtras;
 
    // Applications hardware preferences
    public ArrayList<ConfigurationInfo> configPreferences = null;
 
    // Applications requested features
    public ArrayList<FeatureInfo> reqFeatures = null;
 
    // Applications requested feature groups
    public ArrayList<FeatureGroupInfo> featureGroups = null;
 
    public int installLocation;
 
    public boolean coreApp;
 
    /* An app that's required for all users and cannot be uninstalled for a user */
    public boolean mRequiredForAllUsers;
 
    /* The restricted account authenticator type that is used by this application */
    public String mRestrictedAccountType;
 
    /* The required account type without which this application will not function */
    public String mRequiredAccountType;
 
    public String mOverlayTarget;
    public String mOverlayCategory;
    public int mOverlayPriority;
    public boolean mOverlayIsStatic;
 
    public int mCompileSdkVersion;
    public String mCompileSdkVersionCodename;
 
    /**
     * Data used to feed the KeySetManagerService
     */
    public ArraySet<String> mUpgradeKeySets;
    public ArrayMap<String, ArraySet<PublicKey>> mKeySetMapping;
 
    /**
     * The install time abi override for this package, if any.
     *
     * TODO: This seems like a horrible place to put the abiOverride because
     * this isn't something the packageParser parsers. However, this fits in with
     * the rest of the PackageManager where package scanning randomly pushes
     * and prods fields out of {@code this.applicationInfo}.
     */
    public String cpuAbiOverride;
    /**
     * The install time abi override to choose 32bit abi's when multiple abi's
     * are present. This is only meaningfull for multiarch applications.
     * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
     */
    public boolean use32bitAbi;
 
    public byte[] restrictUpdateHash;
 
    /** Set if the app or any of its components are visible to instant applications. */
    public boolean visibleToInstantApps;
    /** Whether or not the package is a stub and must be replaced by the full version. */
    public boolean isStub;
 16.对于非核心应用,处理Stub packages跟已经disable状态的应用

final Iterator<PackageParser.Package> pkgIterator = mPackages.values().iterator();
while (pkgIterator.hasNext()) {
    final PackageParser.Package pkg = pkgIterator.next();
    if (pkg.isStub) {
        stubSystemApps.add(pkg.packageName);
    }
}
 /*
 * If the package is scanned, it's not erased.
 */
final PackageParser.Package scannedPkg = mPackages.get(ps.name);
if (scannedPkg != null) {
    /*
     * If the system app is both scanned and in the
     * disabled packages list, then it must have been
     * added via OTA. Remove it from the currently
     * scanned package so the previously user-installed
     * application can be scanned.
     */
    if (mSettings.isDisabledSystemPackageLPr(ps.name)) {
        logCriticalInfo(Log.WARN,
                "Expecting better updated system app for " + ps.name
                + "; removing system app.  Last known"
                + " codePath=" + ps.codePathString
                + ", versionCode=" + ps.versionCode
                + "; scanned versionCode=" + scannedPkg.getLongVersionCode());
        removePackageLI(scannedPkg, true);
        mExpectingBetter.put(ps.name, ps.codePath);
    }
 
    continue;
}
private void removePackageLI(PackageParser.Package pkg, boolean chatty) {
    // Remove the parent package setting
    PackageSetting ps = (PackageSetting) pkg.mExtras;
    if (ps != null) {
        removePackageLI(ps, chatty);
    }
    // Remove the child package setting
    final int childCount = (pkg.childPackages != null) ? pkg.childPackages.size() : 0;
    for (int i = 0; i < childCount; i++) {
        PackageParser.Package childPkg = pkg.childPackages.get(i);
        ps = (PackageSetting) childPkg.mExtras;
        if (ps != null) {
            removePackageLI(ps, chatty);
        }
    }
}
 
void removePackageLI(PackageSetting ps, boolean chatty) {
    if (DEBUG_INSTALL) {
        if (chatty)
            Log.d(TAG, "Removing package " + ps.name);
    }
 
    // writer
    synchronized (mPackages) {
        mPackages.remove(ps.name);
        final PackageParser.Package pkg = ps.pkg;
        if (pkg != null) {
            cleanPackageDataStructuresLILPw(pkg, chatty);
        }
    }
}
17.删除中间文件:vmdl开头并且.tmp结束

 private void deleteTempPackageFiles() {
    final FilenameFilter filter = new FilenameFilter() {
        public boolean accept(File dir, String name) {
            return name.startsWith("vmdl") && name.endsWith(".tmp");
        }
    };
    for (File file : sDrmAppPrivateInstallDir.listFiles(filter)) {
        file.delete();
    }
}
18.扫描data目录apk文件

scanDirTracedLI(sAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
 
scanDirTracedLI(sDrmAppPrivateInstallDir, mDefParseFlags
        | PackageParser.PARSE_FORWARD_LOCK,
        scanFlags | SCAN_REQUIRE_KNOWN, 0);
19.移除OTA升级后被禁用的app

 // Remove disable package settings for updated system apps that were
// removed via an OTA. If the update is no longer present, remove the
// app completely. Otherwise, revoke their system privileges.
for (String deletedAppName : possiblyDeletedUpdatedSystemApps) {
    PackageParser.Package deletedPkg = mPackages.get(deletedAppName);
    mSettings.removeDisabledSystemPackageLPw(deletedAppName);
    final String msg;
    if (deletedPkg == null) {
        // should have found an update, but, we didn't; remove everything
        msg = "Updated system package " + deletedAppName
                + " no longer exists; removing its data";
        // Actual deletion of code and data will be handled by later
        // reconciliation step
    } else {
        // found an update; revoke system privileges
        msg = "Updated system package + " + deletedAppName
                + " no longer exists; revoking system privileges";
 
        // Don't do anything if a stub is removed from the system image. If
        // we were to remove the uncompressed version from the /data partition,
        // this is where it'd be done.
 
        final PackageSetting deletedPs = mSettings.mPackages.get(deletedAppName);
        deletedPkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
        deletedPs.pkgFlags &= ~ApplicationInfo.FLAG_SYSTEM;
    }
    logCriticalInfo(Log.WARN, msg);
}
20.回滚所有通过ota升级后系统分区优于data分区的应用

/*
 * Make sure all system apps that we expected to appear on
 * the userdata partition actually showed up. If they never
 * appeared, crawl back and revive the system version.
 */
for (int i = 0; i < mExpectingBetter.size(); i++) {
    final String packageName = mExpectingBetter.keyAt(i);
    if (!mPackages.containsKey(packageName)) {
        final File scanFile = mExpectingBetter.valueAt(i);
 
        logCriticalInfo(Log.WARN, "Expected better " + packageName
                + " but never showed up; reverting to system");
 
        final @ParseFlags int reparseFlags;
        final @ScanFlags int rescanFlags;
        if (FileUtils.contains(privilegedAppDir, scanFile)) {
            reparseFlags =
                    mDefParseFlags |
                    PackageParser.PARSE_IS_SYSTEM_DIR;
            rescanFlags =
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRIVILEGED;
        } else if (FileUtils.contains(systemAppDir, scanFile)) {
            reparseFlags =
                    mDefParseFlags |
                    PackageParser.PARSE_IS_SYSTEM_DIR;
            rescanFlags =
                    scanFlags
                    | SCAN_AS_SYSTEM;
        } else if (FileUtils.contains(privilegedVendorAppDir, scanFile)
                || FileUtils.contains(privilegedOdmAppDir, scanFile)) {
            reparseFlags =
                    mDefParseFlags |
                    PackageParser.PARSE_IS_SYSTEM_DIR;
            rescanFlags =
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR
                    | SCAN_AS_PRIVILEGED;
        } else if (FileUtils.contains(vendorAppDir, scanFile)
                || FileUtils.contains(odmAppDir, scanFile)) {
            reparseFlags =
                    mDefParseFlags |
                    PackageParser.PARSE_IS_SYSTEM_DIR;
            rescanFlags =
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR;
        } else if (FileUtils.contains(oemAppDir, scanFile)) {
            reparseFlags =
                    mDefParseFlags |
                    PackageParser.PARSE_IS_SYSTEM_DIR;
            rescanFlags =
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_OEM;
        } else if (FileUtils.contains(privilegedProductAppDir, scanFile)) {
            reparseFlags =
                    mDefParseFlags |
                    PackageParser.PARSE_IS_SYSTEM_DIR;
            rescanFlags =
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRODUCT
                    | SCAN_AS_PRIVILEGED;
        } else if (FileUtils.contains(productAppDir, scanFile)) {
            reparseFlags =
                    mDefParseFlags |
                    PackageParser.PARSE_IS_SYSTEM_DIR;
            rescanFlags =
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRODUCT;
        } else {
            Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
            continue;
        }
 
        mSettings.enableSystemPackageLPw(packageName);
 
        try {
            scanPackageTracedLI(scanFile, reparseFlags, rescanFlags, 0, null);
        } catch (PackageManagerException e) {
            Slog.e(TAG, "Failed to parse original system package: "
                    + e.getMessage());
        }
    }
}
21.解压和安装stubbed system applications

// Uncompress and install any stubbed system applications.
// This must be done last to ensure all stubs are replaced or disabled.
decompressSystemApplications(stubSystemApps, scanFlags);
 private void decompressSystemApplications(@NonNull List<String> stubSystemApps, int scanFlags) {
    for (int i = stubSystemApps.size() - 1; i >= 0; --i) {
        final String pkgName = stubSystemApps.get(i);
        // skip if the system package is already disabled
        if (mSettings.isDisabledSystemPackageLPr(pkgName)) {
            stubSystemApps.remove(i);
            continue;
        }
        // skip if the package isn't installed (?!); this should never happen
        final PackageParser.Package pkg = mPackages.get(pkgName);
        if (pkg == null) {
            stubSystemApps.remove(i);
            continue;
        }
        // skip if the package has been disabled by the user
        final PackageSetting ps = mSettings.mPackages.get(pkgName);
        if (ps != null) {
            final int enabledState = ps.getEnabled(UserHandle.USER_SYSTEM);
            if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
                stubSystemApps.remove(i);
                continue;
            }
        }
 
        if (DEBUG_COMPRESSION) {
            Slog.i(TAG, "Uncompressing system stub; pkg: " + pkgName);
        }
 
        // uncompress the binary to its eventual destination on /data
        final File scanFile = decompressPackage(pkg);
        if (scanFile == null) {
            continue;
        }
 
        // install the package to replace the stub on /system
        try {
            mSettings.disableSystemPackageLPw(pkgName, true /*replaced*/);
            removePackageLI(pkg, true /*chatty*/);
            scanPackageTracedLI(scanFile, 0 /*reparseFlags*/, scanFlags, 0, null);
            ps.setEnabled(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
                    UserHandle.USER_SYSTEM, "android");
            stubSystemApps.remove(i);
            continue;
        } catch (PackageManagerException e) {
            Slog.e(TAG, "Failed to parse uncompressed system package: " + e.getMessage());
        }
 
        // any failed attempt to install the package will be cleaned up later
    }
 
    // disable any stub still left; these failed to install the full application
    for (int i = stubSystemApps.size() - 1; i >= 0; --i) {
        final String pkgName = stubSystemApps.get(i);
        final PackageSetting ps = mSettings.mPackages.get(pkgName);
        ps.setEnabled(PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                UserHandle.USER_SYSTEM, "android");
        logCriticalInfo(Log.ERROR, "Stub disabled; pkg: " + pkgName);
    }
}
22.解决受保护action过滤,只有setup wizard才允许优先级设置为0

 // Resolve protected action filters. Only the setup wizard is allowed to
// have a high priority filter for these actions.
mSetupWizardPackage = getSetupWizardPackageName();
if (mProtectedFilters.size() > 0) {
    if (DEBUG_FILTERS && mSetupWizardPackage == null) {
        Slog.i(TAG, "No setup wizard;"
            + " All protected intents capped to priority 0");
    }
    for (ActivityIntentInfo filter : mProtectedFilters) {
        if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {
            if (DEBUG_FILTERS) {
                Slog.i(TAG, "Found setup wizard;"
                    + " allow priority " + filter.getPriority() + ";"
                    + " package: " + filter.activity.info.packageName
                    + " activity: " + filter.activity.className
                    + " priority: " + filter.getPriority());
            }
            // skip setup wizard; allow it to keep the high priority filter
            continue;
        }
        if (DEBUG_FILTERS) {
            Slog.i(TAG, "Protected action; cap priority to 0;"
                    + " package: " + filter.activity.info.packageName
                    + " activity: " + filter.activity.className
                    + " origPrio: " + filter.getPriority());
        }
        filter.setPriority(0);
    }
}
23.更新shared library信息,让所有client得到正确路径

 // Now that we know all of the shared libraries, update all clients to have
// the correct library paths.
updateAllSharedLibrariesLPw(null);
 

 private ArrayList<PackageParser.Package> updateAllSharedLibrariesLPw(
        PackageParser.Package changingPkg) {
    ArrayList<PackageParser.Package> res = null;
    for (PackageParser.Package pkg : mPackages.values()) {
        if (changingPkg != null
                && !hasString(pkg.usesLibraries, changingPkg.libraryNames)
                && !hasString(pkg.usesOptionalLibraries, changingPkg.libraryNames)
                && !ArrayUtils.contains(pkg.usesStaticLibraries,
                        changingPkg.staticSharedLibName)) {
            return null;
        }
        if (res == null) {
            res = new ArrayList<>();
        }
        res.add(pkg);
        try {
            updateSharedLibrariesLPr(pkg, changingPkg);
        } catch (PackageManagerException e) {
            // If a system app update or an app and a required lib missing we
            // delete the package and for updated system apps keep the data as
            // it is better for the user to reinstall than to be in an limbo
            // state. Also libs disappearing under an app should never happen
            // - just in case.
            if (!pkg.isSystem() || pkg.isUpdatedSystemApp()) {
                final int flags = pkg.isUpdatedSystemApp()
                        ? PackageManager.DELETE_KEEP_DATA : 0;
                deletePackageLIF(pkg.packageName, null, true, sUserManager.getUserIds(),
                        flags , null, true, null);
            }
            Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
        }
    }
    return res;
}
24.更新所有package、permission信息

mPermissionManager.updateAllPermissions(
        StorageManager.UUID_PRIVATE_INTERNAL, sdkUpdated, mPackages.values(),
        mPermissionCallback);
        
if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
    for (UserInfo user : sUserManager.getUsers(true)) {
        mSettings.applyDefaultPreferredAppsLPw(this, user.id);
        applyFactoryDefaultBrowserLPw(user.id);
        primeDomainVerificationsLPw(user.id);
    }

25.为开机过程启动较早的应用准备存储空间,比如systemui,SettingsProvider

// Prepare storage for system user really early during boot,
// since core system apps like SettingsProvider and SystemUI
// can't wait for user to start
final int storageFlags;
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
    storageFlags = StorageManager.FLAG_STORAGE_DE;
} else {
    storageFlags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
}
List<String> deferPackages = reconcileAppsDataLI(StorageManager.UUID_PRIVATE_INTERNAL,
        UserHandle.USER_SYSTEM, storageFlags, true /* migrateAppData */,
        true /* onlyCoreApps */);
mPrepareAppDataFuture = SystemServerInitThreadPool.get().submit(() -> {
    TimingsTraceLog traceLog = new TimingsTraceLog("SystemServerTimingAsync",
            Trace.TRACE_TAG_PACKAGE_MANAGER);
    traceLog.traceBegin("AppDataFixup");
    try {
        mInstaller.fixupAppData(StorageManager.UUID_PRIVATE_INTERNAL,
                StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE);
    } catch (InstallerException e) {
        Slog.w(TAG, "Trouble fixing GIDs", e);
    }
    traceLog.traceEnd();
 
    traceLog.traceBegin("AppDataPrepare");
    if (deferPackages == null || deferPackages.isEmpty()) {
        return;
    }
    int count = 0;
    for (String pkgName : deferPackages) {
        PackageParser.Package pkg = null;
        synchronized (mPackages) {
            PackageSetting ps = mSettings.getPackageLPr(pkgName);
            if (ps != null && ps.getInstalled(UserHandle.USER_SYSTEM)) {
                pkg = ps.pkg;
            }
        }
        if (pkg != null) {
            synchronized (mInstallLock) {
                prepareAppDataAndMigrateLIF(pkg, UserHandle.USER_SYSTEM, storageFlags,
                        true /* maybeMigrateAppData */);
            }
            count++;
        }
    }
    traceLog.traceEnd();
    Slog.i(TAG, "Deferred reconcileAppsData finished " + count + " packages");
}, "prepareAppData");
26.OTA后的首次正常启动,清除应用code cache

 if (mIsUpgrade && !onlyCore) {
    Slog.i(TAG, "Build fingerprint changed; clearing code caches");
    for (int i = 0; i < mSettings.mPackages.size(); i++) {
        final PackageSetting ps = mSettings.mPackages.valueAt(i);
        if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, ps.volumeUuid)) {
            // No apps are running this early, so no need to freeze
            clearAppDataLIF(ps.pkg, UserHandle.USER_ALL,
                    StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE
                            | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
        }
    }
    ver.fingerprint = Build.FINGERPRINT;
}
27.调用mSettings.writeLPr()将最新包、权限信息更新到系统文件中

mSettings.writeLPr();
 

void writeLPr() {
    //Debug.startMethodTracing("/data/system/packageprof", 8 * 1024 * 1024);
 
    final long startTime = SystemClock.uptimeMillis();
 
    // Keep the old settings around until we know the new ones have
    // been successfully written.
    if (mSettingsFilename.exists()) {
        // Presence of backup settings file indicates that we failed
        // to persist settings earlier. So preserve the older
        // backup for future reference since the current settings
        // might have been corrupted.
        if (!mBackupSettingsFilename.exists()) {
            if (!mSettingsFilename.renameTo(mBackupSettingsFilename)) {
                Slog.wtf(PackageManagerService.TAG,
                        "Unable to backup package manager settings, "
                        + " current changes will be lost at reboot");
                return;
            }
        } else {
            mSettingsFilename.delete();
            Slog.w(PackageManagerService.TAG, "Preserving older settings backup");
        }
    }
 
    mPastSignatures.clear();
 
    try {
        FileOutputStream fstr = new FileOutputStream(mSettingsFilename);
        BufferedOutputStream str = new BufferedOutputStream(fstr);
 
        //XmlSerializer serializer = XmlUtils.serializerInstance();
        XmlSerializer serializer = new FastXmlSerializer();
        serializer.setOutput(str, StandardCharsets.UTF_8.name());
        serializer.startDocument(null, true);
        serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
 
        serializer.startTag(null, "packages");
 
        for (int i = 0; i < mVersion.size(); i++) {
            final String volumeUuid = mVersion.keyAt(i);
            final VersionInfo ver = mVersion.valueAt(i);
 
            serializer.startTag(null, TAG_VERSION);
            XmlUtils.writeStringAttribute(serializer, ATTR_VOLUME_UUID, volumeUuid);
            XmlUtils.writeIntAttribute(serializer, ATTR_SDK_VERSION, ver.sdkVersion);
            XmlUtils.writeIntAttribute(serializer, ATTR_DATABASE_VERSION, ver.databaseVersion);
            XmlUtils.writeStringAttribute(serializer, ATTR_FINGERPRINT, ver.fingerprint);
            serializer.endTag(null, TAG_VERSION);
        }
 
        if (mVerifierDeviceIdentity != null) {
            serializer.startTag(null, "verifier");
            serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
            serializer.endTag(null, "verifier");
        }
 
        if (mReadExternalStorageEnforced != null) {
            serializer.startTag(null, TAG_READ_EXTERNAL_STORAGE);
            serializer.attribute(
                    null, ATTR_ENFORCEMENT, mReadExternalStorageEnforced ? "1" : "0");
            serializer.endTag(null, TAG_READ_EXTERNAL_STORAGE);
        }
 
        serializer.startTag(null, "permission-trees");
        mPermissions.writePermissionTrees(serializer);
        serializer.endTag(null, "permission-trees");
 
        serializer.startTag(null, "permissions");
        mPermissions.writePermissions(serializer);
        serializer.endTag(null, "permissions");
 
        for (final PackageSetting pkg : mPackages.values()) {
            writePackageLPr(serializer, pkg);
        }
 
        for (final PackageSetting pkg : mDisabledSysPackages.values()) {
            writeDisabledSysPackageLPr(serializer, pkg);
        }
 
        for (final SharedUserSetting usr : mSharedUsers.values()) {
            serializer.startTag(null, "shared-user");
            serializer.attribute(null, ATTR_NAME, usr.name);
            serializer.attribute(null, "userId",
                    Integer.toString(usr.userId));
            usr.signatures.writeXml(serializer, "sigs", mPastSignatures);
            writePermissionsLPr(serializer, usr.getPermissionsState()
                    .getInstallPermissionStates());
            serializer.endTag(null, "shared-user");
        }
 
        if (mPackagesToBeCleaned.size() > 0) {
            for (PackageCleanItem item : mPackagesToBeCleaned) {
                final String userStr = Integer.toString(item.userId);
                serializer.startTag(null, "cleaning-package");
                serializer.attribute(null, ATTR_NAME, item.packageName);
                serializer.attribute(null, ATTR_CODE, item.andCode ? "true" : "false");
                serializer.attribute(null, ATTR_USER, userStr);
                serializer.endTag(null, "cleaning-package");
            }
        }
 
        if (mRenamedPackages.size() > 0) {
            for (Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
                serializer.startTag(null, "renamed-package");
                serializer.attribute(null, "new", e.getKey());
                serializer.attribute(null, "old", e.getValue());
                serializer.endTag(null, "renamed-package");
            }
        }
 
        final int numIVIs = mRestoredIntentFilterVerifications.size();
        if (numIVIs > 0) {
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.i(TAG, "Writing restored-ivi entries to packages.xml");
            }
            serializer.startTag(null, "restored-ivi");
            for (int i = 0; i < numIVIs; i++) {
                IntentFilterVerificationInfo ivi = mRestoredIntentFilterVerifications.valueAt(i);
                writeDomainVerificationsLPr(serializer, ivi);
            }
            serializer.endTag(null, "restored-ivi");
        } else {
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.i(TAG, "  no restored IVI entries to write");
            }
        }
 
        mKeySetManagerService.writeKeySetManagerServiceLPr(serializer);
 
        serializer.endTag(null, "packages");
 
        serializer.endDocument();
 
        str.flush();
        FileUtils.sync(fstr);
        str.close();
 
        // New settings successfully written, old ones are no longer
        // needed.
        mBackupSettingsFilename.delete();
        FileUtils.setPermissions(mSettingsFilename.toString(),
                FileUtils.S_IRUSR|FileUtils.S_IWUSR
                |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
                -1, -1);
 
        writeKernelMappingLPr();
        writePackageListLPr();
        writeAllUsersPackageRestrictionsLPr();
        writeAllRuntimePermissionsLPr();
        com.android.internal.logging.EventLogTags.writeCommitSysConfigFile(
                "package", SystemClock.uptimeMillis() - startTime);
        return;
 
    } catch(java.io.IOException e) {
        Slog.wtf(PackageManagerService.TAG, "Unable to write package manager settings, "
                + "current changes will be lost at reboot", e);
    }
    // Clean up partially written files
    if (mSettingsFilename.exists()) {
        if (!mSettingsFilename.delete()) {
            Slog.wtf(PackageManagerService.TAG, "Failed to clean up mangled file: "
                    + mSettingsFilename);
        }
    }
    //Debug.stopMethodTracing();
}
 

这篇关于PMS构造函数流程分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/370045

相关文章

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者

MOLE 2.5 分析分子通道和孔隙

软件介绍 生物大分子通道和孔隙在生物学中发挥着重要作用,例如在分子识别和酶底物特异性方面。 我们介绍了一种名为 MOLE 2.5 的高级软件工具,该工具旨在分析分子通道和孔隙。 与其他可用软件工具的基准测试表明,MOLE 2.5 相比更快、更强大、功能更丰富。作为一项新功能,MOLE 2.5 可以估算已识别通道的物理化学性质。 软件下载 https://pan.quark.cn/s/57

衡石分析平台使用手册-单机安装及启动

单机安装及启动​ 本文讲述如何在单机环境下进行 HENGSHI SENSE 安装的操作过程。 在安装前请确认网络环境,如果是隔离环境,无法连接互联网时,请先按照 离线环境安装依赖的指导进行依赖包的安装,然后按照本文的指导继续操作。如果网络环境可以连接互联网,请直接按照本文的指导进行安装。 准备工作​ 请参考安装环境文档准备安装环境。 配置用户与安装目录。 在操作前请检查您是否有 sud

线性因子模型 - 独立分量分析(ICA)篇

序言 线性因子模型是数据分析与机器学习中的一类重要模型,它们通过引入潜变量( latent variables \text{latent variables} latent variables)来更好地表征数据。其中,独立分量分析( ICA \text{ICA} ICA)作为线性因子模型的一种,以其独特的视角和广泛的应用领域而备受关注。 ICA \text{ICA} ICA旨在将观察到的复杂信号

【软考】希尔排序算法分析

目录 1. c代码2. 运行截图3. 运行解析 1. c代码 #include <stdio.h>#include <stdlib.h> void shellSort(int data[], int n){// 划分的数组,例如8个数则为[4, 2, 1]int *delta;int k;// i控制delta的轮次int i;// 临时变量,换值int temp;in

三相直流无刷电机(BLDC)控制算法实现:BLDC有感启动算法思路分析

一枚从事路径规划算法、运动控制算法、BLDC/FOC电机控制算法、工控、物联网工程师,爱吃土豆。如有需要技术交流或者需要方案帮助、需求:以下为联系方式—V 方案1:通过霍尔传感器IO中断触发换相 1.1 整体执行思路 霍尔传感器U、V、W三相通过IO+EXIT中断的方式进行霍尔传感器数据的读取。将IO口配置为上升沿+下降沿中断触发的方式。当霍尔传感器信号发生发生信号的变化就会触发中断在中断

kubelet组件的启动流程源码分析

概述 摘要: 本文将总结kubelet的作用以及原理,在有一定基础认识的前提下,通过阅读kubelet源码,对kubelet组件的启动流程进行分析。 正文 kubelet的作用 这里对kubelet的作用做一个简单总结。 节点管理 节点的注册 节点状态更新 容器管理(pod生命周期管理) 监听apiserver的容器事件 容器的创建、删除(CRI) 容器的网络的创建与删除