zoukankan      html  css  js  c++  java
  • Android 1.6 PackageManagerService源码分析

    文件清单

    frameworkaseservicescorejavacomandroidserverpmPackageManagerService.java

    PackageManagerService.rar (已经带有文字注释的文件

    下面截取部分介绍

    1 PMS初始化

    1     public static final IPackageManager main(Context context, boolean factoryTest) {
    2         PackageManagerService m = new PackageManagerService(context, factoryTest);
    3         ServiceManager.addService("package", m);
    4         return m;
    5     }

    2 构造函数

      1 public PackageManagerService(Context context, boolean factoryTest) {
      2         EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_START,
      3                 SystemClock.uptimeMillis());
      4         
      5         if (mSdkVersion <= 0) {
      6             Log.w(TAG, "**** ro.build.version.sdk not set!");
      7         }
      8         
      9         mContext = context;
     10         mFactoryTest = factoryTest;
     11         mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
     12         mMetrics = new DisplayMetrics();
     13         mSettings = new Settings();
     14         mSettings.addSharedUserLP("android.uid.system",
     15                 Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
     16         mSettings.addSharedUserLP("android.uid.phone",
     17                 MULTIPLE_APPLICATION_UIDS
     18                         ? RADIO_UID : FIRST_APPLICATION_UID,
     19                 ApplicationInfo.FLAG_SYSTEM);
     20 
     21         String separateProcesses = SystemProperties.get("debug.separate_processes");
     22         if (separateProcesses != null && separateProcesses.length() > 0) {
     23             if ("*".equals(separateProcesses)) {
     24                 mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;
     25                 mSeparateProcesses = null;
     26                 Log.w(TAG, "Running with debug.separate_processes: * (ALL)");
     27             } else {
     28                 mDefParseFlags = 0;
     29                 mSeparateProcesses = separateProcesses.split(",");
     30                 Log.w(TAG, "Running with debug.separate_processes: "
     31                         + separateProcesses);
     32             }
     33         } else {
     34             mDefParseFlags = 0;
     35             mSeparateProcesses = null;
     36         }
     37         
     38         Installer installer = new Installer();
     39         // Little hacky thing to check if installd is here, to determine
     40         // whether we are running on the simulator and thus need to take
     41         // care of building the /data file structure ourself.
     42         // (apparently the sim now has a working installer)
     43         if (installer.ping() && Process.supportsProcesses()) {
     44             mInstaller = installer;
     45         } else {
     46             mInstaller = null;
     47         }
     48 
     49         WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
     50         Display d = wm.getDefaultDisplay();
     51         d.getMetrics(mMetrics);
     52 
     53         synchronized (mInstallLock) {
     54         synchronized (mPackages) {
     55             mHandlerThread.start();
     56             mHandler = new Handler(mHandlerThread.getLooper());
     57             
     58             // data目录
     59             File dataDir = Environment.getDataDirectory();
     60             // 目录:data/data
     61             mAppDataDir = new File(dataDir, "data");
     62             // 目录:data/app-private
     63             mDrmAppPrivateInstallDir = new File(dataDir, "app-private");
     64 
     65             if (mInstaller == null) {
     66                 // Make sure these dirs exist, when we are running in
     67                 // the simulator.
     68                 // Make a wide-open directory for random misc stuff.
     69                 File miscDir = new File(dataDir, "misc");
     70                 miscDir.mkdirs();
     71                 mAppDataDir.mkdirs();
     72                 mDrmAppPrivateInstallDir.mkdirs();
     73             }
     74 
     75             // 读:system/etc/permissions/platform.xml 等xml文件
     76             readPermissions();
     77 
     78             mRestoredSettings = mSettings.readLP();
     79             long startTime = SystemClock.uptimeMillis();
     80             
     81             EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START,
     82                     startTime);
     83             
     84             int scanMode = SCAN_MONITOR;
     85             if (mNoDexOpt) {
     86                 Log.w(TAG, "Running ENG build: no pre-dexopt!");
     87                 scanMode |= SCAN_NO_DEX; 
     88             }
     89             
     90             final HashSet<String> libFiles = new HashSet<String>();
     91             
     92             // 目录:system/framework
     93             mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
     94             
     95             if (mInstaller != null) {
     96                 /**
     97                  * Out of paranoia, ensure that everything in the boot class
     98                  * path has been dexed.
     99                  */
    100                 String bootClassPath = System.getProperty("java.boot.class.path");
    101                 if (bootClassPath != null) {
    102                     String[] paths = splitString(bootClassPath, ':');
    103                     for (int i=0; i<paths.length; i++) {
    104                         try {
    105                             if (dalvik.system.DexFile.isDexOptNeeded(paths[i])) {
    106                                 libFiles.add(paths[i]);
    107                                 // 执行 dexopt 命令
    108                                 mInstaller.dexopt(paths[i], Process.SYSTEM_UID, true);
    109                             }
    110                         } catch (FileNotFoundException e) {
    111                             Log.w(TAG, "Boot class path not found: " + paths[i]);
    112                         } catch (IOException e) {
    113                             Log.w(TAG, "Exception reading boot class path: " + paths[i], e);
    114                         }
    115                     }
    116                 } else {
    117                     Log.w(TAG, "No BOOTCLASSPATH found!");
    118                 }
    119                 
    120                 /**
    121                  * Also ensure all external libraries have had dexopt run on them.
    122                  */
    123                 if (mSharedLibraries.size() > 0) {
    124                     Iterator<String> libs = mSharedLibraries.values().iterator();
    125                     while (libs.hasNext()) {
    126                         String lib = libs.next();
    127                         try {
    128                             if (dalvik.system.DexFile.isDexOptNeeded(lib)) {
    129                                 libFiles.add(lib);
    130                                 // 执行 dexopt 命令
    131                                 mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
    132                             }
    133                         } catch (FileNotFoundException e) {
    134                             Log.w(TAG, "Library not found: " + lib);
    135                         } catch (IOException e) {
    136                             Log.w(TAG, "Exception reading library: " + lib, e);
    137                         }
    138                     }
    139                 }
    140                 
    141                 // 目录:system/framework/framework-res.apk
    142                 // Gross hack for now: we know this file doesn't contain any
    143                 // code, so don't dexopt it to avoid the resulting log spew.
    144                 libFiles.add(mFrameworkDir.getPath() + "/framework-res.apk");
    145                 
    146                 /**
    147                  * And there are a number of commands implemented in Java, which
    148                  * we currently need to do the dexopt on so that they can be
    149                  * run from a non-root shell.
    150                  */
    151                 String[] frameworkFiles = mFrameworkDir.list(); // 列出 framework目录下所有文件
    152                 if (frameworkFiles != null && mInstaller != null) {
    153                     for (int i=0; i<frameworkFiles.length; i++) {
    154                         File libPath = new File(mFrameworkDir, frameworkFiles[i]);
    155                         String path = libPath.getPath();
    156                         // Skip the file if we alrady did it.
    157                         if (libFiles.contains(path)) {
    158                             continue;
    159                         }
    160                         // Skip the file if it is not a type we want to dexopt.
    161                         if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
    162                             continue;
    163                         }
    164                         try {
    165                             if (dalvik.system.DexFile.isDexOptNeeded(path)) {
    166                                 // 执行 dexopt命令 apk & jar
    167                                 mInstaller.dexopt(path, Process.SYSTEM_UID, true);
    168                             }
    169                         } catch (FileNotFoundException e) {
    170                             Log.w(TAG, "Jar not found: " + path);
    171                         } catch (IOException e) {
    172                             Log.w(TAG, "Exception reading jar: " + path, e);
    173                         }
    174                     }
    175                 }
    176             }
    177             
    178             mFrameworkInstallObserver = new AppDirObserver(
    179                 mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
    180             mFrameworkInstallObserver.startWatching();
    181             // 扫描 system/framework 目录
    182             scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
    183                     scanMode | SCAN_NO_DEX);
    184             mSystemAppDir = new File(Environment.getRootDirectory(), "app");
    185             mSystemInstallObserver = new AppDirObserver(
    186                 mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
    187             mSystemInstallObserver.startWatching();
    188             // 扫描 system/app 目录
    189             scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
    190             // data/app 目录
    191             mAppInstallDir = new File(dataDir, "app");
    192             if (mInstaller == null) {
    193                 // Make sure these dirs exist, when we are running in
    194                 // the simulator.
    195                 mAppInstallDir.mkdirs(); // scanDirLI() assumes this dir exists // 创建 data/app目录
    196             }
    197             // 搜索未安装完成的程序包
    198             //look for any incomplete package installations
    199             ArrayList<String> deletePkgsList = mSettings.getListOfIncompleteInstallPackages();
    200             //clean up list
    201             for(int i = 0; i < deletePkgsList.size(); i++) {
    202                 //clean up here
    203                 cleanupInstallFailedPackage(deletePkgsList.get(i)); // 清理安装失败的包
    204             }
    205             //delete tmp files
    206             deleteTempPackageFiles();
    207             
    208             EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_DATA_SCAN_START,
    209                     SystemClock.uptimeMillis());
    210             mAppInstallObserver = new AppDirObserver(
    211                 mAppInstallDir.getPath(), OBSERVER_EVENTS, false);
    212             mAppInstallObserver.startWatching();
    213             // 扫描 data/app 目录
    214             scanDirLI(mAppInstallDir, 0, scanMode);
    215 
    216             mDrmAppInstallObserver = new AppDirObserver(
    217                 mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false);
    218             mDrmAppInstallObserver.startWatching();
    219             // 扫描 data/app-private 目录
    220             scanDirLI(mDrmAppPrivateInstallDir, 0, scanMode | SCAN_FORWARD_LOCKED);
    221 
    222             EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_SCAN_END,
    223                     SystemClock.uptimeMillis());
    224             Log.i(TAG, "Time to scan packages: "
    225                     + ((SystemClock.uptimeMillis()-startTime)/1000f)
    226                     + " seconds");
    227 
    228             updatePermissionsLP();
    229 
    230             // 初始化后
    231             mSettings.writeLP();
    232 
    233             EventLog.writeEvent(LOG_BOOT_PROGRESS_PMS_READY,
    234                     SystemClock.uptimeMillis());
    235             
    236             // Now after opening every single application zip, make sure they
    237             // are all flushed.  Not really needed, but keeps things nice and
    238             // tidy.
    239             Runtime.getRuntime().gc();
    240         } // synchronized (mPackages)
    241         } // synchronized (mInstallLock)
    242     }

    2.1 readPermissions()

     1 void readPermissions() {
     2         // Read permissions from .../etc/permission directory.
     3         File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");
     4         if (!libraryDir.exists() || !libraryDir.isDirectory()) {
     5             Log.w(TAG, "No directory " + libraryDir + ", skipping");
     6             return;
     7         }
     8         if (!libraryDir.canRead()) {
     9             Log.w(TAG, "Directory " + libraryDir + " cannot be read");
    10             return;
    11         }
    12 
    13         // Iterate over the files in the directory and scan .xml files
    14         for (File f : libraryDir.listFiles()) {
    15             // We'll read platform.xml last
    16             if (f.getPath().endsWith("etc/permissions/platform.xml")) {
    17                 continue;
    18             }
    19             
    20             if (!f.getPath().endsWith(".xml")) {
    21                 Log.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
    22                 continue;
    23             }
    24             if (!f.canRead()) {
    25                 Log.w(TAG, "Permissions library file " + f + " cannot be read");
    26                 continue;
    27             }
    28 
    29             readPermissionsFromXml(f);
    30         }
    31         
    32         // 目录:system/etc/permissions/platform.xml
    33         // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
    34         final File permFile = new File(Environment.getRootDirectory(),
    35                 "etc/permissions/platform.xml");
    36         readPermissionsFromXml(permFile);
    37     }

    2.1.1 readPermissionsFromXml

      1  private void readPermissionsFromXml(File permFile) {        
      2         FileReader permReader = null;
      3         try {
      4             permReader = new FileReader(permFile);
      5         } catch (FileNotFoundException e) {
      6             Log.w(TAG, "Couldn't find or open permissions file " + permFile);
      7             return;
      8         }
      9 
     10         try {
     11             XmlPullParser parser = Xml.newPullParser();
     12             parser.setInput(permReader);
     13 
     14             XmlUtils.beginDocument(parser, "permissions");
     15 
     16             while (true) {
     17                 XmlUtils.nextElement(parser);
     18                 if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
     19                     break;
     20                 }
     21 
     22                 String name = parser.getName();
     23                 if ("group".equals(name)) {
     24                     String gidStr = parser.getAttributeValue(null, "gid");
     25                     if (gidStr != null) {
     26                         int gid = Integer.parseInt(gidStr);
     27                         mGlobalGids = appendInt(mGlobalGids, gid);
     28                     } else {
     29                         Log.w(TAG, "<group> without gid at "
     30                                 + parser.getPositionDescription());
     31                     }
     32 
     33                     XmlUtils.skipCurrentTag(parser);
     34                     continue;
     35                 } else if ("permission".equals(name)) {
     36                     String perm = parser.getAttributeValue(null, "name");
     37                     if (perm == null) {
     38                         Log.w(TAG, "<permission> without name at "
     39                                 + parser.getPositionDescription());
     40                         XmlUtils.skipCurrentTag(parser);
     41                         continue;
     42                     }
     43                     perm = perm.intern();
     44                     readPermission(parser, perm);
     45                     
     46                 } else if ("assign-permission".equals(name)) {
     47                     String perm = parser.getAttributeValue(null, "name");
     48                     if (perm == null) {
     49                         Log.w(TAG, "<assign-permission> without name at "
     50                                 + parser.getPositionDescription());
     51                         XmlUtils.skipCurrentTag(parser);
     52                         continue;
     53                     }
     54                     String uidStr = parser.getAttributeValue(null, "uid");
     55                     if (uidStr == null) {
     56                         Log.w(TAG, "<assign-permission> without uid at "
     57                                 + parser.getPositionDescription());
     58                         XmlUtils.skipCurrentTag(parser);
     59                         continue;
     60                     }
     61                     int uid = Process.getUidForName(uidStr);
     62                     if (uid < 0) {
     63                         Log.w(TAG, "<assign-permission> with unknown uid ""
     64                                 + uidStr + "" at "
     65                                 + parser.getPositionDescription());
     66                         XmlUtils.skipCurrentTag(parser);
     67                         continue;
     68                     }
     69                     perm = perm.intern();
     70                     HashSet<String> perms = mSystemPermissions.get(uid);
     71                     if (perms == null) {
     72                         perms = new HashSet<String>();
     73                         mSystemPermissions.put(uid, perms);
     74                     }
     75                     perms.add(perm);
     76                     XmlUtils.skipCurrentTag(parser);
     77                     
     78                 } else if ("library".equals(name)) {
     79                     String lname = parser.getAttributeValue(null, "name");
     80                     String lfile = parser.getAttributeValue(null, "file");
     81                     if (lname == null) {
     82                         Log.w(TAG, "<library> without name at "
     83                                 + parser.getPositionDescription());
     84                     } else if (lfile == null) {
     85                         Log.w(TAG, "<library> without file at "
     86                                 + parser.getPositionDescription());
     87                     } else {
     88                         Log.i(TAG, "Got library " + lname + " in " + lfile);
     89                         this.mSharedLibraries.put(lname, lfile);
     90                     }
     91                     XmlUtils.skipCurrentTag(parser);
     92                     continue;
     93                     
     94                 } else {
     95                     XmlUtils.skipCurrentTag(parser);
     96                     continue;
     97                 }
     98 
     99             }
    100         } catch (XmlPullParserException e) {
    101             Log.w(TAG, "Got execption parsing permissions.", e);
    102         } catch (IOException e) {
    103             Log.w(TAG, "Got execption parsing permissions.", e);
    104         }
    105     }

    2.2 mSettings.readLP()

      1 boolean readLP() {
      2             FileInputStream str = null;
      3             // 如果 data/system/packages-backup.xml 文件存在,则继续
      4             if (mBackupSettingsFilename.exists()) {
      5                 try {
      6                     //文件:data/system/packages-backup.xml
      7                     str = new FileInputStream(mBackupSettingsFilename);
      8                     mReadMessages.append("Reading from backup settings file
    ");
      9                     Log.i(TAG, "Reading from backup settings file!");
     10                 } catch (java.io.IOException e) {
     11                     // We'll try for the normal settings file.
     12                 }
     13             }
     14 
     15             // 清除 mPastSignatures 列表
     16             mPastSignatures.clear();
     17 
     18             try {
     19                 // 如果 "data/system/packages-backup.xml" 文件不存在
     20                 if (str == null) {
     21                     // 如果 data/system/packages.xml 也不存在
     22                     if (!mSettingsFilename.exists()) {
     23                         mReadMessages.append("No settings file found
    ");
     24                         Log.i(TAG, "No current settings file!");
     25                         return false; // 直接返回了
     26                     }
     27                     // 如果存在,则创建 data/system/packages.xml 文件流
     28                     str = new FileInputStream(mSettingsFilename);
     29                 }
     30                 //若packages-backup.xml存在,则解析,否则 解析 packages.xml 文件
     31                 XmlPullParser parser = Xml.newPullParser();
     32                 parser.setInput(str, null);
     33 
     34                 int type;
     35                 while ((type=parser.next()) != XmlPullParser.START_TAG
     36                            && type != XmlPullParser.END_DOCUMENT) {
     37                     ;
     38                 }
     39 
     40                 if (type != XmlPullParser.START_TAG) {
     41                     mReadMessages.append("No start tag found in settings file
    ");
     42                     Log.e(TAG, "No start tag found in package manager settings");
     43                     return false;
     44                 }
     45 
     46                 int outerDepth = parser.getDepth();
     47                 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
     48                        && (type != XmlPullParser.END_TAG
     49                                || parser.getDepth() > outerDepth)) {
     50                     if (type == XmlPullParser.END_TAG
     51                             || type == XmlPullParser.TEXT) {
     52                         continue;
     53                     }
     54 
     55                     String tagName = parser.getName();
     56                     // 解析 packages.xml 文件中的 "package"
     57                     if (tagName.equals("package")) {
     58                         readPackageLP(parser); //解析 package 标签
     59                     } else if (tagName.equals("permissions")) { //解析 permissions 标签 
     60                         readPermissionsLP(mPermissions, parser);
     61                     } else if (tagName.equals("permission-trees")) {
     62                         readPermissionsLP(mPermissionTrees, parser);
     63                     } else if (tagName.equals("shared-user")) { // 解析 shared-user 标签
     64                         readSharedUserLP(parser);
     65                     } else if (tagName.equals("preferred-packages")) {
     66                         readPreferredPackagesLP(parser);
     67                     } else if (tagName.equals("preferred-activities")) {
     68                         readPreferredActivitiesLP(parser);
     69                     } else if(tagName.equals("updated-package")) { //解析 updated-package 标签
     70                         readDisabledSysPackageLP(parser);
     71                     } else {
     72                         Log.w(TAG, "Unknown element under <packages>: "
     73                               + parser.getName());
     74                         XmlUtils.skipCurrentTag(parser);
     75                     }
     76                 }
     77 
     78                 str.close();
     79 
     80             } catch(XmlPullParserException e) {
     81                 mReadMessages.append("Error reading: " + e.toString());
     82                 Log.e(TAG, "Error reading package manager settings", e);
     83 
     84             } catch(java.io.IOException e) {
     85                 mReadMessages.append("Error reading: " + e.toString());
     86                 Log.e(TAG, "Error reading package manager settings", e);
     87 
     88             }
     89 
     90             int N = mPendingPackages.size();
     91             for (int i=0; i<N; i++) {
     92                 final PendingPackage pp = mPendingPackages.get(i);
     93                 Object idObj = getUserIdLP(pp.sharedId);
     94                 if (idObj != null && idObj instanceof SharedUserSetting) {
     95                     PackageSetting p = getPackageLP(pp.name,
     96                             (SharedUserSetting)idObj, pp.codePath, pp.resourcePath,
     97                             pp.versionCode, pp.pkgFlags, true, true);
     98                     if (p == null) {
     99                         Log.w(TAG, "Unable to create application package for "
    100                                 + pp.name);
    101                         continue;
    102                     }
    103                     p.copyFrom(pp);
    104                 } else if (idObj != null) {
    105                     String msg = "Bad package setting: package " + pp.name
    106                             + " has shared uid " + pp.sharedId
    107                             + " that is not a shared uid
    ";
    108                     mReadMessages.append(msg);
    109                     Log.e(TAG, msg);
    110                 } else {
    111                     String msg = "Bad package setting: package " + pp.name
    112                             + " has shared uid " + pp.sharedId
    113                             + " that is not defined
    ";
    114                     mReadMessages.append(msg);
    115                     Log.e(TAG, msg);
    116                 }
    117             }
    118             mPendingPackages.clear();
    119 
    120             N = mPendingPreferredPackages.size();
    121             mPreferredPackages.clear();
    122             for (int i=0; i<N; i++) {
    123                 final String name = mPendingPreferredPackages.get(i);
    124                 final PackageSetting p = mPackages.get(name);
    125                 if (p != null) {
    126                     mPreferredPackages.add(p);
    127                 } else {
    128                     Log.w(TAG, "Unknown preferred package: " + name);
    129                 }
    130             }
    131             mPendingPreferredPackages.clear();
    132 
    133             mReadMessages.append("Read completed successfully: "
    134                     + mPackages.size() + " packages, "
    135                     + mSharedUsers.size() + " shared uids
    ");
    136 
    137             return true;
    138         }

    2.2.1 readPackageLP

      1 // 解析 data/system/packages.xml 文件中的 "package"标签
      2         private void readPackageLP(XmlPullParser parser)
      3                 throws XmlPullParserException, IOException {
      4             String name = null;
      5             String idStr = null;
      6             String sharedIdStr = null;
      7             String codePathStr = null;
      8             String resourcePathStr = null;
      9             String systemStr = null;
     10             String installerPackageName = null;
     11             int pkgFlags = 0;
     12             String timeStampStr;
     13             long timeStamp = 0;
     14             PackageSettingBase packageSetting = null;
     15             String version = null;
     16             int versionCode = 0;
     17             try {
     18                 // name:包名
     19                 name = parser.getAttributeValue(null, "name");
     20                 idStr = parser.getAttributeValue(null, "userId");
     21                 sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
     22                 codePathStr = parser.getAttributeValue(null, "codePath");
     23                 resourcePathStr = parser.getAttributeValue(null, "resourcePath");
     24                 version = parser.getAttributeValue(null, "version");
     25                 if (version != null) {
     26                     try {
     27                         versionCode = Integer.parseInt(version);
     28                     } catch (NumberFormatException e) {
     29                     }
     30                 }
     31                 systemStr = parser.getAttributeValue(null, "system");
     32                 // installer的值: com.google.android.packageinstaller or com.android.vending etc.
     33                 installerPackageName = parser.getAttributeValue(null, "installer");
     34                 if (systemStr != null) {
     35                     if ("true".equals(systemStr)) {
     36                         pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
     37                     }
     38                 } else {
     39                     // Old settings that don't specify system...  just treat
     40                     // them as system, good enough.
     41                     pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
     42                 }
     43                 timeStampStr = parser.getAttributeValue(null, "ts"); // 解析时间戳
     44                 if (timeStampStr != null) {
     45                     try {
     46                         timeStamp = Long.parseLong(timeStampStr);
     47                     } catch (NumberFormatException e) {
     48                     }
     49                 }
     50                 if (DEBUG_SETTINGS) Log.v(TAG, "Reading package: " + name
     51                         + " userId=" + idStr + " sharedUserId=" + sharedIdStr);
     52                 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
     53                 if (resourcePathStr == null) {
     54                     // 若没有 resourcePath 属性,则赋值为 codePath 属性的值
     55                     resourcePathStr = codePathStr;
     56                 }
     57                 if (name == null) { // 没有包名
     58                     reportSettingsProblem(Log.WARN,
     59                             "Error in package manager settings: <package> has no name at "
     60                             + parser.getPositionDescription());
     61                 } else if (codePathStr == null) { // 没有 codePath 属性值
     62                     reportSettingsProblem(Log.WARN,
     63                             "Error in package manager settings: <package> has no codePath at "
     64                             + parser.getPositionDescription());
     65                 } else if (userId > 0) {
     66                     // 有包名、有codePathStr的值,且userId大于0
     67                     // 根据上述解析的信息,创建 PackageSettingBase 对象
     68                     packageSetting = addPackageLP(name.intern(), new File(codePathStr), 
     69                             new File(resourcePathStr), userId, versionCode, pkgFlags);
     70                     if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
     71                             + ": userId=" + userId + " pkg=" + packageSetting);
     72                     if (packageSetting == null) {
     73                         reportSettingsProblem(Log.ERROR,
     74                                 "Failure adding uid " + userId
     75                                 + " while parsing settings at "
     76                                 + parser.getPositionDescription());
     77                     } else {
     78                         // 设置时间戳
     79                         packageSetting.setTimeStamp(timeStamp, timeStampStr);
     80                     }
     81                 } else if (sharedIdStr != null) { // 存在 sharedUserId 的值
     82                     // 将 sharedUserId 的值赋值给 userId
     83                     userId = sharedIdStr != null
     84                             ? Integer.parseInt(sharedIdStr) : 0;
     85                     if (userId > 0) {
     86                         // 存在 sharedUserId的值 ,且 sharedUserId 大于0,创建 PendingPackage 对象
     87                         packageSetting = new PendingPackage(name.intern(), new File(codePathStr),
     88                                 new File(resourcePathStr), userId, versionCode, pkgFlags);
     89                         packageSetting.setTimeStamp(timeStamp, timeStampStr);
     90                         // mPendingPackages 装入的是 存在 sharedUserId 值的 package 标签
     91                         mPendingPackages.add((PendingPackage) packageSetting);
     92                         if (DEBUG_SETTINGS) Log.i(TAG, "Reading package " + name
     93                                 + ": sharedUserId=" + userId + " pkg="
     94                                 + packageSetting);
     95                     } else { // sharedUserId 小于0,报告错误
     96                         reportSettingsProblem(Log.WARN,
     97                                 "Error in package manager settings: package "
     98                                 + name + " has bad sharedId " + sharedIdStr
     99                                 + " at " + parser.getPositionDescription());
    100                     }
    101                 } else { // userId 的值不符合,报告错误
    102                     reportSettingsProblem(Log.WARN,
    103                             "Error in package manager settings: package "
    104                             + name + " has bad userId " + idStr + " at "
    105                             + parser.getPositionDescription());
    106                 }
    107             } catch (NumberFormatException e) {
    108                 reportSettingsProblem(Log.WARN,
    109                         "Error in package manager settings: package "
    110                         + name + " has bad userId " + idStr + " at "
    111                         + parser.getPositionDescription());
    112             }
    113             if (packageSetting != null) { // 针对存在userId 或 sharedUserId 属性的 package标签
    114                 packageSetting.installerPackageName = installerPackageName;
    115                 final String enabledStr = parser.getAttributeValue(null, "enabled");
    116                 if (enabledStr != null) { // 有 enabled 属性值
    117                     if (enabledStr.equalsIgnoreCase("true")) {
    118                         packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
    119                     } else if (enabledStr.equalsIgnoreCase("false")) {
    120                         packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
    121                     } else if (enabledStr.equalsIgnoreCase("default")) {
    122                         packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
    123                     } else {
    124                         reportSettingsProblem(Log.WARN,
    125                                 "Error in package manager settings: package "
    126                                 + name + " has bad enabled value: " + idStr
    127                                 + " at " + parser.getPositionDescription());
    128                     }
    129                 } else { // 无 enabled 属性
    130                     packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
    131                 }
    132                 final String installStatusStr = parser.getAttributeValue(null, "installStatus");
    133                 if (installStatusStr != null) { // 有 installStatus 属性值
    134                     if (installStatusStr.equalsIgnoreCase("false")) {
    135                         packageSetting.installStatus = PKG_INSTALL_INCOMPLETE;
    136                     } else {
    137                         packageSetting.installStatus = PKG_INSTALL_COMPLETE;
    138                     }
    139                 }
    140                 
    141                 int outerDepth = parser.getDepth();
    142                 int type;
    143                 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    144                        && (type != XmlPullParser.END_TAG
    145                                || parser.getDepth() > outerDepth)) {
    146                     if (type == XmlPullParser.END_TAG
    147                             || type == XmlPullParser.TEXT) {
    148                         continue;
    149                     }
    150 
    151                     String tagName = parser.getName();
    152                     // 解析 package 标签下 的子标签
    153                     if (tagName.equals("disabled-components")) { // 解析子标签  disabled-components
    154                         readDisabledComponentsLP(packageSetting, parser);
    155                     } else if (tagName.equals("enabled-components")) {
    156                         readEnabledComponentsLP(packageSetting, parser); // 解析子标签  enabled-components
    157                     } else if (tagName.equals("sigs")) { // 解析子标签 sigs
    158                         packageSetting.signatures.readXml(parser, mPastSignatures);
    159                     } else if (tagName.equals("perms")) { // 解析子标签 perms
    160                         // 把解析的"权限名称"装入 packageSetting.loadedPermissions 集合中
    161                         readGrantedPermissionsLP(parser,
    162                                 packageSetting.loadedPermissions);
    163                         packageSetting.permissionsFixed = true;
    164                     } else { // 报告错误
    165                         reportSettingsProblem(Log.WARN,
    166                                 "Unknown element under <package>: "
    167                                 + parser.getName());
    168                         XmlUtils.skipCurrentTag(parser);
    169                     }
    170                 }
    171             } else {
    172                 XmlUtils.skipCurrentTag(parser);
    173             }
    174         }

    2.2.1.1 readDisabledComponentsLP

     1         // 解析"data/system/package.xml"文件中的 package 标签下的子标签 "disabled-components"
     2         private void readDisabledComponentsLP(PackageSettingBase packageSetting,
     3                                                   XmlPullParser parser)
     4                 throws IOException, XmlPullParserException {
     5             int outerDepth = parser.getDepth();
     6             int type;
     7             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
     8                    && (type != XmlPullParser.END_TAG
     9                            || parser.getDepth() > outerDepth)) {
    10                 if (type == XmlPullParser.END_TAG
    11                         || type == XmlPullParser.TEXT) {
    12                     continue;
    13                 }
    14 
    15                 String tagName = parser.getName();
    16                 if (tagName.equals("item")) { // 解析子标签"item"
    17                     // 获取name属性值
    18                     String name = parser.getAttributeValue(null, "name");
    19                     if (name != null) {
    20                         // 装入到 disabledComponents 集合中
    21                         packageSetting.disabledComponents.add(name.intern());
    22                     } else {
    23                         reportSettingsProblem(Log.WARN,
    24                                 "Error in package manager settings: <disabled-components> has"
    25                                 + " no name at " + parser.getPositionDescription());
    26                     }
    27                 } else {
    28                     reportSettingsProblem(Log.WARN,
    29                             "Unknown element under <disabled-components>: "
    30                             + parser.getName());
    31                 }
    32                 XmlUtils.skipCurrentTag(parser);
    33             }
    34         }

    2.2.1.2 readEnabledComponentsLP

     1         // 解析"data/system/package.xml"文件中的 package 标签下的子标签 "enabled-components"
     2         private void readEnabledComponentsLP(PackageSettingBase packageSetting,
     3                                                   XmlPullParser parser)
     4                 throws IOException, XmlPullParserException {
     5             int outerDepth = parser.getDepth();
     6             int type;
     7             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
     8                    && (type != XmlPullParser.END_TAG
     9                            || parser.getDepth() > outerDepth)) {
    10                 if (type == XmlPullParser.END_TAG
    11                         || type == XmlPullParser.TEXT) {
    12                     continue;
    13                 }
    14 
    15                 String tagName = parser.getName();
    16                 if (tagName.equals("item")) {
    17                     String name = parser.getAttributeValue(null, "name");
    18                     if (name != null) {
    19                         packageSetting.enabledComponents.add(name.intern());
    20                     } else {
    21                         reportSettingsProblem(Log.WARN,
    22                                 "Error in package manager settings: <enabled-components> has"
    23                                    + " no name at " + parser.getPositionDescription());
    24                     }
    25                 } else {
    26                     reportSettingsProblem(Log.WARN,
    27                             "Unknown element under <enabled-components>: "
    28                             + parser.getName());
    29                 }
    30                 XmlUtils.skipCurrentTag(parser);
    31             }
    32         }

    2.2.1.3 readGrantedPermissionsLP

     1         // 解析标签 "perms"的值
     2         private void readGrantedPermissionsLP(XmlPullParser parser,
     3                 HashSet<String> outPerms) throws IOException, XmlPullParserException {
     4             int outerDepth = parser.getDepth();
     5             int type;
     6             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
     7                    && (type != XmlPullParser.END_TAG
     8                            || parser.getDepth() > outerDepth)) {
     9                 if (type == XmlPullParser.END_TAG
    10                         || type == XmlPullParser.TEXT) {
    11                     continue;
    12                 }
    13 
    14                 String tagName = parser.getName();
    15                 if (tagName.equals("item")) { // 解析子标签 item
    16                     // name:权限名称
    17                     String name = parser.getAttributeValue(null, "name");
    18                     if (name != null) {
    19                         // 解析"权限名称"后装入 outPerms 中
    20                         outPerms.add(name.intern());
    21                     } else {
    22                         reportSettingsProblem(Log.WARN,
    23                                 "Error in package manager settings: <perms> has"
    24                                    + " no name at " + parser.getPositionDescription());
    25                     }
    26                 } else {
    27                     reportSettingsProblem(Log.WARN,
    28                             "Unknown element under <perms>: "
    29                             + parser.getName());
    30                 }
    31                 XmlUtils.skipCurrentTag(parser);
    32             }
    33         }

    2.2.2 readPermissionsLP

     1 // 解析 data/system/packages.xml 文件中的  permissions 标签和 permission-trees 标签
     2         private void readPermissionsLP(HashMap<String, BasePermission> out,
     3                 XmlPullParser parser)
     4                 throws IOException, XmlPullParserException {
     5             int outerDepth = parser.getDepth();
     6             int type;
     7             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
     8                    && (type != XmlPullParser.END_TAG
     9                            || parser.getDepth() > outerDepth)) {
    10                 if (type == XmlPullParser.END_TAG
    11                         || type == XmlPullParser.TEXT) {
    12                     continue;
    13                 }
    14 
    15                 String tagName = parser.getName();
    16                 if (tagName.equals("item")) {
    17                     String name = parser.getAttributeValue(null, "name");
    18                     String sourcePackage = parser.getAttributeValue(null, "package");
    19                     String ptype = parser.getAttributeValue(null, "type");
    20                     if (name != null && sourcePackage != null) {
    21                         boolean dynamic = "dynamic".equals(ptype);
    22                         BasePermission bp = new BasePermission(name, sourcePackage,
    23                                 dynamic
    24                                 ? BasePermission.TYPE_DYNAMIC
    25                                 : BasePermission.TYPE_NORMAL);
    26                         if (dynamic) {
    27                             PermissionInfo pi = new PermissionInfo();
    28                             pi.packageName = sourcePackage.intern();
    29                             pi.name = name.intern();
    30                             pi.icon = readInt(parser, null, "icon", 0);
    31                             pi.nonLocalizedLabel = parser.getAttributeValue(
    32                                     null, "label");
    33                             pi.protectionLevel = readInt(parser, null, "protection",
    34                                     PermissionInfo.PROTECTION_NORMAL);
    35                             bp.pendingInfo = pi;
    36                         }
    37                         out.put(bp.name, bp);
    38                     } else {
    39                         reportSettingsProblem(Log.WARN,
    40                                 "Error in package manager settings: permissions has"
    41                                 + " no name at " + parser.getPositionDescription());
    42                     }
    43                 } else {
    44                     reportSettingsProblem(Log.WARN,
    45                             "Unknown element reading permissions: "
    46                             + parser.getName() + " at "
    47                             + parser.getPositionDescription());
    48                 }
    49                 XmlUtils.skipCurrentTag(parser);
    50             }
    51         }

    2.2.3 readSharedUserLP

     1 // 解析"data/system/package.xml"文件中的 shared-user 标签
     2         private void readSharedUserLP(XmlPullParser parser)
     3                 throws XmlPullParserException, IOException {
     4             String name = null;
     5             String idStr = null;
     6             int pkgFlags = 0;
     7             SharedUserSetting su = null;
     8             try {
     9                 name = parser.getAttributeValue(null, "name");// 解析name属性值
    10                 idStr = parser.getAttributeValue(null, "userId");// 解析 userId 属性值
    11                 int userId = idStr != null ? Integer.parseInt(idStr) : 0;
    12                 if ("true".equals(parser.getAttributeValue(null, "system"))) {
    13                     pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
    14                 }
    15                 if (name == null) {
    16                     reportSettingsProblem(Log.WARN,
    17                             "Error in package manager settings: <shared-user> has no name at "
    18                             + parser.getPositionDescription());
    19                 } else if (userId == 0) {
    20                     reportSettingsProblem(Log.WARN,
    21                             "Error in package manager settings: shared-user "
    22                             + name + " has bad userId " + idStr + " at "
    23                             + parser.getPositionDescription());
    24                 } else {
    25                     if ((su=addSharedUserLP(name.intern(), userId, pkgFlags)) == null) {
    26                         reportSettingsProblem(Log.ERROR,
    27                                 "Occurred while parsing settings at "
    28                                 + parser.getPositionDescription());
    29                     }
    30                 }
    31             } catch (NumberFormatException e) {
    32                 reportSettingsProblem(Log.WARN,
    33                         "Error in package manager settings: package "
    34                         + name + " has bad userId " + idStr + " at "
    35                         + parser.getPositionDescription());
    36             };
    37 
    38             if (su != null) {
    39                 int outerDepth = parser.getDepth();
    40                 int type;
    41                 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    42                        && (type != XmlPullParser.END_TAG
    43                                || parser.getDepth() > outerDepth)) {
    44                     if (type == XmlPullParser.END_TAG
    45                             || type == XmlPullParser.TEXT) {
    46                         continue;
    47                     }
    48 
    49                     String tagName = parser.getName();
    50                     if (tagName.equals("sigs")) { // 解析 sigs 子标签
    51                         su.signatures.readXml(parser, mPastSignatures);
    52                     } else if (tagName.equals("perms")) { // 解析 perms 标签
    53                         readGrantedPermissionsLP(parser, su.loadedPermissions);
    54                     } else {
    55                         reportSettingsProblem(Log.WARN,
    56                                 "Unknown element under <shared-user>: "
    57                                 + parser.getName());
    58                         XmlUtils.skipCurrentTag(parser);
    59                     }
    60                 }
    61 
    62             } else {
    63                 XmlUtils.skipCurrentTag(parser);
    64             }
    65         }

    2.2.4 readDisabledSysPackageLP

     1 // 解析 packages.xml 文件中的 updated-package 标签值 
     2         private void readDisabledSysPackageLP(XmlPullParser parser)
     3         throws XmlPullParserException, IOException {
     4             String name = parser.getAttributeValue(null, "name");
     5             String codePathStr = parser.getAttributeValue(null, "codePath");
     6             String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
     7             // 如果 resourcePathStr 没有值
     8             if(resourcePathStr == null) {
     9                 // 则赋值为 codePath的值
    10                 resourcePathStr = codePathStr;
    11             }
    12             String version = parser.getAttributeValue(null, "version");
    13             int versionCode = 0;
    14             // 如果有 version 的值
    15             if (version != null) {
    16                 try {
    17                     // 则解析version的值
    18                     versionCode = Integer.parseInt(version);
    19                 } catch (NumberFormatException e) {
    20                 }
    21             }
    22             
    23             int pkgFlags = 0;
    24             pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
    25             // 根据上述 解析的信息,创建  PackageSetting 对象
    26             // name:包名
    27             // codePathStr:com.google.android.gms
    28             PackageSetting ps = new PackageSetting(name, 
    29                     new File(codePathStr), 
    30                     new File(resourcePathStr), versionCode, pkgFlags);
    31             String timeStampStr = parser.getAttributeValue(null, "ts");
    32             if (timeStampStr != null) {
    33                 try {
    34                     // 如果有时间戳信息,则解析时间戳
    35                     long timeStamp = Long.parseLong(timeStampStr);
    36                     // 设置时间戳
    37                     ps.setTimeStamp(timeStamp, timeStampStr);
    38                 } catch (NumberFormatException e) {
    39                 }
    40             }
    41             // 解析 userId的值
    42             String idStr = parser.getAttributeValue(null, "userId");
    43             ps.userId = idStr != null ? Integer.parseInt(idStr) : 0; // 设置 userId
    44             if(ps.userId <= 0) {
    45                 // 如果 userId 小于0,则取值于 sharedUserId 的值
    46                 String sharedIdStr = parser.getAttributeValue(null, "sharedUserId");
    47                 ps.userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
    48             }
    49             int outerDepth = parser.getDepth();
    50             int type;
    51             while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
    52                    && (type != XmlPullParser.END_TAG
    53                            || parser.getDepth() > outerDepth)) {
    54                 if (type == XmlPullParser.END_TAG
    55                         || type == XmlPullParser.TEXT) {
    56                     continue;
    57                 }
    58 
    59                 String tagName = parser.getName();
    60                 // 解析 updated-package 标签内的子标签"perms"
    61                 if (tagName.equals("perms")) {
    62                     // ps.grantedPermissions 内装入的是子标签"perms"中声明的"权限名称"
    63                     readGrantedPermissionsLP(parser,
    64                             ps.grantedPermissions);
    65                 } else {
    66                     reportSettingsProblem(Log.WARN,
    67                             "Unknown element under <updated-package>: "
    68                             + parser.getName());
    69                     XmlUtils.skipCurrentTag(parser);
    70                 }
    71             }
    72             // name:包名,根据包名转入 PackageSetting对象
    73             mDisabledSysPackages.put(name, ps);
    74         }

    2.3 scanDirLI

     1     // 扫描:system/app目录、system/framework目录、data/app目录、data/app-private目录
     2     private void scanDirLI(File dir, int flags, int scanMode) {
     3         Log.d(TAG, "Scanning app dir " + dir);
     4 
     5         String[] files = dir.list();
     6 
     7         int i;
     8         for (i=0; i<files.length; i++) {
     9             File file = new File(dir, files[i]);
    10             File resFile = file;
    11             // Pick up the resource path from settings for fwd locked apps
    12             if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {  // data/app-private目录 ?
    13                 resFile = null;
    14             }
    15             // 第1个参数、第2个参数和第3个参数,大多时候同一个值
    16             PackageParser.Package pkg = scanPackageLI(file, file, resFile,
    17                     flags|PackageParser.PARSE_MUST_BE_APK, scanMode);
    18         }
    19     }

    2.3.1 scanPackageLI

     1 /*
     2      *  Scan a package and return the newly parsed package.
     3      *  Returns null in case of errors and the error code is stored in mLastScanError
     4      */
     5     private PackageParser.Package scanPackageLI(File scanFile,
     6             File destCodeFile, File destResourceFile, int parseFlags,
     7             int scanMode) {
     8         mLastScanError = PackageManager.INSTALL_SUCCEEDED;
     9         parseFlags |= mDefParseFlags;
    10         PackageParser pp = new PackageParser(scanFile.getPath());
    11         pp.setSeparateProcesses(mSeparateProcesses);
    12         pp.setSdkVersion(mSdkVersion, mSdkCodename);
    13         // 解析包,主要是解析 AndroidManifest.xml 文件
    14         final PackageParser.Package pkg = pp.parsePackage(scanFile,
    15                 destCodeFile.getAbsolutePath(), mMetrics, parseFlags);
    16         if (pkg == null) { // 解析异常,直接返回
    17             mLastScanError = pp.getParseError();
    18             return null;
    19         }
    20         PackageSetting ps;
    21         PackageSetting updatedPkg;
    22         synchronized (mPackages) {
    23             ps = mSettings.peekPackageLP(pkg.packageName);
    24             updatedPkg = mSettings.mDisabledSysPackages.get(pkg.packageName);
    25         }
    26         ///// 首先验证APK签名信息,如果验证出现问题,则直接返回
    27         // Verify certificates first
    28         if (!collectCertificatesLI(pp, ps, pkg, scanFile, parseFlags)) {
    29             Log.i(TAG, "Failed verifying certificates for package:" + pkg.packageName);
    30             return null;
    31         }
    32         if (updatedPkg != null) {
    33             // An updated system app will not have the PARSE_IS_SYSTEM flag set initially
    34             parseFlags |= PackageParser.PARSE_IS_SYSTEM;
    35         }
    36         if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
    37             // Check for updated system applications here
    38             if (updatedPkg != null) {
    39                 if ((ps != null) && (!ps.codePath.getPath().equals(scanFile.getPath()))) {
    40                     if (pkg.mVersionCode <= ps.versionCode) { // 版本号对比:和 mSettings 集合中搜索出来的包进行对比
    41                      // The system package has been updated and the code path does not match
    42                         // Ignore entry. Just return
    43                         Log.w(TAG, "Package:" + pkg.packageName +
    44                                 " has been updated. Ignoring the one from path:"+scanFile);
    45                         mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
    46                         return null;
    47                     } else {
    48                         // Delete the older apk pointed to by ps
    49                         // At this point, its safely assumed that package installation for
    50                         // apps in system partition will go through. If not there won't be a working
    51                         // version of the app
    52                         synchronized (mPackages) {
    53                             // Just remove the loaded entries from package lists.
    54                             mPackages.remove(ps.name);
    55                         }
    56                         // 删除资源包
    57                         deletePackageResourcesLI(ps.name, ps.codePathString, ps.resourcePathString);
    58                         mSettings.enableSystemPackageLP(ps.name);
    59                     }
    60                 }
    61             }
    62         }
    63         // The apk is forward locked (not public) if its code and resources
    64         // are kept in different files.
    65         if (ps != null && !ps.codePath.equals(ps.resourcePath)) { // code 路径和 resourcePath 路径保存位置不同
    66             scanMode |= SCAN_FORWARD_LOCKED;
    67         }
    68         File resFile = destResourceFile;
    69         if ((scanMode & SCAN_FORWARD_LOCKED) != 0) {
    70             resFile = getFwdLockedResource(ps.name);
    71         }
    72         // Note that we invoke the following method only if we are about to unpack an application
    73         return scanPackageLI(scanFile, destCodeFile, resFile,
    74                 pkg, parseFlags, scanMode | SCAN_UPDATE_SIGNATURE);
    75     }

    # PackageParser.java

     2.3.1.1 parsePackage

     1 public Package parsePackage(File sourceFile, String destFileName,
     2             DisplayMetrics metrics, int flags) {
     3         // 默认值:安装成功
     4         mParseError = PackageManager.INSTALL_SUCCEEDED;
     5 
     6         // 拿到文件路径
     7         mArchiveSourcePath = sourceFile.getPath();
     8         if (!sourceFile.isFile()) {// 过滤出目录
     9             Log.w(TAG, "Skipping dir: " + mArchiveSourcePath);
    10             mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
    11             return null;
    12         }
    13         // 判断是否是APK文件,如果不是apk文件,则直接返回
    14         if (!isPackageFilename(sourceFile.getName())
    15                 && (flags&PARSE_MUST_BE_APK) != 0) {
    16             if ((flags&PARSE_IS_SYSTEM) == 0) {
    17                 // We expect to have non-.apk files in the system dir,
    18                 // so don't warn about them.
    19                 Log.w(TAG, "Skipping non-package file: " + mArchiveSourcePath);
    20             }
    21             mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
    22             return null;
    23         }
    24 
    25         if ((flags&PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
    26             TAG, "Scanning package: " + mArchiveSourcePath);
    27 
    28         XmlResourceParser parser = null;
    29         AssetManager assmgr = null;
    30         boolean assetError = true;
    31         try {
    32             assmgr = new AssetManager();
    33             // 将apk文件加入装入
    34             int cookie = assmgr.addAssetPath(mArchiveSourcePath);
    35             if(cookie != 0) {// 文件装入OK
    36                 parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");// 打开 AndroidManifest.xml 文件
    37                 assetError = false;
    38             } else {
    39                 Log.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);
    40             }
    41         } catch (Exception e) {
    42             Log.w(TAG, "Unable to read AndroidManifest.xml of "
    43                     + mArchiveSourcePath, e);
    44         }
    45         if(assetError) { // 打开 AndroidManifest.xml 出现错误,直接返回
    46             if (assmgr != null) assmgr.close();
    47             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
    48             return null;
    49         }
    50         String[] errorText = new String[1];
    51         Package pkg = null;
    52         Exception errorException = null;
    53         try {
    54             // XXXX todo: need to figure out correct configuration.
    55             Resources res = new Resources(assmgr, metrics, null);
    56             ////////// 解析 AndroidManifest.xml 文件
    57             pkg = parsePackage(res, parser, flags, errorText);
    58         } catch (Exception e) {
    59             errorException = e;
    60             mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
    61         }
    62 
    63 
    64         // 解析包出错,释放资源,直接返回
    65         if (pkg == null) {
    66             if (errorException != null) {
    67                 Log.w(TAG, mArchiveSourcePath, errorException);
    68             } else {
    69                 Log.w(TAG, mArchiveSourcePath + " (at "
    70                         + parser.getPositionDescription()
    71                         + "): " + errorText[0]);
    72             }
    73             parser.close();
    74             assmgr.close();
    75             if (mParseError == PackageManager.INSTALL_SUCCEEDED) {
    76                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    77             }
    78             return null;
    79         }
    80 
    81         parser.close();
    82         assmgr.close();
    83 
    84         // 赋值 sourceDir 和 publicSourceDir
    85         pkg.applicationInfo.sourceDir = destFileName;
    86         pkg.applicationInfo.publicSourceDir = destFileName;
    87         pkg.mSignatures = null;
    88 
    89         return pkg;
    90     }

    2.3.1.1.1  parsePackage

      1  // 解析 AndroidManifest.xml 文件
      2     private Package parsePackage(
      3         Resources res, XmlResourceParser parser, int flags, String[] outError)
      4         throws XmlPullParserException, IOException {
      5         AttributeSet attrs = parser;
      6 
      7         mParseInstrumentationArgs = null;
      8         mParseActivityArgs = null;
      9         mParseServiceArgs = null;
     10         mParseProviderArgs = null;
     11         
     12         // 从 AndroidManifest.xml 文件中解析包名
     13         String pkgName = parsePackageName(parser, attrs, flags, outError);
     14         if (pkgName == null) { // 没有拿到包名
     15             mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
     16             return null;
     17         }
     18         int type;
     19 
     20         // 根据 “包名” 新建 Package 对象
     21         final Package pkg = new Package(pkgName);
     22         boolean foundApp = false;
     23         
     24         TypedArray sa = res.obtainAttributes(attrs,
     25                 com.android.internal.R.styleable.AndroidManifest);
     26         // 获取 versionCode 属性值
     27         pkg.mVersionCode = sa.getInteger(
     28                 com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
     29         // 获取 versionName 属性值
     30         pkg.mVersionName = sa.getNonResourceString(
     31                 com.android.internal.R.styleable.AndroidManifest_versionName);
     32         if (pkg.mVersionName != null) {
     33             pkg.mVersionName = pkg.mVersionName.intern();
     34         }
     35         // 获取 sharedUserId 属性值
     36         String str = sa.getNonResourceString(
     37                 com.android.internal.R.styleable.AndroidManifest_sharedUserId);
     38         if (str != null) {// 如果存在 sharedUserId 属性值
     39             String nameError = validateName(str, true);
     40             if (nameError != null && !"android".equals(pkgName)) {
     41                 outError[0] = "<manifest> specifies bad sharedUserId name ""
     42                     + str + "": " + nameError;
     43                 mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID;
     44                 return null;
     45             }
     46             // 将 sharedUserId 的值赋值给 Package 对象
     47             pkg.mSharedUserId = str.intern();
     48             // 获取 sharedUserLabel 属性值
     49             pkg.mSharedUserLabel = sa.getResourceId(
     50                     com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
     51         }
     52         sa.recycle(); // TypedArray资源回收
     53 
     54         // Resource boolean are -1, so 1 means we don't know the value.
     55         int supportsSmallScreens = 1;
     56         int supportsNormalScreens = 1;
     57         int supportsLargeScreens = 1;
     58         int resizeable = 1;
     59         int anyDensity = 1;
     60         
     61         int outerDepth = parser.getDepth();
     62         while ((type=parser.next()) != parser.END_DOCUMENT
     63                && (type != parser.END_TAG || parser.getDepth() > outerDepth)) {
     64             if (type == parser.END_TAG || type == parser.TEXT) {
     65                 continue;
     66             }
     67 
     68             String tagName = parser.getName();
     69             // 从 AndroidManifest.xml 文件中解析 application 标签
     70             if (tagName.equals("application")) {
     71                 if (foundApp) {
     72                     if (RIGID_PARSER) {
     73                         outError[0] = "<manifest> has more than one <application>";
     74                         mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
     75                         return null;
     76                     } else {
     77                         Log.w(TAG, "<manifest> has more than one <application>");
     78                         XmlUtils.skipCurrentTag(parser);
     79                         continue;
     80                     }
     81                 }
     82 
     83                 foundApp = true;
     84                 // 解析 application 标签
     85                 if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
     86                     return null;
     87                 }
     88                 // 解析 permission-group 标签
     89             } else if (tagName.equals("permission-group")) {
     90                 if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) {
     91                     return null;
     92                 }
     93                 // 解析 permission 标签
     94             } else if (tagName.equals("permission")) {
     95                 if (parsePermission(pkg, res, parser, attrs, outError) == null) {
     96                     return null;
     97                 }
     98                 // 解析 permission-tree 标签
     99             } else if (tagName.equals("permission-tree")) {
    100                 if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
    101                     return null;
    102                 }
    103                 // 解析 uses-permission 标签
    104             } else if (tagName.equals("uses-permission")) {
    105                 sa = res.obtainAttributes(attrs,
    106                         com.android.internal.R.styleable.AndroidManifestUsesPermission);
    107 
    108                 String name = sa.getNonResourceString(
    109                         com.android.internal.R.styleable.AndroidManifestUsesPermission_name);
    110 
    111                 sa.recycle();
    112 
    113                 if (name != null && !pkg.requestedPermissions.contains(name)) {
    114                     pkg.requestedPermissions.add(name.intern());
    115                 }
    116 
    117                 XmlUtils.skipCurrentTag(parser);
    118 
    119                 // 解析 uses-configuration 标签
    120             } else if (tagName.equals("uses-configuration")) {
    121                 ConfigurationInfo cPref = new ConfigurationInfo();
    122                 sa = res.obtainAttributes(attrs,
    123                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration);
    124                 cPref.reqTouchScreen = sa.getInt(
    125                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
    126                         Configuration.TOUCHSCREEN_UNDEFINED);
    127                 cPref.reqKeyboardType = sa.getInt(
    128                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
    129                         Configuration.KEYBOARD_UNDEFINED);
    130                 if (sa.getBoolean(
    131                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
    132                         false)) {
    133                     cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
    134                 }
    135                 cPref.reqNavigation = sa.getInt(
    136                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
    137                         Configuration.NAVIGATION_UNDEFINED);
    138                 if (sa.getBoolean(
    139                         com.android.internal.R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
    140                         false)) {
    141                     cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
    142                 }
    143                 sa.recycle();
    144                 pkg.configPreferences.add(cPref);
    145 
    146                 XmlUtils.skipCurrentTag(parser);
    147                 // 解析 uses-feature 标签
    148             } else if (tagName.equals("uses-feature")) {
    149                 ConfigurationInfo cPref = new ConfigurationInfo();
    150                 sa = res.obtainAttributes(attrs,
    151                         com.android.internal.R.styleable.AndroidManifestUsesFeature);
    152                 cPref.reqGlEsVersion = sa.getInt(
    153                         com.android.internal.R.styleable.AndroidManifestUsesFeature_glEsVersion,
    154                         ConfigurationInfo.GL_ES_VERSION_UNDEFINED);
    155                 sa.recycle();
    156                 pkg.configPreferences.add(cPref);
    157 
    158                 XmlUtils.skipCurrentTag(parser);
    159 
    160                 // 解析 uses-sdk 标签
    161             } else if (tagName.equals("uses-sdk")) {
    162                 if (mSdkVersion > 0) {
    163                     sa = res.obtainAttributes(attrs,
    164                             com.android.internal.R.styleable.AndroidManifestUsesSdk);
    165 
    166                     int minVers = 0;
    167                     String minCode = null;
    168                     int targetVers = 0;
    169                     String targetCode = null;
    170                     
    171                     // 解析 minSdkVersion 属性值
    172                     TypedValue val = sa.peekValue(
    173                             com.android.internal.R.styleable.AndroidManifestUsesSdk_minSdkVersion);
    174                     if (val != null) { // 数值和字串区别
    175                         if (val.type == TypedValue.TYPE_STRING && val.string != null) {
    176                             targetCode = minCode = val.string.toString();
    177                         } else {
    178                             // If it's not a string, it's an integer.
    179                             targetVers = minVers = val.data;
    180                         }
    181                     }
    182                     
    183                     // 解析 targetSdkVersion 属性
    184                     val = sa.peekValue(
    185                             com.android.internal.R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
    186                     if (val != null) { // 数值和字串区别
    187                         if (val.type == TypedValue.TYPE_STRING && val.string != null) {
    188                             targetCode = minCode = val.string.toString();
    189                         } else {
    190                             // If it's not a string, it's an integer.
    191                             targetVers = val.data;
    192                         }
    193                     }
    194                     
    195                     // 解析 maxSdkVersion 属性
    196                     int maxVers = sa.getInt(
    197                             com.android.internal.R.styleable.AndroidManifestUsesSdk_maxSdkVersion,
    198                             mSdkVersion);
    199 
    200                     sa.recycle();
    201 
    202                     if (minCode != null) {
    203                         if (!minCode.equals(mSdkCodename)) {
    204                             if (mSdkCodename != null) {
    205                                 outError[0] = "Requires development platform " + minCode
    206                                         + " (current platform is " + mSdkCodename + ")";
    207                             } else {
    208                                 outError[0] = "Requires development platform " + minCode
    209                                         + " but this is a release platform.";
    210                             }
    211                             mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
    212                             return null;
    213                         }
    214                     } else if (minVers > mSdkVersion) {
    215                         outError[0] = "Requires newer sdk version #" + minVers
    216                                 + " (current version is #" + mSdkVersion + ")";
    217                         mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
    218                         return null;
    219                     }
    220                     
    221                     if (targetCode != null) {
    222                         if (!targetCode.equals(mSdkCodename)) {
    223                             if (mSdkCodename != null) {
    224                                 outError[0] = "Requires development platform " + targetCode
    225                                         + " (current platform is " + mSdkCodename + ")";
    226                             } else {
    227                                 outError[0] = "Requires development platform " + targetCode
    228                                         + " but this is a release platform.";
    229                             }
    230                             mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
    231                             return null;
    232                         }
    233                         // If the code matches, it definitely targets this SDK.
    234                         pkg.applicationInfo.targetSdkVersion
    235                                 = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
    236                     } else {
    237                         pkg.applicationInfo.targetSdkVersion = targetVers;
    238                     }
    239                     
    240                     if (maxVers < mSdkVersion) {
    241                         outError[0] = "Requires older sdk version #" + maxVers
    242                                 + " (current version is #" + mSdkVersion + ")";
    243                         mParseError = PackageManager.INSTALL_FAILED_OLDER_SDK;
    244                         return null;
    245                     }
    246                 }
    247 
    248                 XmlUtils.skipCurrentTag(parser);
    249 
    250                 // 解析 supports-screens 标签
    251             } else if (tagName.equals("supports-screens")) {
    252                 sa = res.obtainAttributes(attrs,
    253                         com.android.internal.R.styleable.AndroidManifestSupportsScreens);
    254 
    255                 // This is a trick to get a boolean and still able to detect
    256                 // if a value was actually set.
    257                 supportsSmallScreens = sa.getInteger(
    258                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_smallScreens,
    259                         supportsSmallScreens);
    260                 supportsNormalScreens = sa.getInteger(
    261                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_normalScreens,
    262                         supportsNormalScreens);
    263                 supportsLargeScreens = sa.getInteger(
    264                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_largeScreens,
    265                         supportsLargeScreens);
    266                 resizeable = sa.getInteger(
    267                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_resizeable,
    268                         supportsLargeScreens);
    269                 anyDensity = sa.getInteger(
    270                         com.android.internal.R.styleable.AndroidManifestSupportsScreens_anyDensity,
    271                         anyDensity);
    272 
    273                 sa.recycle();
    274                 
    275                 XmlUtils.skipCurrentTag(parser);
    276                 // 解析protected-broadcast 标签
    277             } else if (tagName.equals("protected-broadcast")) {
    278                 sa = res.obtainAttributes(attrs,
    279                         com.android.internal.R.styleable.AndroidManifestProtectedBroadcast);
    280 
    281                 String name = sa.getNonResourceString(
    282                         com.android.internal.R.styleable.AndroidManifestProtectedBroadcast_name);
    283 
    284                 sa.recycle();
    285 
    286                 if (name != null && (flags&PARSE_IS_SYSTEM) != 0) {
    287                     if (pkg.protectedBroadcasts == null) {
    288                         pkg.protectedBroadcasts = new ArrayList<String>();
    289                     }
    290                     if (!pkg.protectedBroadcasts.contains(name)) {
    291                         pkg.protectedBroadcasts.add(name.intern());
    292                     }
    293                 }
    294 
    295                 XmlUtils.skipCurrentTag(parser);
    296                 // 解析 instrumentation 标签
    297             } else if (tagName.equals("instrumentation")) {
    298                 if (parseInstrumentation(pkg, res, parser, attrs, outError) == null) {
    299                     return null;
    300                 }
    301                 // 解析 eat-comment 标签
    302             } else if (tagName.equals("eat-comment")) {
    303                 // Just skip this tag
    304                 XmlUtils.skipCurrentTag(parser);
    305                 continue;
    306                 
    307             } else if (RIGID_PARSER) { // 打印log信息
    308                 outError[0] = "Bad element under <manifest>: "
    309                     + parser.getName();
    310                 mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
    311                 return null;
    312 
    313             } else { // 打印log信息
    314                 Log.w(TAG, "Bad element under <manifest>: "
    315                       + parser.getName());
    316                 XmlUtils.skipCurrentTag(parser);
    317                 continue;
    318             }
    319         }
    320 
    321         if (!foundApp && pkg.instrumentation.size() == 0) { // 没有发现 <application> 标签 或 <instrumentation> 标签
    322             outError[0] = "<manifest> does not contain an <application> or <instrumentation>";
    323             mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY;
    324         }
    325 
    326         final int NP = PackageParser.NEW_PERMISSIONS.length;
    327         for (int ip=0; ip<NP; ip++) {
    328             final PackageParser.NewPermissionInfo npi
    329                     = PackageParser.NEW_PERMISSIONS[ip];
    330             if (pkg.applicationInfo.targetSdkVersion >= npi.sdkVersion) {
    331                 break;
    332             }
    333             if (!pkg.requestedPermissions.contains(npi.name)) {
    334                 Log.i(TAG, "Impliciting adding " + npi.name + " to old pkg "
    335                         + pkg.packageName);
    336                 pkg.requestedPermissions.add(npi.name);
    337             }
    338         }
    339         
    340         if (pkg.usesLibraries.size() > 0) {
    341             pkg.usesLibraryFiles = new String[pkg.usesLibraries.size()];
    342             pkg.usesLibraries.toArray(pkg.usesLibraryFiles);
    343         }
    344         
    345         if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
    346                 && pkg.applicationInfo.targetSdkVersion
    347                         >= android.os.Build.VERSION_CODES.DONUT)) {
    348             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
    349         }
    350         if (supportsNormalScreens != 0) {
    351             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
    352         }
    353         if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
    354                 && pkg.applicationInfo.targetSdkVersion
    355                         >= android.os.Build.VERSION_CODES.DONUT)) {
    356             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
    357         }
    358         if (resizeable < 0 || (resizeable > 0
    359                 && pkg.applicationInfo.targetSdkVersion
    360                         >= android.os.Build.VERSION_CODES.DONUT)) {
    361             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
    362         }
    363         if (anyDensity < 0 || (anyDensity > 0
    364                 && pkg.applicationInfo.targetSdkVersion
    365                         >= android.os.Build.VERSION_CODES.DONUT)) {
    366             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
    367         }
    368 
    369         return pkg;
    370     }

    2.3.1.2 collectCertificatesLI

     1     private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
     2             PackageParser.Package pkg, File srcFile, int parseFlags) {
     3         if (GET_CERTIFICATES) {
     4             if (ps == null || !ps.codePath.equals(srcFile)
     5                     || ps.getTimeStamp() != srcFile.lastModified()) {
     6                 // 源文件已经改变,再次收集证书
     7                 Log.i(TAG, srcFile.toString() + " changed; collecting certs");
     8                 // 收集证书
     9                 if (!pp.collectCertificates(pkg, parseFlags)) {
    10                     mLastScanError = pp.getParseError();
    11                     return false;
    12                 }
    13             }
    14         }
    15         return true;
    16     }

    2.3.1.3 deletePackageResourcesLI

     1     private void deletePackageResourcesLI(String packageName,
     2             String sourceDir, String publicSourceDir) {
     3         File sourceFile = new File(sourceDir);
     4         if (!sourceFile.exists()) {
     5             Log.w(TAG, "Package source " + sourceDir + " does not exist.");
     6         }
     7         // 删除文件
     8         // Delete application's code and resources
     9         sourceFile.delete();
    10         final File publicSourceFile = new File(publicSourceDir);
    11         if (publicSourceFile.exists()) {
    12             publicSourceFile.delete();
    13         }
    14         if (mInstaller != null) {
    15             // 通过 mInstaller 删除dex文件 
    16             int retCode = mInstaller.rmdex(sourceFile.toString());
    17             if (retCode < 0) {
    18                 Log.w(TAG, "Couldn't remove dex file for package: "
    19                         + packageName + " at location " + sourceFile.toString() + ", retcode=" + retCode);
    20                 // we don't consider this to be a failure of the core package deletion
    21             }
    22         }
    23     }

    2.3.1.4 scanPackageLI

      1 private PackageParser.Package scanPackageLI(
      2         File scanFile, File destCodeFile, File destResourceFile,
      3         PackageParser.Package pkg, int parseFlags, int scanMode) {
      4 
      5         mScanningPath = scanFile;
      6         if (pkg == null) { // pkg传入的是null,直接返回
      7             mLastScanError = PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME;
      8             return null;
      9         }
     10 
     11         final String pkgName = pkg.applicationInfo.packageName;
     12         if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) {
     13             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
     14         }
     15 
     16         if (pkgName.equals("android")) { // android包
     17             synchronized (mPackages) {
     18                 if (mAndroidApplication != null) { // 已经解析过了,不再解析
     19                     Log.w(TAG, "*************************************************");
     20                     Log.w(TAG, "Core android package being redefined.  Skipping.");
     21                     Log.w(TAG, " file=" + mScanningPath);
     22                     Log.w(TAG, "*************************************************");
     23                     mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
     24                     return null;
     25                 }
     26     
     27                 // 第一次解析
     28                 // Set up information for our fall-back user intent resolution
     29                 // activity.
     30                 mPlatformPackage = pkg; // 保存平台包信息
     31                 pkg.mVersionCode = mSdkVersion;
     32                 mAndroidApplication = pkg.applicationInfo;
     33                 //### ResolverActivity 这个activity 赋值的地方
     34                 mResolveActivity.applicationInfo = mAndroidApplication;
     35                 mResolveActivity.name = ResolverActivity.class.getName();
     36                 mResolveActivity.packageName = mAndroidApplication.packageName;
     37                 mResolveActivity.processName = mAndroidApplication.processName;
     38                 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
     39                 mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
     40                 mResolveActivity.theme = com.android.internal.R.style.Theme_Dialog_Alert;
     41                 mResolveActivity.exported = true;
     42                 mResolveActivity.enabled = true;
     43                 mResolveInfo.activityInfo = mResolveActivity;
     44                 mResolveInfo.priority = 0;
     45                 mResolveInfo.preferredOrder = 0;
     46                 mResolveInfo.match = 0;
     47                 // 构建 ResolverActivity 这个activity的ComponentName
     48                 mResolveComponentName = new ComponentName(
     49                         mAndroidApplication.packageName, mResolveActivity.name);
     50             }
     51         }
     52 
     53         if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) Log.d(
     54                 TAG, "Scanning package " + pkgName);
     55         if (mPackages.containsKey(pkgName) || mSharedLibraries.containsKey(pkgName)) {
     56             Log.w(TAG, "*************************************************");
     57             Log.w(TAG, "Application package " + pkgName
     58                     + " already installed.  Skipping duplicate.");
     59             Log.w(TAG, "*************************************************");
     60             mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
     61             return null;
     62         }
     63 
     64         SharedUserSetting suid = null;
     65         PackageSetting pkgSetting = null;
     66         
     67         boolean removeExisting = false;
     68         
     69         synchronized (mPackages) {
     70             // Check all shared libraries and map to their actual file path.
     71             if (pkg.usesLibraryFiles != null) {
     72                 for (int i=0; i<pkg.usesLibraryFiles.length; i++) {
     73                     String file = mSharedLibraries.get(pkg.usesLibraryFiles[i]);
     74                     if (file == null) {
     75                         Log.e(TAG, "Package " + pkg.packageName
     76                                 + " requires unavailable shared library "
     77                                 + pkg.usesLibraryFiles[i] + "; ignoring!");
     78                         mLastScanError = PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
     79                         return null;
     80                     }
     81                     pkg.usesLibraryFiles[i] = file;
     82                 }
     83             }
     84             
     85             if (pkg.mSharedUserId != null) {
     86                 suid = mSettings.getSharedUserLP(pkg.mSharedUserId,
     87                         pkg.applicationInfo.flags, true);
     88                 if (suid == null) {
     89                     Log.w(TAG, "Creating application package " + pkgName
     90                             + " for shared user failed");
     91                     mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
     92                     return null;
     93                 }
     94                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD) {
     95                     Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid="
     96                             + suid.userId + "): packages=" + suid.packages);
     97                 }
     98             }
     99 
    100             // Just create the setting, don't add it yet. For already existing packages
    101             // the PkgSetting exists already and doesn't have to be created.
    102             pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile,
    103                             destResourceFile, pkg.applicationInfo.flags, true, false);
    104             if (pkgSetting == null) {
    105                 Log.w(TAG, "Creating application package " + pkgName + " failed");
    106                 mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
    107                 return null;
    108             }
    109             if(mSettings.mDisabledSysPackages.get(pkg.packageName) != null) {
    110                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
    111             }
    112         
    113             pkg.applicationInfo.uid = pkgSetting.userId;
    114             pkg.mExtras = pkgSetting;
    115     
    116             // 校验签名
    117             if (!verifySignaturesLP(pkgSetting, pkg, parseFlags, 
    118                     (scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
    119                 if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
    120                     mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
    121                     return null;
    122                 }
    123                 // The signature has changed, but this package is in the system
    124                 // image...  let's recover!
    125                 pkgSetting.signatures.mSignatures = pkg.mSignatures;
    126                 // However...  if this package is part of a shared user, but it
    127                 // doesn't match the signature of the shared user, let's fail.
    128                 // What this means is that you can't change the signatures
    129                 // associated with an overall shared user, which doesn't seem all
    130                 // that unreasonable.
    131                 if (pkgSetting.sharedUser != null) {
    132                     if (!pkgSetting.sharedUser.signatures.mergeSignatures(
    133                             pkg.mSignatures, false)) {
    134                         mLastScanError = PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
    135                         return null;
    136                     }
    137                 }
    138                 removeExisting = true;
    139             }
    140             
    141             // Verify that this new package doesn't have any content providers
    142             // that conflict with existing packages.  Only do this if the
    143             // package isn't already installed, since we don't want to break
    144             // things that are installed.
    145             if ((scanMode&SCAN_NEW_INSTALL) != 0) { // 检查 content provider 避免冲突
    146                 int N = pkg.providers.size();
    147                 int i;
    148                 for (i=0; i<N; i++) {
    149                     PackageParser.Provider p = pkg.providers.get(i);
    150                     String names[] = p.info.authority.split(";");
    151                     for (int j = 0; j < names.length; j++) {
    152                         if (mProviders.containsKey(names[j])) {
    153                             PackageParser.Provider other = mProviders.get(names[j]);
    154                             Log.w(TAG, "Can't install because provider name " + names[j] +
    155                                     " (in package " + pkg.applicationInfo.packageName +
    156                                     ") is already used by "
    157                                     + ((other != null && other.component != null)
    158                                             ? other.component.getPackageName() : "?"));
    159                             mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
    160                             return null;
    161                         }
    162                     }
    163                 }
    164             }
    165         }
    166 
    167         if (removeExisting) {
    168             if (mInstaller != null) {
    169                 int ret = mInstaller.remove(pkgName);
    170                 if (ret != 0) {
    171                     String msg = "System package " + pkg.packageName
    172                             + " could not have data directory erased after signature change.";
    173                     reportSettingsProblem(Log.WARN, msg);
    174                     mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
    175                     return null;
    176                 }
    177             }
    178             Log.w(TAG, "System package " + pkg.packageName
    179                     + " signature changed: existing data removed.");
    180             mLastScanError = PackageManager.INSTALL_SUCCEEDED;
    181         }
    182         
    183         // 文件时间戳比对
    184         long scanFileTime = scanFile.lastModified();
    185         final boolean forceDex = (scanMode&SCAN_FORCE_DEX) != 0;
    186         final boolean scanFileNewer = forceDex || scanFileTime != pkgSetting.getTimeStamp();
    187         pkg.applicationInfo.processName = fixProcessName(
    188                 pkg.applicationInfo.packageName,
    189                 pkg.applicationInfo.processName,
    190                 pkg.applicationInfo.uid);
    191         pkg.applicationInfo.publicSourceDir = destResourceFile.toString();
    192 
    193         File dataPath;
    194         if (mPlatformPackage == pkg) { // 平台包,包名 “android”
    195             // The system package is special.
    196             dataPath = new File (Environment.getDataDirectory(), "system");// "系统包"是特殊的,路径:data/system
    197             pkg.applicationInfo.dataDir = dataPath.getPath(); // 路径:data/system 目录
    198         } else { // 普通包
    199             // This is a normal package, need to make its data directory.
    200             dataPath = new File(mAppDataDir, pkgName);// 普通应用数据目录:data/data/"包名"
    201             if (dataPath.exists()) {
    202                 mOutPermissions[1] = 0;
    203                 FileUtils.getPermissions(dataPath.getPath(), mOutPermissions);
    204                 if (mOutPermissions[1] == pkg.applicationInfo.uid
    205                         || !Process.supportsProcesses()) {
    206                     pkg.applicationInfo.dataDir = dataPath.getPath(); // data/data/"包名"
    207                 } else {
    208                     boolean recovered = false;
    209                     if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) != 0) { // 如果是system app
    210                         // If this is a system app, we can at least delete its
    211                         // current data so the application will still work.
    212                         if (mInstaller != null) {
    213                             int ret = mInstaller.remove(pkgName); // 删除旧数据
    214                             if(ret >= 0) {
    215                                 // Old data gone!
    216                                 String msg = "System package " + pkg.packageName
    217                                         + " has changed from uid: "
    218                                         + mOutPermissions[1] + " to "
    219                                         + pkg.applicationInfo.uid + "; old data erased";
    220                                 reportSettingsProblem(Log.WARN, msg);
    221                                 recovered = true;
    222                                 
    223                                 // 重新安装
    224                                 // And now re-install the app.
    225                                 ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
    226                                         pkg.applicationInfo.uid);
    227                                 if (ret == -1) {
    228                                     // Ack should not happen!
    229                                     msg = "System package " + pkg.packageName
    230                                             + " could not have data directory re-created after delete.";
    231                                     reportSettingsProblem(Log.WARN, msg);
    232                                     mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
    233                                     return null;
    234                                 }
    235                             }
    236                         } 
    237                         if (!recovered) {
    238                             mHasSystemUidErrors = true;
    239                         }
    240                     }
    241                     if (!recovered) {
    242                         pkg.applicationInfo.dataDir = "/mismatched_uid/settings_"
    243                             + pkg.applicationInfo.uid + "/fs_"
    244                             + mOutPermissions[1];
    245                         String msg = "Package " + pkg.packageName
    246                                 + " has mismatched uid: "
    247                                 + mOutPermissions[1] + " on disk, "
    248                                 + pkg.applicationInfo.uid + " in settings";
    249                         synchronized (mPackages) {
    250                             if (!mReportedUidError) {
    251                                 mReportedUidError = true;
    252                                 msg = msg + "; read messages:
    "
    253                                         + mSettings.getReadMessagesLP();
    254                             }
    255                             reportSettingsProblem(Log.ERROR, msg);
    256                         }
    257                     }
    258                 }
    259                 pkg.applicationInfo.dataDir = dataPath.getPath();
    260             } else {
    261                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGV)
    262                     Log.v(TAG, "Want this data dir: " + dataPath);
    263                 // 调用 installer 去执行真正的安装
    264                 //invoke installer to do the actual installation
    265                 if (mInstaller != null) {
    266                     int ret = mInstaller.install(pkgName, pkg.applicationInfo.uid,
    267                             pkg.applicationInfo.uid);
    268                     if(ret < 0) { // 安装失败,直接返回
    269                         // Error from installer
    270                         mLastScanError = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
    271                         return null;
    272                     }
    273                 } else {
    274                     dataPath.mkdirs(); // 创建数据目录
    275                     if (dataPath.exists()) {
    276                         // 对数据目录设置权限
    277                         FileUtils.setPermissions(
    278                             dataPath.toString(),
    279                             FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
    280                             pkg.applicationInfo.uid, pkg.applicationInfo.uid);
    281                     }
    282                 }
    283                 if (dataPath.exists()) { // 目录创建成功,直接赋值
    284                     pkg.applicationInfo.dataDir = dataPath.getPath();
    285                 } else {
    286                     Log.w(TAG, "Unable to create data directory: " + dataPath);
    287                     pkg.applicationInfo.dataDir = null;
    288                 }
    289             }
    290         }
    291 
    292         // 如果不是system app,执行共享库安装和dex优化
    293         // Perform shared library installation and dex validation and
    294         // optimization, if this is not a system app.
    295         if (mInstaller != null) {
    296             String path = scanFile.getPath();
    297             if (scanFileNewer) {
    298                 Log.i(TAG, path + " changed; unpacking"); // 解包
    299                 int err = cachePackageSharedLibsLI(pkg, dataPath, scanFile);
    300                 if (err != PackageManager.INSTALL_SUCCEEDED) {
    301                     mLastScanError = err;
    302                     return null;
    303                 }
    304             }
    305 
    306             pkg.mForwardLocked = (scanMode&SCAN_FORWARD_LOCKED) != 0;
    307             pkg.mScanPath = path;
    308             
    309             if ((scanMode&SCAN_NO_DEX) == 0) {
    310                 // 执行dex优化
    311                 if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) {
    312                     mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT;
    313                     return null;
    314                 }
    315             }
    316         }
    317         
    318         // 工厂测试权限
    319         if (mFactoryTest && pkg.requestedPermissions.contains(
    320                 android.Manifest.permission.FACTORY_TEST)) {
    321             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FACTORY_TEST;
    322         }
    323 
    324         // We don't expect installation to fail beyond this point,
    325         if ((scanMode&SCAN_MONITOR) != 0) {
    326             pkg.mPath = destCodeFile.getAbsolutePath();
    327             mAppDirs.put(pkg.mPath, pkg);
    328         }
    329 
    330         // Request the ActivityManager to kill the process(only for existing packages)
    331         // so that we do not end up in a confused state while the user is still using the older
    332         // version of the application while the new one gets installed.
    333         IActivityManager am = ActivityManagerNative.getDefault();
    334         if ((am != null) && ((parseFlags & PackageManager.INSTALL_REPLACE_EXISTING ) != 0)) {
    335             try {
    336                 // 杀进程
    337                 am.killApplicationWithUid(pkg.applicationInfo.packageName,
    338                         pkg.applicationInfo.uid);
    339             } catch (RemoteException e) {
    340             }
    341         }
    342         synchronized (mPackages) {
    343             // 添加到mSettings
    344             // Add the new setting to mSettings
    345             mSettings.insertPackageSettingLP(pkgSetting, pkg, destCodeFile, destResourceFile);
    346             // Add the new setting to mPackages
    347             // 添加到mPackages
    348             mPackages.put(pkg.applicationInfo.packageName, pkg);
    349             int N = pkg.providers.size();
    350             StringBuilder r = null;
    351             int i;
    352             for (i=0; i<N; i++) {
    353                 PackageParser.Provider p = pkg.providers.get(i);
    354                 p.info.processName = fixProcessName(pkg.applicationInfo.processName,
    355                         p.info.processName, pkg.applicationInfo.uid);
    356                 mProvidersByComponent.put(new ComponentName(p.info.packageName,
    357                         p.info.name), p);
    358                 p.syncable = p.info.isSyncable;
    359                 String names[] = p.info.authority.split(";");
    360                 p.info.authority = null;
    361                 for (int j = 0; j < names.length; j++) {
    362                     if (j == 1 && p.syncable) {
    363                         // We only want the first authority for a provider to possibly be
    364                         // syncable, so if we already added this provider using a different
    365                         // authority clear the syncable flag. We copy the provider before
    366                         // changing it because the mProviders object contains a reference
    367                         // to a provider that we don't want to change.
    368                         // Only do this for the second authority since the resulting provider
    369                         // object can be the same for all future authorities for this provider.
    370                         p = new PackageParser.Provider(p);
    371                         p.syncable = false;
    372                     }
    373                     if (!mProviders.containsKey(names[j])) {
    374                         mProviders.put(names[j], p);
    375                         if (p.info.authority == null) {
    376                             p.info.authority = names[j];
    377                         } else {
    378                             p.info.authority = p.info.authority + ";" + names[j];
    379                         }
    380                         if ((parseFlags&PackageParser.PARSE_CHATTY) != 0 && Config.LOGD)
    381                             Log.d(TAG, "Registered content provider: " + names[j] +
    382                             ", className = " + p.info.name +
    383                             ", isSyncable = " + p.info.isSyncable);
    384                     } else {
    385                         PackageParser.Provider other = mProviders.get(names[j]);
    386                         Log.w(TAG, "Skipping provider name " + names[j] +
    387                               " (in package " + pkg.applicationInfo.packageName +
    388                               "): name already used by "
    389                               + ((other != null && other.component != null)
    390                                       ? other.component.getPackageName() : "?"));
    391                     }
    392                 }
    393                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
    394                     if (r == null) {
    395                         r = new StringBuilder(256);
    396                     } else {
    397                         r.append(' ');
    398                     }
    399                     r.append(p.info.name);
    400                 }
    401             }
    402             if (r != null) {
    403                 if (Config.LOGD) Log.d(TAG, "  Providers: " + r);
    404             }
    405     
    406             N = pkg.services.size();
    407             r = null;
    408             for (i=0; i<N; i++) {
    409                 PackageParser.Service s = pkg.services.get(i);
    410                 s.info.processName = fixProcessName(pkg.applicationInfo.processName,
    411                         s.info.processName, pkg.applicationInfo.uid);
    412                 mServices.addService(s);
    413                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
    414                     if (r == null) {
    415                         r = new StringBuilder(256);
    416                     } else {
    417                         r.append(' ');
    418                     }
    419                     r.append(s.info.name);
    420                 }
    421             }
    422             if (r != null) {
    423                 if (Config.LOGD) Log.d(TAG, "  Services: " + r);
    424             }
    425     
    426             N = pkg.receivers.size();
    427             r = null;
    428             for (i=0; i<N; i++) {
    429                 PackageParser.Activity a = pkg.receivers.get(i);
    430                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
    431                         a.info.processName, pkg.applicationInfo.uid);
    432                 mReceivers.addActivity(a, "receiver");
    433                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
    434                     if (r == null) {
    435                         r = new StringBuilder(256);
    436                     } else {
    437                         r.append(' ');
    438                     }
    439                     r.append(a.info.name);
    440                 }
    441             }
    442             if (r != null) {
    443                 if (Config.LOGD) Log.d(TAG, "  Receivers: " + r);
    444             }
    445     
    446             N = pkg.activities.size();
    447             r = null;
    448             for (i=0; i<N; i++) {
    449                 PackageParser.Activity a = pkg.activities.get(i);
    450                 a.info.processName = fixProcessName(pkg.applicationInfo.processName,
    451                         a.info.processName, pkg.applicationInfo.uid);
    452                 mActivities.addActivity(a, "activity");
    453                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
    454                     if (r == null) {
    455                         r = new StringBuilder(256);
    456                     } else {
    457                         r.append(' ');
    458                     }
    459                     r.append(a.info.name);
    460                 }
    461             }
    462             if (r != null) {
    463                 if (Config.LOGD) Log.d(TAG, "  Activities: " + r);
    464             }
    465     
    466             N = pkg.permissionGroups.size();
    467             r = null;
    468             for (i=0; i<N; i++) {
    469                 PackageParser.PermissionGroup pg = pkg.permissionGroups.get(i);
    470                 PackageParser.PermissionGroup cur = mPermissionGroups.get(pg.info.name);
    471                 if (cur == null) {
    472                     mPermissionGroups.put(pg.info.name, pg);
    473                     if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
    474                         if (r == null) {
    475                             r = new StringBuilder(256);
    476                         } else {
    477                             r.append(' ');
    478                         }
    479                         r.append(pg.info.name);
    480                     }
    481                 } else {
    482                     Log.w(TAG, "Permission group " + pg.info.name + " from package "
    483                             + pg.info.packageName + " ignored: original from "
    484                             + cur.info.packageName);
    485                     if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
    486                         if (r == null) {
    487                             r = new StringBuilder(256);
    488                         } else {
    489                             r.append(' ');
    490                         }
    491                         r.append("DUP:");
    492                         r.append(pg.info.name);
    493                     }
    494                 }
    495             }
    496             if (r != null) {
    497                 if (Config.LOGD) Log.d(TAG, "  Permission Groups: " + r);
    498             }
    499     
    500             N = pkg.permissions.size();
    501             r = null;
    502             for (i=0; i<N; i++) {
    503                 PackageParser.Permission p = pkg.permissions.get(i);
    504                 HashMap<String, BasePermission> permissionMap =
    505                         p.tree ? mSettings.mPermissionTrees
    506                         : mSettings.mPermissions;
    507                 p.group = mPermissionGroups.get(p.info.group);
    508                 if (p.info.group == null || p.group != null) {
    509                     BasePermission bp = permissionMap.get(p.info.name);
    510                     if (bp == null) {
    511                         bp = new BasePermission(p.info.name, p.info.packageName,
    512                                 BasePermission.TYPE_NORMAL);
    513                         permissionMap.put(p.info.name, bp);
    514                     }
    515                     if (bp.perm == null) {
    516                         if (bp.sourcePackage == null
    517                                 || bp.sourcePackage.equals(p.info.packageName)) {
    518                             BasePermission tree = findPermissionTreeLP(p.info.name);
    519                             if (tree == null
    520                                     || tree.sourcePackage.equals(p.info.packageName)) {
    521                                 bp.perm = p;
    522                                 bp.uid = pkg.applicationInfo.uid;
    523                                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
    524                                     if (r == null) {
    525                                         r = new StringBuilder(256);
    526                                     } else {
    527                                         r.append(' ');
    528                                     }
    529                                     r.append(p.info.name);
    530                                 }
    531                             } else {
    532                                 Log.w(TAG, "Permission " + p.info.name + " from package "
    533                                         + p.info.packageName + " ignored: base tree "
    534                                         + tree.name + " is from package "
    535                                         + tree.sourcePackage);
    536                             }
    537                         } else {
    538                             Log.w(TAG, "Permission " + p.info.name + " from package "
    539                                     + p.info.packageName + " ignored: original from "
    540                                     + bp.sourcePackage);
    541                         }
    542                     } else if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
    543                         if (r == null) {
    544                             r = new StringBuilder(256);
    545                         } else {
    546                             r.append(' ');
    547                         }
    548                         r.append("DUP:");
    549                         r.append(p.info.name);
    550                     }
    551                 } else {
    552                     Log.w(TAG, "Permission " + p.info.name + " from package "
    553                             + p.info.packageName + " ignored: no group "
    554                             + p.group);
    555                 }
    556             }
    557             if (r != null) {
    558                 if (Config.LOGD) Log.d(TAG, "  Permissions: " + r);
    559             }
    560     
    561             N = pkg.instrumentation.size();
    562             r = null;
    563             for (i=0; i<N; i++) {
    564                 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
    565                 a.info.packageName = pkg.applicationInfo.packageName;
    566                 a.info.sourceDir = pkg.applicationInfo.sourceDir;
    567                 a.info.publicSourceDir = pkg.applicationInfo.publicSourceDir;
    568                 a.info.dataDir = pkg.applicationInfo.dataDir;
    569                 mInstrumentation.put(a.component, a);
    570                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
    571                     if (r == null) {
    572                         r = new StringBuilder(256);
    573                     } else {
    574                         r.append(' ');
    575                     }
    576                     r.append(a.info.name);
    577                 }
    578             }
    579             if (r != null) {
    580                 if (Config.LOGD) Log.d(TAG, "  Instrumentation: " + r);
    581             }
    582     
    583             if (pkg.protectedBroadcasts != null) {
    584                 N = pkg.protectedBroadcasts.size();
    585                 for (i=0; i<N; i++) {
    586                     mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
    587                 }
    588             }
    589             
    590             pkgSetting.setTimeStamp(scanFileTime);
    591         }
    592         
    593         return pkg;
    594     }
  • 相关阅读:
    MySQL 常用到的几个字符处理函数
    MySQL DATE_SUB查询工龄大于35的员工信息
    Mysql 没有nvl()函数,却有一个类似功能的函数ifnull();
    switch 循环中的case理解
    批处理系统和分时系统各具有什么特点?为什么分时系统的响应比较快?
    存储式计算机的主要特点是什么?
    代码实现导航栏分割线
    Keras函数式API介绍
    Keras通过子类(subclass)自定义神经网络模型
    R语言kohonen包主要函数介绍
  • 原文地址:https://www.cnblogs.com/onelikeone/p/9184871.html
Copyright © 2011-2022 走看看