PackageManagerService分析之一

来源:互联网 发布:网络订票如何选下铺 编辑:程序博客网 时间:2024/06/06 19:28

1, 基本概念

PackageManagerService(简称PMS), 是android系统中一个核心的服务,

它负责系统中Package的管理,应该程序的安装、卸载等.在SystemServer的startBootstrapServices方法启动。

mPackageManagerService = PackageManagerService.main(mSystemContext, installer,                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
PMS的main方法如下,
   public static PackageManagerService main(Context context, Installer installer,            boolean factoryTest, boolean onlyCore) {        PackageManagerService m = new PackageManagerService(context, installer,                factoryTest, onlyCore);        ServiceManager.addService("package", m); // 注册        return m;    }

看来所有动作都在PMS的构造方法中完成的。

再看看PMS的结构可知,PMS服务也是一个Binder服务,

public class PackageManagerService extends IPackageManager.Stub {

在ActivityThread的getPackageManager方法中,可以获取PMS服务。

if (sPackageManager != null) {            //Slog.v("PackageManager", "returning cur default = " + sPackageManager);            return sPackageManager;        }        IBinder b = ServiceManager.getService("package");        //Slog.v("PackageManager", "default service binder = " + b);        sPackageManager = IPackageManager.Stub.asInterface(b);        //Slog.v("PackageManager", "default service = " + sPackageManager);        return sPackageManager;    }

PMS的构造方法很长很长,主要包括以下逻辑

  • 扫描目标文件夹之前的准备工作。
  • 扫描目标文件夹。
  • 扫描之后的工作。

 

2, 准备工作

PMS的构造方法关于Settings部分代码如下,

mSettings = new Settings(mPackages);        mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);        mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);        mSettings.addSharedUserLPw("android.uid.log", LOG_UID,                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);        mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);        mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);        mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

mPackages是一个ArrayMap变量,

@GuardedBy("mPackages")    final ArrayMap<String, PackageParser.Package> mPackages =            new ArrayMap<String, PackageParser.Package>();

流程图如下,


2.1 Settings

Settings的构造方法如下,

Settings(Object lock) {        this(Environment.getDataDirectory(), lock);    }    Settings(File dataDir, Object lock) {        mLock = lock;        mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);        mSystemDir = new File(dataDir, "system");        mSystemDir.mkdirs();        FileUtils.setPermissions(mSystemDir.toString(),                FileUtils.S_IRWXU|FileUtils.S_IRWXG                |FileUtils.S_IROTH|FileUtils.S_IXOTH,                -1, -1);        mSettingsFilename = new File(mSystemDir, "packages.xml");        mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");        mPackageListFilename = new File(mSystemDir, "packages.list");        FileUtils.setPermissions(mPackageListFilename, 0640, SYSTEM_UID, PACKAGE_INFO_GID);        // Deprecated: Needed for migration        mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");        mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");    }

新建了5个文件夹,

private final File mSettingsFilename;    private final File mBackupSettingsFilename;    private final File mPackageListFilename;    private final File mStoppedPackagesFilename;    private final File mBackupStoppedPackagesFilename;

Environment.getDataDirectory()返回/data目录,然后创建/data/system/目录,并设置它的权限,

并 在/data/system目录中创建5个文件。packages.xml就是保存了系统所有的Package信息,

packages-backup.xml是packages.xml的备份,防止在写packages.xml突然断电等问题。

2.2 addSharedUserLPw

mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

调用addSharedUserLPw将几种SharedUserId的名字和它对应的UID对应写到Settings当中。

关于 SharedUserId的使用,在后面介绍APK的安装过程中再来分析. Process中提供的UID列表如下,

public static final int ROOT_UID = 0; public static final int SYSTEM_UID = 1000; // systempublic static final int PHONE_UID = 1001;// telephonypublic static final int SHELL_UID = 2000;// user shellpublic static final int LOG_UID = 1007;// log group public static final int WIFI_UID = 1010;// WIFI•••

Settings中的addSharedUserLPw方法如下,

SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {        SharedUserSetting s = mSharedUsers.get(name);        if (s != null) {            if (s.userId == uid) {                return s;            }            PackageManagerService.reportSettingsProblem(Log.ERROR,                    "Adding duplicate shared user, keeping first: " + name);            return null;        }        s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);        s.userId = uid;        if (addUserIdLPw(uid, s, name)) {            mSharedUsers.put(name, s);            return s;        }        return null;    }

首先根据name, pkgFlags, pkgPrivateFlags等信息构造SharedUserSetting,然后添加到mSharedUsers的ArrayMap中。

final ArrayMap<String, SharedUserSetting> mSharedUsers =            new ArrayMap<String, SharedUserSetting>();

例如在SystemUI.apk的AndroidManifest.xml文件中,有关键代码:

<mainfest xmlns:android="http://schemas.android.com/apk/res/android"        package="com.android.systemui"        coreApp="true"        android:sharedUserId="android.uid.system"        android:process="system">

在该标签中,声明了一个android:sharedUserId的属性,其值为“android.uid.system”。sharedUserId和UID有关,它的作用是

1,两个或者多个声明了同一种sharedUserid的APK可共享彼此的数据,并且可运行在同一进程中。

2,通过声明特定的sharedUserId,该APK所在的进程将被赋予指定UID。

例如SystemUI声明了system的uid,运行SystemUI的进程就可享有system用户所对应的权限了,实际上就是将该进程的UID设置为system的uid了

2.3 XML文件扫描

接下来是扫描系统目录下与系统权限相关的xml文件,新建文件,处理线程和Handler等。

String separateProcesses = SystemProperties.get("debug.separate_processes");        if (separateProcesses != null && separateProcesses.length() > 0) {            if ("*".equals(separateProcesses)) {                mDefParseFlags = PackageParser.PARSE_IGNORE_PROCESSES;                mSeparateProcesses = null;                Slog.w(TAG, "Running with debug.separate_processes: * (ALL)");            } else {                mDefParseFlags = 0;                mSeparateProcesses = separateProcesses.split(",");                Slog.w(TAG, "Running with debug.separate_processes: "                        + separateProcesses);            }        } else {            mDefParseFlags = 0;            mSeparateProcesses = null;        }        mInstaller = installer;        mPackageDexOptimizer = new PackageDexOptimizer(this);        mMoveCallbacks = new MoveCallbacks(FgThread.get().getLooper());        mOnPermissionChangeListeners = new OnPermissionChangeListeners(                FgThread.get().getLooper());        getDefaultDisplayMetrics(context, mMetrics);        SystemConfig systemConfig = SystemConfig.getInstance();        mGlobalGids = systemConfig.getGlobalGids();        mSystemPermissions = systemConfig.getSystemPermissions();        mAvailableFeatures = systemConfig.getAvailableFeatures();

新建文件

 File dataDir = Environment.getDataDirectory();            mAppDataDir = new File(dataDir, "data");            mAppInstallDir = new File(dataDir, "app");            mAppLib32InstallDir = new File(dataDir, "app-lib");            mAsecInternalPath = new File(dataDir, "app-asec").getPath();            mUserAppDataDir = new File(dataDir, "user");            mDrmAppPrivateInstallDir = new File(dataDir, "app-private");            mRegionalizationAppInstallDir = new File(dataDir, "app-regional");

解析系统权限文件, 主要是解析系统目录下xml文件,获得设备相关的权限.

 例如该设备是否支持蓝牙,wifi等

ArrayMap<String, SystemConfig.PermissionEntry> permConfig                    = systemConfig.getPermissions();            for (int i=0; i<permConfig.size(); i++) {                SystemConfig.PermissionEntry perm = permConfig.valueAt(i);                BasePermission bp = mSettings.mPermissions.get(perm.name);                if (bp == null) {                    bp = new BasePermission(perm.name, "android", BasePermission.TYPE_BUILTIN);                    mSettings.mPermissions.put(perm.name, bp);                }                if (perm.gids != null) {                    bp.setGids(perm.gids, perm.perUser);                }            }

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 父亲沉迷安利十年该怎么办 脚的大脚骨痛怎么办 自考准考证号忘记了怎么办 有桌子老师不出马怎么办 电商遇到职业打假人怎么办 超市遇到职业打假人怎么办 阿里巴巴碰到职业打假人怎么办 商家遇到职业打假人怎么办 买过期食品不赔怎么办 淘宝卖假货遇到打假师怎么办 网店遇到职业打假人怎么办 职业打假师把我起诉法院怎么办 被职业打假举报了怎么办 车档杆拉不动显示不在p档怎么办 宜人贷还不起了怎么办 买高跟鞋一只脚合适一只脚挤怎么办 脚瘦穿高跟鞋撑不起来怎么办 银川市阅海幼儿园进不去怎么办 考编专业不对口怎么办 北京55中国际部怎么办 初中数学没学好高中怎么办 靴子大了一码怎么办 靴子买大了一码怎么办 马丁靴大了一码怎么办 社保掌上通登录密码忘记怎么办 录微课时忘词怎么办 微课掌上通看不到信息怎么办 五年级学生上课很吵新老师怎么办 跟财务老师吵起来怎么办 qq把微信冻结了怎么办 微信给封号了怎么办 微信久了没登录冻结了怎么办 换手机号了微店怎么办 ai文件置入后都是字怎么办 excel加载项被禁用了怎么办 被期刊网骗了怎么办 发表的文章不想被收录怎么办? 农村长说的眼睛害了怎么办 普通党员不认同领导的决定怎么办 大学读不下去了怎么办 教师因病长期不能上班怎么办