声明:此文章来自http://shuwoom.com/?p=60的学习记录
启动式安装
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对象。
应用程序在安装时涉及到如下几个重要目录:
system/app | 系统应用程序的目录 |
data/app | 用户程序安装的目录 |
data/data | 存放应用程序数据的目录 |
data/dalvik-cache | 存放的是经过优化的dex文件 |
PackageManagerService是Android系统的核心服务之一,在系统启动的时候由SystemServer组件负责启动起来。PackageManagerService用于管理系统中的所有安装包信息以及应用程序的安装和卸载,但是实际应用程序的安装卸载并不是由PackageManagerService亲自完成,而是通过socket通信,PackageManagerService来访问installd服务来实现应用程序的安装和卸载。
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();}
}
SystemServer中的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);……}
}
PackageManagerService构造函数如下
public PackageManagerService(Context context, Installer installer,boolean factoryTest, boolean onlyCore) {synchronized (mInstallLock) {// writersynchronized (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”目录下的apkscanDirLI(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”目录下的apkscanDirLI(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”目录下的apkscanDirLI(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目录下的apkscanDirLI(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状态falseif (!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”目录下的apkscanDirLI(mAppInstallDir, 0, scanMode, 0);mDrmAppInstallObserver = new AppDirObserver(mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false, false);mDrmAppInstallObserver.startWatching();//扫描”/data/app-private”目录下的apkscanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,scanMode, 0);……} ……..
}
这里调用了很多scanDirLI,这个函数调用了scanPackageLI
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'scontinue;}PackageParser.Package pkg = scanPackageLI(file,flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);……}
}
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;
}
其调用了parsePackage用于获取apk中的资源对象res和对Androidmanifest.xml文件进行格式化,并调用另一个parsePackage函数进一步做解析,也是package类真正生成的地方
啥是package?
package类是安卓框架中用于表示一个应用程序包的结构和信息的类。它包含了应用程序的多个方面的信息,包括:
- 包名:唯一标识应用程序的字符串,通常是反向域名格式(例如,
com.example.myapp
)。 - 版本信息:包括应用程序的版本号和版本代码,帮助识别应用的更新和兼容性。
- 权限:声明应用所需的权限,例如访问互联网、读取联系人等。
- 组件:描述应用程序包含的组件,如活动(Activity)、服务(Service)、内容提供者(Content Provider)和广播接收器(Broadcast Receiver)。
保存了app的信息之后 调用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;
}
调用了install类的install方法 install调用execute execute调用transaction transaction进行客户端-服务端通信,首先判断客户端-服务端是否连接
然后调用writeCommand向服务端通过socket,向服务端发送指令
如果发送的指令是install 服务端就会调用do_install进行安装 do_install调用了commands.c文件的install函数执行安装
int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
{char pkgdir[PKG_PATH_MAX]; //程序目录路径最长256char 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;
}
点击安装
ADB安装
商店安装
总结:实际上四种安装方式都有用到PackageManagerService,而PackageManagerService也都是通过客户端-服务端的方式,向服务端发送命令进行安装的,也是四种安装方式的共同点。