声明:原创文章,转载请备注来源:http://shuwoom.com/?p=60&preview=true

Android应用程序安装有四种方式,分别如下:

  • 系统启动时安装,没有安装界面
  • 第三方应用安装,有安装界面,也是我们最熟悉的方式
  • ADB命令安装,没有安装界面
  • 通过Google Play市场安装,没有安装界面

虽然安装方式不同,但是最后四种方式都是通过PackageManagerService服务来完成应用程序的安装。而PackageManagerService服务则通过与Installd服务通信,发送具体的指令来执行应用程序的安装、卸载等工作。它们的关系如下图所示:  

public static final IPackageManager main(Context context, Installer installer,
    boolean factoryTest, boolean onlyCore) {
	    PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore);
	    ServiceManager.addService("package", m);
	    return m;
}

应用程序在安装时涉及到如下几个重要目录:

system/app

系统应用程序的目录

data/app

用户程序安装的目录

data/data

存放应用程序数据的目录

data/dalvik-cache

存放的是经过优化的dex文件

1.1 系统启动时安装

系统启动时安装APK的函数关系图如下:

  

1.1.1 PackageManagerService简介

    应用程序管理服务PackageManagerService是Android系统的核心服务之一在系统启动的时候由SystemServer组件负责启动起来。PackageManagerService用于管理系统中的所有安装包信息以及应用程序的安装和卸载但是实际应用程序的安装卸载并不是由PackageManagerService亲自完成而是通过socket通信,PackageManagerService来访问installd服务来实现应用程序的安装和卸载。

    SystemServer关键代码如下:

    SystemServer.java位置:/frameworks/base/services/java/com/android/server/SystemServer.java。

public class SystemServer {
    ...
	/**
     * Called to initialize native system services.
    */
    private static native void nativeInit();
	public static void main(String[] args) {
	...
	System.loadLibrary("android_servers");

	Slog.i(TAG, "Entered the Android system server!");

	// Initialize native services.
	nativeInit();
	// This used to be its own separate thread, but now it is
	// just the loop we run on the main thread.
	ServerThread thr = new ServerThread();
	thr.initAndLoop();
	}
}

SystemServermain函数中创建ServerThread类对象来启动PackageManagerService。关键代码如下:

class ServerThread {
	private static final String TAG = "SystemServer";
    ……
    ContentResolver mContentResolver;
    ……

    public void initAndLoop() {
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN,
        SystemClock.uptimeMillis());
        Looper.prepareMainLooper();

        ……
		boolean onlyCore = false;
        boolean firstBoot = false;
        ……
        try {
            Slog.i(TAG, "Display Manager");
            display = new DisplayManagerService(context, wmHandler);
            ServiceManager.addService(Context.DISPLAY_SERVICE, display, true);

            Slog.i(TAG, "Telephony Registry");
            telephonyRegistry = new TelephonyRegistry(context);
            ServiceManager.addService("telephony.registry", telephonyRegistry);

            Slog.i(TAG, "Scheduling Policy");
            ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());

            AttributeCache.init(context);

            if (!display.waitForDefaultDisplay()) {
                reportWtf("Timeout waiting for default display to be initialized.",
                        new Throwable());
            }

            Slog.i(TAG, "Package Manager");
            // 处于加密状态时,紧解析核心应用
            String cryptState = SystemProperties.get("vold.decrypt");
            if (ENCRYPTING_STATE.equals(cryptState)) {
                Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
                onlyCore = true;
            } else if (ENCRYPTED_STATE.equals(cryptState)) {
                Slog.w(TAG, "Device encrypted - only parsing core apps");
                onlyCore = true;
            }

            pm = PackageManagerService.main(context, installer,
                    factoryTest != SystemServer.FACTORY_TEST_OFF,
                    onlyCore);
            
           ……
      }
}

    initAndLoop函数中代码:“String cryptState = SystemProperties.get(“vold.decrypt”);”是获取Android磁盘加密状态。Android磁盘加密机制是从Android3.0引入的,详细可以参考:《Android安全架构深究》一书第10章设备安全的磁盘加密章节。在默认情况下,Android磁盘加密功能是关闭的,必须由用户手动打开或托管设备的设备策略打开。所以,默认情况下,传递给PackageManagerService.main函数的onlyCore参数为false。
    接着,ServerThread调用PackageManagerService的静态函数main安装应用。
    在ServerThread类中,除了启动PackageManagerService外,还启动其他系统服务,包括ActivityManagerService、WindowManagerService、AlarmManagerService等,详细见ServerThread类的源码,这里我们只关注PackageManagerService,下面的章节,我们就开始从PackageManagerService.main函数分析开始。

1.1.2 扫描关键目录

PackageManagerService位置: 
/frameworks/base/services/java/com/android/server/pm/PackageManagerService.java
上述main函数定义如下:

public static final IPackageManager main(Context context, Installer installer,
    boolean factoryTest, boolean onlyCore) {
	    PackageManagerService m = new PackageManagerService(context, installer, factoryTest, onlyCore);
	    ServiceManager.addService("package", m);
	    return m;
}

main函数中创建PackageManagerService服务对象,并把服务添加到ServiceManager中。ServiceManager是Android系统Binder进程通信机制的守护进程,一直运行在后台。它主要负责管理系统中的Binder对象。

我们接着分析PackageManagerService类的构造函数,关键代码如下:

public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
	synchronized (mInstallLock) {
        // writer
        synchronized (mPackages) {
            mHandlerThread.start();
            mHandler = new PackageHandler(mHandlerThread.getLooper());
            Watchdog.getInstance().addThread(mHandler, mHandlerThread.getName(),
                    WATCHDOG_TIMEOUT);

            File dataDir = Environment.getDataDirectory();
            mAppDataDir = new File(dataDir, "data");  
            mAppInstallDir = new File(dataDir, "app");  
            mAppLibInstallDir = new File(dataDir, "app-lib"); 
            mAsecInternalPath = new File(dataDir, "app-asec").getPath();  
            mUserAppDataDir = new File(dataDir, "user");  
            mDrmAppPrivateInstallDir = new File(dataDir, "app-private"); 
            ……
            mFrameworkDir = new File(Environment.getRootDirectory(), "framework");
            mDalvikCacheDir = new File(dataDir, "dalvik-cache");
            ……
           // Find base frameworks (resource packages without code).
            mFrameworkInstallObserver = new AppDirObserver(
                frameworkDir.getPath(), OBSERVER_EVENTS, true, false);
            mFrameworkInstallObserver.startWatching();
            //扫描”/system/framework”目录下的apk
            scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR
                    | PackageParser.PARSE_IS_PRIVILEGED,
                    scanMode | SCAN_NO_DEX, 0);

            // Collected privileged system packages.
            File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
            mPrivilegedInstallObserver = new AppDirObserver(
                    privilegedAppDir.getPath(), OBSERVER_EVENTS, true, true);
            mPrivilegedInstallObserver.startWatching();
            //扫描”/system/priv-app”目录下的apk
            scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
                        | PackageParser.PARSE_IS_SYSTEM_DIR
                        | PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);

            // Collect ordinary system packages.
            File systemAppDir = new File(Environment.getRootDirectory(), "app"); 
            mSystemInstallObserver = new AppDirObserver(
                systemAppDir.getPath(), OBSERVER_EVENTS, true, false);
            mSystemInstallObserver.startWatching();
            //扫描”/system/app”目录下的apk
            scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

            // Collect all vendor packages.
            File vendorAppDir = new File("/vendor/app");
            mVendorInstallObserver = new AppDirObserver(
                vendorAppDir.getPath(), OBSERVER_EVENTS, true, false);
            mVendorInstallObserver.startWatching();
            // vender目录其实连接到/system/vendor,实际扫描:/system/vendor/app目录下的apk
            scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
                    | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);

            if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
            mInstaller.moveFiles();

            // Prune any system packages that no longer exist.
            final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<String>();
           //由上一部分内容知道,默认情况下磁盘加密状态关闭,即mOnlyCore状态false
           if (!mOnlyCore) {
                EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
                        SystemClock.uptimeMillis());
                mAppInstallObserver = new AppDirObserver(
                    mAppInstallDir.getPath(), OBSERVER_EVENTS, false, false);
                mAppInstallObserver.startWatching();
                //扫描”/data/app”目录下的apk
                scanDirLI(mAppInstallDir, 0, scanMode, 0);
    
                mDrmAppInstallObserver = new AppDirObserver(
                    mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false, false);
                mDrmAppInstallObserver.startWatching();
                //扫描”/data/app-private”目录下的apk
                scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
                        scanMode, 0);

                ……
            } 
        ……..
}

如上代码,可以看到PackageManagerService在构造函数中,会扫描如下6个目录下的APK,保证这些APK的信息被预先加载进来。

/system/framework

/system/priv-app

/system/app

/system/vendor/app

/data/app

/data/app-private

/system/app目录存放的是系统自带的apk;
/data/app目录下存放的是用户安装的apk;
/system/priv-app目录下的应用是特权应用,这对这些应用富裕signatureOrSystem保护级别的权限,而不是所有/system下的应用
TOOD:查看Android安全架构深究
我们接着分析scanDirLI函数,其函数定义如下:

private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
    String[] files = dir.list();
    ……

    int i;
    for (i=0; i<files.length; i++) {
        File file = new File(dir, files[i]);
        //只扫描apk后缀的文件
        if (!isPackageFilename(files[i])) {
            // Ignore entries which are not apk's
            continue;
        }
        
        PackageParser.Package pkg = scanPackageLI(file,
                flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
       ……
    }
}

scanPackageLI函数主要扫描apk文件并返回解析后的PackageParser.Package对象。
scanPackageLI的关键代码:

private PackageParser.Package scanPackageLI(File scanFile,
    int parseFlags, int scanMode, long currentTime, UserHandle user) {
    ……
    String scanPath = scanFile.getPath();
    parseFlags |= mDefParseFlags;
    PackageParser pp = new PackageParser(scanPath);
    pp.setSeparateProcesses(mSeparateProcesses);
    pp.setOnlyCoreApps(mOnlyCore);
    //解析安装包
    final PackageParser.Package pkg = pp.parsePackage(scanFile, scanPath, mMetrics, parseFlags);
    ……
    //保存解析后的安装包
    PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
            | SCAN_UPDATE_SIGNATURE, currentTime, user);
    ……
    return scannedPkg;
}

1.1.3 解析保存应用程序信息

查看parsePackage函数位置:frameworks/base/core/java/android/content/pm/PackageParser.java,其关键代码如下:

public Package parsePackage(File sourceFile, String destCodePath,
            DisplayMetrics metrics, int flags) {
    mParseError = PackageManager.INSTALL_SUCCEEDED;

    mArchiveSourcePath = sourceFile.getPath();
    ……
	XmlResourceParser parser = null;
    AssetManager assmgr = null; //AssetManager用来管理包中的资源
    Resources res = null; //Resources就是资源,包括图片、xml等
    boolean assetError = true;
    try {
        assmgr = new AssetManager();
        int cookie = assmgr.addAssetPath(mArchiveSourcePath);
        if (cookie != 0) {
            res = new Resources(assmgr, metrics, null);
            assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                    Build.VERSION.RESOURCES_SDK_INT);
            parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
            assetError = false;
        } else {
            Slog.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);
        }
    } catch (Exception e) {
        Slog.w(TAG, "Unable to read AndroidManifest.xml of "
                + mArchiveSourcePath, e);
    }
    ……
    Package pkg = null;
    Exception errorException = null;
    try {
        // XXXX todo: need to figure out correct configuration.
        pkg = parsePackage(res, parser, flags, errorText);
    } catch (Exception e) {
        errorException = e;
        mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
    }
    ……
    parser.close();
    assmgr.close();

    // Set code and resource paths
    pkg.mPath = destCodePath;
    pkg.mScanPath = mArchiveSourcePath;
    //pkg.applicationInfo.sourceDir = destCodePath;
    //pkg.applicationInfo.publicSourceDir = destRes;
    pkg.mSignatures = null;

    return pkg;
}

上述函数主要是获取apk中的资源对象res和对Androidmanifest.xml文件进行格式化,并调用另一个parsePackage函数进一步做解析,这个才是Package真正生成的地方。
其函数关键代码如下:

private Package parsePackage(
    Resources res, XmlResourceParser parser, int flags, String[] outError)
    throws XmlPullParserException, IOException {
	    ……
	    
	    String pkgName = parsePackageName(parser, attrs, flags, outError);
	    ……

	    final Package pkg = new Package(pkgName);
	    ……
	    pkg.mVersionCode = sa.getInteger(
	            com.android.internal.R.styleable.AndroidManifest_versionCode, 0);
	    pkg.mVersionName = sa.getNonConfigurationString(
	            com.android.internal.R.styleable.AndroidManifest_versionName, 0);
	    if (pkg.mVersionName != null) {
	        pkg.mVersionName = pkg.mVersionName.intern();
	    }
	    String str = sa.getNonConfigurationString(
	            com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
	    if (str != null && str.length() > 0) {
	        ……
	        pkg.mSharedUserId = str.intern();
	        pkg.mSharedUserLabel = sa.getResourceId(
	                com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
	    }
	    ……

	    pkg.installLocation = sa.getInteger(
	            com.android.internal.R.styleable.AndroidManifest_installLocation,
	            PARSE_DEFAULT_INSTALL_LOCATION);
	    pkg.applicationInfo.installLocation = pkg.installLocation;

	    /* Set the global "forward lock" flag */
	    if ((flags & PARSE_FORWARD_LOCK) != 0) {
	        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
	    }

	    /* Set the global "on SD card" flag */
	    if ((flags & PARSE_ON_SDCARD) != 0) {
	        pkg.applicationInfo.flags |= ApplicationInfo.FLAG_EXTERNAL_STORAGE;
	    }
	    ……
	    while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
	            && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
	        if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
	            continue;
	        }

	        String tagName = parser.getName();
	        if (tagName.equals("application")) {
	            ……
	            if (!parseApplication(pkg, res, parser, attrs, flags, outError)) {
	                return null;
	            }
	        } else if (tagName.equals("keys")) {
	            if (!parseKeys(pkg, res, parser, attrs, outError)) {
	                return null;
	            }
	        } else if (tagName.equals("permission-group")) {
	            if (parsePermissionGroup(pkg, flags, res, parser, attrs, outError) == null) {
	                return null;
	            }
	        } else if (tagName.equals("permission")) {
	            if (parsePermission(pkg, res, parser, attrs, outError) == null) {
	                return null;
	            }
	        } else if (tagName.equals("permission-tree")) {
	            if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
	                return null;
	            }
	        } else if (tagName.equals("uses-permission")) {
	            if (!parseUsesPermission(pkg, res, parser, attrs, outError)) {
	                return null;
	            }

	        } else if (tagName.equals("uses-configuration")) {  
	            ......  
	        } else if (tagName.equals("uses-feature")) {  
	            ......  
	        } else if (tagName.equals("uses-sdk")) {  
	            ......  
	        } else if (tagName.equals("supports-screens")) {  
	            ......  
	        } else if (tagName.equals("protected-broadcast")) {  
	            ......  
	        } else if (tagName.equals("instrumentation")) {  
	            ......  
	        } else if (tagName.equals("original-package")) {  
	            ......  
	        } else if (tagName.equals("adopt-permissions")) {  
	            ......  
	        } else if (tagName.equals("uses-gl-texture")) {  
	            ......  
	        } else if (tagName.equals("compatible-screens")) {  
	            ......  
	        } else if (tagName.equals("eat-comment")) {  
	            ......  
	        } else if (RIGID_PARSER) {  
	            ......  
	        } else {  
	            ......  
	        }
	  ……
	  return pkg;
}

由上面的代码知道,该函数主要是解析安装包并根据AndroidManifest.xml文件的标签调用响应的解析函数进行解析,如:parseApplication、parseKeys、parsePermissionGroup、parsePermission、parseUsesPermission等等,并把解析后的信息保存到Package对象pkg中并返回。这里我们只看parseApplication解析函数,其他解析函数类似,具体细节可以查看frameworks/base/core/java/android/content/pm/PackageParser.java函数查看。

parseApplication关键代码如下:

private boolean parseApplication(Package owner, Resources res,
    XmlPullParser parser, AttributeSet attrs, int flags, String[] outError)
    throws XmlPullParserException, IOException {
        final ApplicationInfo ai = owner.applicationInfo;
        final String pkgName = owner.applicationInfo.packageName;
        ……
        ai.icon = sa.getResourceId(
                com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
        ai.logo = sa.getResourceId(
                com.android.internal.R.styleable.AndroidManifestApplication_logo, 0);
        ai.theme = sa.getResourceId(
                com.android.internal.R.styleable.AndroidManifestApplication_theme, 0);
        ai.descriptionRes = sa.getResourceId(
                com.android.internal.R.styleable.AndroidManifestApplication_description, 0);
        ……
        ai.taskAffinity = buildTaskAffinityName(ai.packageName, ai.packageName, str, outError); 
         ……
		ai.uiOptions = sa.getInt(com.android.internal.R.styleable.AndroidManifestApplication_uiOptions, 0);
		……
		while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
		      && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
		  	……
			String tagName = parser.getName();
			if (tagName.equals("activity")) {
			     Activity a = parseActivity(owner, res, parser, attrs, flags, outError, false,
			              hardwareAccelerated);
			     ……
			     owner.activities.add(a);
			} else if (tagName.equals("receiver")) {
			     Activity a = parseActivity(owner, res, parser, attrs, flags, outError, true, false);
			     ……
			     owner.receivers.add(a);
			} else if (tagName.equals("service")) {
			     Service s = parseService(owner, res, parser, attrs, flags, outError);
			     ……
				owner.services.add(s);
			} else if (tagName.equals("provider")) {
			    Provider p = parseProvider(owner, res, parser, attrs, flags, outError);
			    ……
				owner.providers.add(p);
			} else if (tagName.equals("activity-alias")) {
			   Activity a = parseActivityAlias(owner, res, parser, attrs, flags, outError);
			    ……
				owner.activities.add(a);
			} else if (parser.getName().equals("meta-data")) {
			   ……
			} else if (tagName.equals("library")) {
			    ……
			} else if (tagName.equals("uses-library")) {
			   ……
			}else if (tagName.equals("uses-package")) {
			  ……
			}else{
			……
			}
		}//end of while
		return true;
}

parseApplication代码主要解析application标签下的子标签内容,并调用相应子标签对应的函数解析,如:parseActivity、parseService、parseProvider等,并将解析的数据保存到ApplicationInfo和Package对象里,同时检查application及其子标签的格式是否合法。

1.1.4 安装应用程序

到这里,我们再返回到1.1.2节中scanPackageLI完成解析后,调用了另外一个scanPackageLI函数,其定义如下:

private PackageParser.Package scanPackageLI(PackageParser.Package pkg,  
    int parseFlags, int scanMode, long currentTime) {  
    ......  
    synchronized (mPackages) {  
        ......  
        // Add the new setting to mPackages  
        mPackages.put(pkg.applicationInfo.packageName, pkg);  
        ......  
        int N = pkg.providers.size();  
        int i;  
        for (i=0; i<N; i++) {  
            PackageParser.Provider p = pkg.providers.get(i);  
            p.info.processName = fixProcessName(pkg.applicationInfo.processName,  
                p.info.processName, pkg.applicationInfo.uid);  
            mProvidersByComponent.put(new ComponentName(p.info.packageName,  
                p.info.name), p);  
            ......  
        }  

        N = pkg.services.size();  
        for (i=0; i<N; i++) {  
            PackageParser.Service s = pkg.services.get(i);  
            s.info.processName = fixProcessName(pkg.applicationInfo.processName,  
                s.info.processName, pkg.applicationInfo.uid);  
            mServices.addService(s);  

            ......  
        }  

        N = pkg.receivers.size();  
        r = null;  
        for (i=0; i<N; i++) {  
            PackageParser.Activity a = pkg.receivers.get(i);  
            a.info.processName = fixProcessName(pkg.applicationInfo.processName,  
                a.info.processName, pkg.applicationInfo.uid);  
            mReceivers.addActivity(a, "receiver");  
            ......  
        }  

        N = pkg.activities.size();  
        for (i=0; i<N; i++) {  
            PackageParser.Activity a = pkg.activities.get(i);  
            a.info.processName = fixProcessName(pkg.applicationInfo.processName,  
                a.info.processName, pkg.applicationInfo.uid);  
            mActivities.addActivity(a, "activity");  
            ......  
        }  
        ......  
    }  
    ...... 
    //这里主要是获取应用程序的安装目录,并保存到pkg.applicationInfo.dataDir中
    File dataPath;
    if (mPlatformPackage == pkg) {
        // The system package is special.
        dataPath = new File (Environment.getDataDirectory(), "system");
        pkg.applicationInfo.dataDir = dataPath.getPath();
    } else {
        dataPath = getDataPathForPackage(pkg.packageName, 0);

       ……

        if (dataPath.exists()) {
            //条件1:已经安装过,这里系统应用程序是已经安装了的,所以是执行此处的逻辑
            ……
            pkg.applicationInfo.dataDir = dataPath.getPath();
        } else {
            ……
            //条件2:createDataDirsLI才是实际进行安装的操作
            int ret = createDataDirsLI(pkgName, pkg.applicationInfo.uid,
                                       pkg.applicationInfo.seinfo);
            ……
            if (dataPath.exists()) {
                pkg.applicationInfo.dataDir = dataPath.getPath();
            } else {
                Slog.w(TAG, "Unable to create data directory: " + dataPath);
                pkg.applicationInfo.dataDir = null;
            }
        }
        ……
    }
    ……
    return pkg;  
}  

这个函数主要是把前面解析安装包得到的activity、service、receiver、provider等信息保存到PackageParse.Package对象中。
    该函数在解析过程中,如果应用程序第一次安装,则进入条件2的代码逻辑,并调用createDataDirsLI函数,这个函数才是真正安装操作的,安装程序并保存创建的程序目录。但是由于我们是系统启动方式,此时的应用程序都是已经安装了的,所以是进入条件1的代码逻辑。我们会在1.2节中讲手动安装apk的方式,此时进入的就是条件2的代码逻辑。这里我们假设是应用程序未安装,接着分析createDataDirsLI函数。
createDataDirsLI函数定义如下:

private int createDataDirsLI(String packageName, int uid, String seinfo) {
    int[] users = sUserManager.getUserIds();
    int res = mInstaller.install(packageName, uid, uid, seinfo);
    if (res < 0) {
        return res;
    }
    for (int user : users) {
        if (user != 0) {
            res = mInstaller.createUserData(packageName,
                    UserHandle.getUid(user, uid), user);
            if (res < 0) {
                return res;
            }
        }
    }
    return res;
}

可以看到该函数调用Installer类的install成员函数执行安装操作,安装成功后才调用createUserData函数创建应用程序的用户数据。这里我们主要分析Installer类的install成员函数细节。
Installer.java位置: frameworks/base/services/java/com/android/server/pm/Installer.java
install函数定义如下:

public int install(String name, int uid, int gid, String seinfo) {
    StringBuilder builder = new StringBuilder("install");
    builder.append(' ');
    builder.append(name);
    builder.append(' ');
    builder.append(uid);
    builder.append(' ');
    builder.append(gid);
    builder.append(' ');
    builder.append(seinfo != null ? seinfo : "!");
    return execute(builder.toString());
}

该函数将传递的参数组合成一个install的字符串命令,传递给execute函数执行。我们接着分析execute函数。
execute函数定义:

private int execute(String cmd) {
    String res = transaction(cmd);
    try {
        return Integer.parseInt(res);
    } catch (NumberFormatException ex) {
        return -1;
    }
}

该函数调用transaction执行命令。
transaction函数定义:

private synchronized String transaction(String cmd) {
    if (!connect()) {
        ……
    }

    if (!writeCommand(cmd)) {
        ……
    }
    ……
}

这里transaction实际是通过CS的通信方式发送指令给服务端进行具体的操作,包括安装卸载等。
connect是跟服务端进行连接,连接成功后才调用writeCommand函数将具体的命令cmd发送过去。
我们接着看connect函数实现,看它是跟那个服务通信。
connect函数定义:

private boolean connect() {
        if (mSocket != null) {
            return true;
        }
        Slog.i(TAG, "connecting...");
        try {
            mSocket = new LocalSocket();

            LocalSocketAddress address = new LocalSocketAddress("installd",
                    LocalSocketAddress.Namespace.RESERVED);

            mSocket.connect(address);

            mIn = mSocket.getInputStream();
            mOut = mSocket.getOutputStream();
        } catch (IOException ex) {
            disconnect();
            return false;
        }
        return true;
    }

writeCommand函数定义:

private boolean writeCommand(String _cmd) {
    byte[] cmd = _cmd.getBytes();
    int len = cmd.length;
    if ((len < 1) || (len > 1024))
        return false;
    buf[0] = (byte) (len & 0xff);
    buf[1] = (byte) ((len >> 8) & 0xff);
    try {
        mOut.write(buf, 0, 2);
        mOut.write(cmd, 0, len);
    } catch (IOException ex) {
        Slog.e(TAG, "write error");
        disconnect();
        return false;
    }
    return true;
}

    到这里,我们就明了,原来PackageManagerService是跟Installd服务进行通信,通过给Installd服务进程发送具体指令进行安装卸载应用程序,,如上面安装程序操作则发送了一个”install”开头的字符串命令。并通过writeCommand函数发送给Installd服务端进程。
    Installd服务进程是由init进程启动的,其源码位于:frameworks/base/cmds/installd。

仔细看installd.c源码,可以看到一个命令数组:

struct cmdinfo {
    const char *name;
    unsigned numargs;
    int (*func)(char **arg, char reply[REPLY_MAX]);
};

struct cmdinfo cmds[] = {
    //命令名称       参数个数  对应函数
    { "ping",                 0, do_ping },
    { "install",              4, do_install },
    { "dexopt",               3, do_dexopt },
    { "movedex",              2, do_move_dex },
    { "rmdex",                1, do_rm_dex },
    { "remove",               2, do_remove },
    { "rename",               2, do_rename },
    { "fixuid",               3, do_fixuid },
    { "freecache",            1, do_free_cache },
    { "rmcache",              2, do_rm_cache },
    { "getsize",              6, do_get_size },
    { "rmuserdata",           2, do_rm_user_data },
    { "movefiles",            0, do_movefiles },
    { "linklib",              3, do_linklib },
    { "mkuserdata",           3, do_mk_user_data },
    { "rmuser",               1, do_rm_user },
};

到这里,我们就明白了上面的install函数为什么构造一个带有”install”的字符串,其实是发送给Installd服务进程调用do_install执行安装操作。

public int install(String name, int uid, int gid, String seinfo) {
    StringBuilder builder = new StringBuilder("install");
    …
    return execute(builder.toString());
}

我们看do_install函数的实现:

static int do_install(char **arg, char reply[REPLY_MAX])
{
    return install(arg[0], atoi(arg[1]), atoi(arg[2]), arg[3]); /* pkgname, uid, gid, seinfo */
}

这里它调用了commands.c文件的install函数:
install函数定义:

int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
{
    char pkgdir[PKG_PATH_MAX];  //程序目录路径最长256
    char libsymlink[PKG_PATH_MAX];
    char applibdir[PKG_PATH_MAX];
    struct stat libStat;
    // 权限判断
    if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
        ALOGE("invalid uid/gid: %d %d\n", uid, gid);
        return -1;
    }
    // 组合应用程序安装目录pkgdir=”/data/data/应用程序包名”
    if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
        ALOGE("cannot create package path\n");
        return -1;
    }
    ……
    // 创建应用程序安装目录pkgdir=”/data/data/应用程序包名”
    if (mkdir(pkgdir, 0751) < 0) {
        ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
        return -1;
	}
	// 修改应用程序安装目录pkgdir=”/data/data/应用程序包名”权限
    if (chmod(pkgdir, 0751) < 0) {
        ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
        unlink(pkgdir);
        return -1;
    }
    ……
    return 0;
}

至此,我们就分析完系统启东市安装apk的完整流程

1.2 第三方应用安装

手动安装apk函数关系如下图:

1.2.1 调用PackageInstaller应用程序的PackageInstallActivity

我们看下PackageInstaller.apk的AndroidManifest.xml文件中

<activity android:configChanges="keyboardHidden|orientation|screenSize" android:excludeFromRecents="true" android:name=".PackageInstallerActivity">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <action android:name="android.intent.action.INSTALL_PACKAGE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="file"/>
        <data android:mimeType="application/vnd.android.package-archive"/>
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.INSTALL_PACKAGE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="file"/>
        <data android:scheme="package"/>
    </intent-filter>
</activity>

点击的时候发送” android.intent.action.INSTALL_PACKAGE”消息,调用起PackageInstaller.apk应用程序的PackageInstallerActivity处理并开始安装程序。
PackageInstallerActivity定义如下:

public class PackageInstallerActivity extends Activity implements OnCancelListener, OnClickListener {
	private static final String TAG = "PackageInstaller";

	……
	@Override
	    protected void onCreate(Bundle icicle) {
	        super.onCreate(icicle);

	        // 获取Intent传递过来的数据
	        final Intent intent = getIntent();
	        mPackageURI = intent.getData();
	        mOriginatingURI = intent.getParcelableExtra(Intent.EXTRA_ORIGINATING_URI);
	        mReferrerURI = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
	        mPm = getPackageManager();
	        …
	        initiateInstall();
	}
	……
}

我们看到PackageInstallerActivity接收到Intent后,获取其地址,并调用initiateInstall函数开始安装。
initiateInstall函数关键代码如下:

private void initiateInstall() {
    String pkgName = mPkgInfo.packageName;
    ……
    startInstallConfirm();
}

initiateInstall开始检查安装包是否安装过,并调用startInstallConfirm函数弹出选择对话框供用户选择是否安装。也就是下面我们常见的安装界面:

接着分析startInstallConfirm函数,关键代码如下:

private void startInstallConfirm() {
    mInstallConfirm.setVisibility(View.VISIBLE);
    mOk = (Button)findViewById(R.id.ok_button);
    mCancel = (Button)findViewById(R.id.cancel_button);
    mOk.setOnClickListener(this);
    mCancel.setOnClickListener(this);
    if (mScrollView == null) {
        // There is nothing to scroll view, so the ok button is immediately
        // set to install.
        mOk.setText(R.string.install);
        mOkCanInstall = true;
    } else {
        mScrollView.setFullScrollAction(new Runnable() {
            @Override
            public void run() {
                mOk.setText(R.string.install);
                mOkCanInstall = true;
            }
        });
    }
}

startInstallConfirm初始化并显示安装界面,同时绑定确认和取消按钮事件。接下来,我们看onClick函数。
其关键代码如下:

public void onClick(View v) {
    if(v == mOk) {
        if (mOkCanInstall || mScrollView == null) {
            //确认安装,并调用另一个Activity处理
            ……
            newIntent.setClass(this, InstallAppProgress.class);
            ……
            startActivity(newIntent);
            finish();
        } 
        ……
    } else if(v == mCancel) {
        //取消安装
        ……
    }
}

这里面onClick函数发送Intent给InstallAppProgess类处理安装任务。

1.2.2 调用PackageInstaller应用程序的InstallAppProgess

我们查看InstallAppProgess类的onCreate函数。

@Override
public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    Intent intent = getIntent();
    mAppInfo = intent.getParcelableExtra(PackageUtil.INTENT_ATTR_APPLICATION_INFO);
    mInstallFlowAnalytics = intent.getParcelableExtra(EXTRA_INSTALL_FLOW_ANALYTICS);
    mInstallFlowAnalytics.setContext(this);
    mPackageURI = intent.getData();

    final String scheme = mPackageURI.getScheme();
    if (scheme != null && !"file".equals(scheme) && !"package".equals(scheme)) {
        mInstallFlowAnalytics.setFlowFinished(
                InstallFlowAnalytics.RESULT_FAILED_UNSUPPORTED_SCHEME);
        throw new IllegalArgumentException("unexpected scheme " + scheme);
    }

    initView();
}

onCreate获取传递过来的Intent并调用initView函数。
initView函数关键代码如下:

public void initView() {
    ……
    PackageInstallObserver observer = new PackageInstallObserver();

    if ("package".equals(mPackageURI.getScheme())) {
        //安装一个已经存在的应用程序
        try {
            pm.installExistingPackage(mAppInfo.packageName);
            observer.packageInstalled(mAppInfo.packageName,
                    PackageManager.INSTALL_SUCCEEDED);
        } catch (PackageManager.NameNotFoundException e) {
            observer.packageInstalled(mAppInfo.packageName,
                    PackageManager.INSTALL_FAILED_INVALID_APK);
        }
    } else {
        //第一次安装
        pm.installPackageWithVerificationAndEncryption(mPackageURI, observer, installFlags,
                installerPackageName, verificationParams, null);
    }
}

initView先是做一些布局初始化的工作,如果是第一次安装,则调用PackageManager类的installPackageWithVerificationAndEncryption函数完成安装。传递过去的第一个参数实际是安装包的路径,第二个参数则是一个应用程序安装的观察者。
这里PackageManager是抽象类,该函数的具体实现在PackageManagerService类里,所以实际上是调用PackageManagerService服务进行安装。

1.2.3 调用PackageManagerService服务的函数完成安装

跳转到PacakgeManagerService类,查看installPackageWithVerificationAndEncryption函数关键代码:

public void installPackageWithVerificationAndEncryption(Uri packageURI,
    IPackageInstallObserver observer, int flags, String installerPackageName,
    VerificationParams verificationParams, ContainerEncryptionParams encryptionParams) {
    ……
    //该函数发送一个”INIT_COPY”的消息和一个InstallParams类对象给
	//PackageHandler类对象mHandler处理 
    final Message msg = mHandler.obtainMessage(INIT_COPY);
    msg.obj = new InstallParams(packageURI, observer, filteredFlags, installerPackageName,
            verificationParams, encryptionParams, user);
    mHandler.sendMessage(msg);
}

我们跳转到PackageHandler类的消息处理函数handleMessage:

public void handleMessage(Message msg) {
    try {
        doHandleMessage(msg);
    } finally {
        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
    }
}

该函数调用doHandleMessage进行消息处理,我们看看doHandleMessage接收到INIT_COPY消息后如何处理:

void doHandleMessage(Message msg) {
	switch (msg.what) {
	    case INIT_COPY: {
	        ……
	        if (!mBound) {
	           ……
	        } else {
	            mPendingInstalls.add(idx, params);
	            //发送MCS_BOUND消息
	            if (idx == 0) {
	                mHandler.sendEmptyMessage(MCS_BOUND);
	            }
	        }
	        break;
	    }
	 case MCS_BOUND: {
	        ……
	        if (mContainerService == null) {
	            ……
	        } else if (mPendingInstalls.size() > 0) {
	            HandlerParams params = mPendingInstalls.get(0);
	            if (params != null) {
	                if (params.startCopy()) {
	                    ……
	                    
	                }
	            }
	        }
	        ……
	    }
	……
	}
}

在接收到INIT_COPY消息后,mHandler又给自己发送MCS_BOUND消息。在该消息的处理过程中,调用HandlerParams类的startCopy函数。注意的是HandlerParams是抽象类,InstallParams继承了HandlerParams并实现下述3个抽象函数。后面分析到这3个函数,我们 就需要到HandleParams类下查找。

  • abstract void handleStartCopy() throws RemoteException;
  • abstract void handleServiceError();
  • abstract void handleReturnCode();

我们继续看startCopy函数的关键代码:

final boolean startCopy() {
    boolean res;
    try {
        ……

        if (++mRetries > MAX_RETRIES) {
            ……
            handleServiceError();
            return false;
        } else {
            handleStartCopy();
            res = true;
        }
    } catch (RemoteException e) {
        ……
    }
    handleReturnCode();
    return res;
}

startCopy调用了3个函数:handleServiceError、handleStartCopy和handleReturnCode。

handleServiceError是用来处理安装错误的,这里我们不展开讲;
handleStartCopy主要是获取安装包信息,并给两个关键变量完成赋值工作,分别是InstallArgs类对象mArgs和mRet变量。
handleStartCopy关键代码:

public void handleStartCopy() throws RemoteException {
    int ret = PackageManager.INSTALL_SUCCEEDED;
    ……

    final InstallArgs args = createInstallArgs(this);
    mArgs = args;
    ……
    mRet = ret;
}

handleReturnCode函数定义如下:

@Override
void handleReturnCode() {
    
    if (mArgs != null) {
        processPendingInstall(mArgs, mRet);
        ……
    }
}

这里,我们看到handleReturnCode调用processPendingInstall并传递handleStartCopy赋值的两个参数mArgs和mRet。
processPendingInstall函数关键代码如下:

private void processPendingInstall(final InstallArgs args, final int currentStatus) {
    // Queue up an async operation since the package installation may take a little while.
    mHandler.post(new Runnable() {
        public void run() {
            mHandler.removeCallbacks(this);
             // Result object to be returned
            PackageInstalledInfo res = new PackageInstalledInfo();
            res.returnCode = currentStatus;
            res.uid = -1;
            res.pkg = null;
            res.removedInfo = new PackageRemovedInfo();
            if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
                args.doPreInstall(res.returnCode);
                synchronized (mInstallLock) {
                    installPackageLI(args, true, res);
                }
                args.doPostInstall(res.returnCode, res.uid);
            }
            ……
        }
    });
}

该函数启动了一个线程并调用installPackageLI安装。

private void installPackageLI(InstallArgs args,
        boolean newInstall, PackageInstalledInfo res) {
    ……
	if (replace) {
        replacePackageLI(pkg, parseFlags, scanMode, args.user,
                installerPackageName, res);
    } else {
        installNewPackageLI(pkg, parseFlags, scanMode | SCAN_DELETE_DATA_ON_FAILURES, args.user,
                installerPackageName, res);
    }
    ……
}

这里,installPackageLI有两种操作,如果应用程序已经在,则调用replacePackageLI替换,如果是第一次安装,则调用installNewPackageLI函数,这里我们假设是第一次安装。
接下来分析installNewPackageLI函数的关键代码:

private void installNewPackageLI(PackageParser.Package pkg,
    int parseFlags, int scanMode, UserHandle user,
    String installerPackageName, PackageInstalledInfo res) {
	……
	PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
	        System.currentTimeMillis(), user);
	……
}

这里,我们又看到1.1分析中调用的scanPackageLI函数,后面的分析就跟1.1.4节一样了,这里就不重复讲。

1.3通过ADB命令安装

TODO:继续详细化ADB内容
ADB的执行机制其实是按照客户端、服务端的方式工作。
(1)客户端:adb或adb.exe,运行于PC段
(2)服务端:adbd,运行在手机端或模拟器等设备上的守护进程。该进程由init父进程创建。

通过ADB命令方式安装,其整体函数关系如下图所示:

首先,要想进一步了解ADB命令安装的工作方式,就需要我们进一步研究adb模块的源码。adb运行的入口在:
system\core\adb\adb.c,我们查看main函数定义:

int main(int argc, char **argv)
{
#if ADB_HOST //也就是我们的PC客户端
    adb_sysdeps_init();
    adb_trace_init();
    D("Handling commandline()\n");
    return adb_commandline(argc - 1, argv + 1); //运行PC段的adb/adb.exe可执行程序
#else
    /* If adbd runs inside the emulator this will enable adb tracing via
     * adb-debug qemud service in the emulator. */
    adb_qemu_trace_init();
    if((argc > 1) && (!strcmp(argv[1],"recovery"))) {
        adb_device_banner = "recovery";
        recovery_mode = 1;
    }

    start_device_log();
    D("Handling main()\n");
    return adb_main(0, DEFAULT_ADB_PORT); //运行在目标设备上的adbd可执行程序
#endif
}

接着分析adb_commandline函数的关键代码:

int adb_commandline(int argc, char **argv)
{
	……
	if(!strcmp(argv[0], "devices")) {….}
	if(!strcmp(argv[0], "connect")) {…}
	if(!strcmp(argv[0], "disconnect")) {…}
	if (!strcmp(argv[0], "emu")) {…}
	if(!strcmp(argv[0], "shell") || !strcmp(argv[0], "hell")) {…}
	if(!strcmp(argv[0], "kill-server")) {…}
	if(!strcmp(argv[0], "sideload")) {…}
	if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
	            || !strcmp(argv[0], "reboot-bootloader")
	            || !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
	            || !strcmp(argv[0], "root")) {…}
	……
	if(!strcmp(argv[0], "install")) {
	        if (argc < 2) return usage();
	        return install_app(ttype, serial, argc, argv);
	    }

	    if(!strcmp(argv[0], "uninstall")) {
	        if (argc < 2) return usage();
	        return uninstall_app(ttype, serial, argc, argv);
	    }
	……
}

adb_commandline其实就是处理我们输入的命令行,调用响应的函数工作。

我们看到当收到”install”指令时,调用install_app函数执行安装工作。

int install_app(transport_type transport, char* serial, int argc, char** argv)
{
	……
	apk_file = argv[file_arg];
	……
	err = do_sync_push(apk_file, apk_dest, verify_apk);
	……
	pm_command(transport, serial, argc, argv);
	……
}

install_app再安装前,调用了pm_command函数做一些命令行修改,实际就是给命令行字符串添加”shell:pm”指令,这里pm其实就是pm.jar,Package管理器。pm.jar主要执行终端下传递过来的pm命令。类似的jar包还有am.jar,Activity管理器等,它们都位于\system\framework目录下。
也就是说,adb命令安装方式实际上是调用pm包管理器来对安装包进行安装卸载等工作。
    pm.jar包的关键方法:Pm.java,其文件位置:com/android/commands/pm/Pm.java。
该文件的入口函数为:main函数:

public final class Pm {
	IPackageManager mPm;
	IUserManager mUm;
	    ……

	    public static void main(String[] args) {
	        new Pm().run(args);
	}
	……
}

main函数创建Pm类对象并调用run函数,其关键代码如下:

public void run(String[] args) {
    ……
    mUm = IUserManager.Stub.asInterface(ServiceManager.getService("user"));
    mPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
    ……

    if ("list".equals(op)) {
        runList();
        return;
    }

    if ("path".equals(op)) {
        runPath();
        return;
    }

    if ("dump".equals(op)) {
        runDump();
        return;
    }

    if ("install".equals(op)) {
        runInstall();
        return;
    }

    if ("uninstall".equals(op)) {
        runUninstall();
        return;
    }
    ……
}

我们分析下面这行代码:
TODO: 学习了解下Binder机制
mPm = IPackageManager.Stub.asInterface(ServiceManager.getService(“package”))。
Stub是接口IPackageManager的静态抽象类,asInterface是返回IPackageManager代理的静态方法。
我们在返回看PackageManagerService.java的定义:

public class PackageManagerService extends IPackageManager.Stub {
……
}
所以,IPackageManager类对象mPm的函数实际上是调用PackageManagerService类对应的函数。

安装操作会调用runInstall函数。
runInstall函数关键代码如下:

private void runInstall() {
    …….
    PackageInstallObserver obs = new PackageInstallObserver();
    try {
        ……
        mPm.installPackageWithVerificationAndEncryption(apkURI, obs, installFlags,
                installerPackageName, verificationParams, encryptionParams);
        ……
    } catch (RemoteException e) {
        System.err.println(e.toString());
        System.err.println(PM_NOT_RUNNING_ERR);
    }
}

这里,runInstal通过mPm对象调用installPackageWithVerificationAndEncryption函数实现具体的安装操作。通过上面的分析,我们知道实际上mPm调用的是PackageManagerService下的installPackageWithVerificationAndEncryption函数。这里就跟我们上面1.2.3节分析的一样了,这里就不展开讲。

1.4 通过Google Play安装

在Google市场下载完应用程序时,会自动调用PackageManager类的installPackage方法进行安装。PackageManager是抽象类,installPackage函数在PackageManagerService类中实现。
installPackage函数定义如下:

/* Called when a downloaded package installation has been confirmed by the user */
public void installPackage(
        final Uri packageURI, final IPackageInstallObserver observer, final int flags) {
    installPackage(packageURI, observer, flags, null);
}

通过函数的注释我们可以知道这个是通过网络下载的方式安装APK。
该函数调用另一个installPackage函数:

public void installPackage(
    final Uri packageURI, final IPackageInstallObserver observer, final int flags,
    final String installerPackageName) {
    installPackageWithVerification(packageURI, observer, flags, installerPackageName, null,
            null, null);
}

该函数调用installPackageWithVerification:

@Override
public void installPackageWithVerification(Uri packageURI, IPackageInstallObserver observer,
        int flags, String installerPackageName, Uri verificationURI,
        ManifestDigest manifestDigest, ContainerEncryptionParams encryptionParams) {
    VerificationParams verificationParams = new VerificationParams(verificationURI, null, null,
            VerificationParams.NO_UID, manifestDigest);
    installPackageWithVerificationAndEncryption(packageURI, observer, flags,
            installerPackageName, verificationParams, encryptionParams);
}

到这里,我们看到installPackageWithVerification调用了installPackageWithVerificationAndEncryption函数进行安装,该函数我们在1.2.3节中已经分析,这里就不做展开。下面附上通过该方式安装应用程序的函数关系图:

1.5 总结

1.6 参考

  • Android应用程序安装过程源代码分析 http://blog.csdn.net/luoshengyang/article/details/6766010
  • Android内核开发:前夕APK的安装过程 http://ticktick.blog.51cto.com/823160/1669525
  • Android App安装过程学习笔记 http://palanceli.com/2016/10/23/2016/1015Installer1/
  • 《深入理解Android》卷II http://wiki.jikexueyuan.com/project/deep-android-v2/packagemanagerservice.html
  • http://androidxref.com/4.4.3_r1.1/xref/frameworks/base/services/java/com/android/server/SystemServer.java
  • http://androidxref.com/4.4.3_r1.1/xref/frameworks/base/core/java/android/content/pm/PackageParser.java
  • http://androidxref.com/4.4.3_r1.1/raw/frameworks/base/services/java/com/android/server/pm/PackageManagerService.java
  • http://androidxref.com/4.4.3_r1.1/xref/frameworks/base/services/java/com/android/server/pm/Installer.java
  • http://androidxref.com/4.4.3_r1.1/xref/frameworks/native/cmds/installd/
  • http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.3_r1/com/android/commands/pm/Pm.java
  • http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.3_r1/android/os/ServiceManager.java
  • 《Android安全架构深究》
  • Android安装服务installd源码分析 http://blog.csdn.net/yangwen123/article/details/11104397
  • APK安装过程及原理详解 https://www.kancloud.cn/digest/androidframeworks/127788
  • 小白雪Android之adb篇(三) http://yupengt66y.wang/2016/04/18/adb-study-03/
  • ADB源码分析 http://sunzeduo.blog.51cto.com/2758509/1401170
  • android系统源码目录system/framework下各个jar包的用途 https://my.oschina.net/DragonWang/blog/62082
  • http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/4.4.3_r1/com/android/packageinstaller/PackageInstallerActivity.java

发表评论

电子邮件地址不会被公开。 必填项已用*标注