privatevoid scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime) { finalFile[] files = dir.listFiles(); if (ArrayUtils.isEmpty(files)) { Log.d(TAG, "No files in app dir " + dir); return; } // Scanning 로그 출력 // if (DEBUG_PACKAGE_SCANNING) { Log.d(TAG, "Scanning app dir " + dir + " scanFlags=" + scanFlags + " flags=0x" + Integer.toHexString(parseFlags)); } for (Filefile : files) { finalboolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName()); if (!isPackage) { // Ignore entries which are not packages continue; } try { scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK, scanFlags, currentTime, null); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage()); // Delete invalid userdata apps if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && e.error == PackageManager.INSTALL_FAILED_INVALID_APK) { logCriticalInfo(Log.WARN, "Deleting invalid package at " + file); if (file.isDirectory()) { mInstaller.rmPackageDir(file.getAbsolutePath()); } else { file.delete(); } } } } }
2. scanPackageDirtyLI 메소드
Line : 6482 ~ 7545
scanPackageDirtyLI는 scanPackageLI에서 부르며, scanPackageLI는 scanDirLI에서 부른다.
해당 메소드는 인자로 받은 package를 분석하여 다시 return한다. (분석 내용은 패키지 업데이트 여부, codePath, partition(system partition or data partition), certificate, 버전 체크 등등)
DEBUG_PACKAGE_SCANNING 플래그가 true일 경우에는 다음을 로그로 출력한다. line 6545 - 스캐닝 중인 app의 name line 6572 - PackageSetting 값이 있을 때, Package의 codePath, 세팅값의 codePathString, resourcePathString line 6611 - Package의 mSharedUserId가 null이 아닌 경우, Package의 mSharedUserId, 세팅값의 userId, packages line 6939 - normal package이며 해당 directory가 존재하지 않을 경우 line 7259 - Package의 Provider가 존재할때? provider 이름, info name, Syncable한지 line 7285 - Providers의 info.name line 7305 - Services의 info.name line 7325 - receivers의 info.name line 7345 - activities의 info.name line 7379 - permissionGroups의 info.name line 7480 - Permissions의 info.name line 7508 - Instrumentation의 info.name
아래 코드는 내용이 많기 때문에, DEBUG_PACKAGE_SCANNING 플래그가 포함된 부분만 발췌
private PackageParser.Package scanPackageDirtyLI(PackageParser.Package pkg, int parseFlags, int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { // Scanning 로그 출력 // if (DEBUG_PACKAGE_SCANNING) { if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) // PackageParser Log.d(TAG, "Scanning package " + pkg.packageName); }
: :
if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) { if (mExpectingBetter.containsKey(pkg.packageName)) { logCriticalInfo(Log.WARN, "Relax SCAN_REQUIRE_KNOWN requirement for package " + pkg.packageName); } else { PackageSetting known = mSettings.peekPackageLPr(pkg.packageName); if (known != null) { // Scanning 로그 출력 // if (DEBUG_PACKAGE_SCANNING) { Log.d(TAG, "Examining " + pkg.codePath + " and requiring known paths " + known.codePathString + " & " + known.resourcePathString); } if (!pkg.applicationInfo.getCodePath().equals(known.codePathString) || !pkg.applicationInfo.getResourcePath().equals(known.resourcePathString)) { thrownew PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED, "Application package " + pkg.packageName + " found at " + pkg.applicationInfo.getCodePath() + " but expected at " + known.codePathString + "; ignoring."); } } } }
: :
synchronized (mPackages) { if (pkg.mSharedUserId != null) { suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, 0, true); if (suid == null) { thrownew PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Creating application package " + pkg.packageName + " for shared user failed"); } // Scanning 로그 출력 // if (DEBUG_PACKAGE_SCANNING) { if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) // PackageParser Log.d(TAG, "Shared UserID " + pkg.mSharedUserId + " (uid=" + suid.userId + "): packages=" + suid.packages); } }
: : }
: :
if (mPlatformPackage == pkg) { // The system package is special. dataPath = newFile(Environment.getDataDirectory(), "system"); pkg.applicationInfo.dataDir = dataPath.getPath(); } else { // This is a normal package, need to make its data directory. dataPath = Environment.getDataUserPackageDirectory(pkg.volumeUuid, UserHandle.USER_OWNER, pkg.packageName); boolean uidError = false; if (dataPath.exists()) {
: :
} else { // Scanning 로그 출력 // if (DEBUG_PACKAGE_SCANNING) { if ((parseFlags & PackageParser.PARSE_CHATTY) != 0) // PackageParser Log.v(TAG, "Want this data dir: " + dataPath); } //invoke installer to do the actual installation int ret = createDataDirsLI(pkg.volumeUuid, pkgName, pkg.applicationInfo.uid, pkg.applicationInfo.seinfo); if (ret < 0) { // Error from installer thrownew PackageManagerException(INSTALL_FAILED_INSUFFICIENT_STORAGE, "Unable to create data dirs [errorCode=" + ret + "]"); } if (dataPath.exists()) { pkg.applicationInfo.dataDir = dataPath.getPath(); } else { Slog.w(TAG, "Unable to create data directory: " + dataPath); pkg.applicationInfo.dataDir = null; } }
: :
// writer synchronized (mPackages) { // We don't expect installation to fail beyond this point
: :
int N = pkg.providers.size(); StringBuilder r = null; int i; for (i=0; i<N; i++) {