PackageManagerService服务框架详解

PMS作用:

https://blog.csdn.net/alexwll/article/details/102777742

1.管理系统的jar包和系统的apk,负责系统的权限

2.负责apk的卸载,安装,更新,解析

3.对其他应用服务提供安装卸载服务;

PMS启动过程描述:

和intsalld链接进行apk的安装卸载操作(实际安装卸载apk是有installd来进行的,PMS只是提供接口);

创建PackageHandle来处理外部apk的安装卸载请求;

处理系统权限相关文件

扫描安装

 

PMS的结构图:

service-client结构

service:提供代理类proxy给client调用,所有动作的具体实现都是在Service中实现的。

    PackageManagerService,(    )

client:获得Service的proxy实现调用

    PackageManager,ApplicationManager,其余都是Service

客户端:

PackageManager实际是一个抽象类,主要是用来调用Service中的方法。以getPackageInfo为例,来讲述Client如何调用Service中的方法:

frameworks/base/core/java/android/content/pm/PackageManager.java

public abstract class PackageManager {
    ...//三个点代表省略部分代码
    public abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags)
            throws NameNotFoundException;
     @RequiresPermission(Manifest.permission.INTERACT_ACROSS_USERS)
    public abstract PackageInfo getPackageInfoAsUser(String packageName,
            @PackageInfoFlags int flags, @UserIdInt int userId) throws NameNotFoundException;
    ...
}

对PackManager的调用上下文ContextImpl.java,即使用Context.getPackageManager();

/frameworks/base/core/java/android/app/ContextImpl.java

@Override
    public PackageManager getPackageManager() {
        if (mPackageManager != null) {
            return mPackageManager;
        }

        IPackageManager pm = ActivityThread.getPackageManager();
        if (pm != null) {
            // Doesn't matter if we make more than one instance.
            return (mPackageManager = new ApplicationPackageManager(this, pm));
        }

        return null;
    }

分为:

(1)ActivityThread.getPackageManager()

frameworks/base/core/java/android/app/ActivityThread.java

@UnsupportedAppUsage
    public static IPackageManager getPackageManager() {
        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;
    }

首先获取package服务,实际是PackageManagerService(PMS),然后IPackageManager.Stub.asInterface(b)得到内部类,即代理类IPackageManager.Stub.Proxy。即调用了proxy.getPackageInfo方法。

(2)return (mPackageManager = new ApplicationPackageManager(this, pm));

/frameworks/base/core/java/android/app/ApplicationPackageManager.java

    @Override
    public PackageInfo getPackageInfo(String packageName, int flags)
            throws NameNotFoundException {
        return getPackageInfoAsUser(packageName, flags, getUserId());
    }

    @Override
    public PackageInfo getPackageInfo(VersionedPackage versionedPackage, int flags)
            throws NameNotFoundException {
        final int userId = getUserId();
        try {
            PackageInfo pi = mPM.getPackageInfoVersioned(versionedPackage,
                    updateFlagsForPackage(flags, userId), userId);
            if (pi != null) {
                return pi;
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        throw new NameNotFoundException(versionedPackage.toString());
    }
/×××××××××××××××××××××××××××××××××××××××××××××/
    @Override
    public PackageInfo getPackageInfoAsUser(String packageName, int flags, int userId)
            throws NameNotFoundException {
        try {
            PackageInfo pi = mPM.getPackageInfo(packageName,
                    updateFlagsForPackage(flags, userId), userId);
            if (pi != null) {
                return pi;
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        throw new NameNotFoundException(packageName);
    }


/***********************************************/
  private final IPackageManager mPM;
/***********************************************/

IPackageManager:即aidl接口

服务端

 

PackageManagerservice

 

PackageManagerservice对权限的处理过程:

读取权限:

遍历、system/etc/permissions/目录下的xml文件并将解析结果添加到哈希对象中;

data/system   permissions

 

 

更新安装apk和jar包

更新system/framework/下的jar包

创建监控线程system/app

scanDirLi:扫描系统中的apk

解析AndroidManifest.xml的信息

将安装包apk的信息添加到本地配置,系统重新启动不需要再次安装。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

public class PackageManagerService extends IPackageManager.Stub {
    ...
    public static PackageManagerService main(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {
        // Self-check for initial settings.
        PackageManagerServiceCompilerMapping.checkProperties();
    //创建PackageManagerService
        PackageManagerService m = new PackageManagerService(context, installer,
                factoryTest, onlyCore);
        m.enableSystemUserPackages();
        // Disable any carrier apps. We do this very early in boot to prevent the apps from being
        // disabled after already being started.
        CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m,
                UserHandle.USER_SYSTEM);
    //创建完成后把PMS加入到ServiceManager中
        ServiceManager.addService("package", m);
        return m;
    }
    ...
    @Override
    public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
        if (!sUserManager.exists(userId)) return null;
        flags = updateFlagsForPackage(flags, userId, packageName);
        enforceCrossUserPermission(Binder.getCallingUid(), userId,
                false /* requireFullPermission */, false /* checkShell */, "get package info");
        // reader
        synchronized (mPackages) {
            final boolean matchFactoryOnly = (flags & MATCH_FACTORY_ONLY) != 0;
            PackageParser.Package p = null;
            if (matchFactoryOnly) {
                final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
                if (ps != null) {
                    return generatePackageInfo(ps, flags, userId);
                }
            }
            if (p == null) {
                p = mPackages.get(packageName);
                if (matchFactoryOnly && p != null && !isSystemApp(p)) {
                    return null;
                }
            }
            if (DEBUG_PACKAGE_INFO)
                Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
            if (p != null) {
                return generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
            }
            if (!matchFactoryOnly && (flags & MATCH_UNINSTALLED_PACKAGES) != 0) {
                final PackageSetting ps = mSettings.mPackages.get(packageName);
                return generatePackageInfo(ps, flags, userId);
            }
        }
        return null;
    }
}

我们来分析这个代码片段:
1、第一点也是最关键的一点,PackageManagerService继承IPackageManager.Stub类,而IPackageManager.Stub类继承自Binder实现IpackageManager接口
2、这里请上翻看客户端中讲的最后个方法ActivityThread.getPackageManager(),这个方法中先是获得Binder实例:IBinder b = ServiceManager.getService("package")然后通过binder实例获得代理类Proxy
3、我们看服务端代码,在PMS创建完成后就添加到了ServiceManager中:ServiceManager.addService("package", m);所以2中实际得到的是PMS的Binder类型实例,然后得到PMS的代理类
4、接着上面的getPackageInfo方法,调用到Stub中的getPackageInfo接口方法,PackageManagerService则是接口方法getPackageInfo的实现,所以最终方法是调用到了PackageManagerService.getPackageInfo

 

 

Android程序包管理机制

包含内容:

根据Intent 匹配到对应的的Activity,provider,Service。即应用程序调用startAtivity(inent),能将参数中包含的特定intent转换成对应的一个包含此信息的activity。

进行权限检查。当需要特定权限时,系统可判断是否拥有权限。

提供安装,删除应用程序的接口。

包管理分为三层:

应用程序层,PMS服务层,数据文件层

1.应用程序层

应用程序使用包管理服务时,调用Contextlmpl类的getPackageManager()返回一个ApplicationPackageManager对象,继承于PackageManager抽象类。    参数传入Pms,Apm类调用各种pms的类方法。

2.数据文件层

使用xml文件管理相关信息。

第一个目录:"system/etc/permissions"该目录用于权限的管理,定义系统中包含了那些用户权限,应用可以在AndroidMananifest.xml,其中platform.xml为特别的uid和gid分配了默认的权限。

第二个目录:"data/system/packages.xml"保存安装程序的基本包信息,例如:

<packages>
    <last-platform-version internal="19" external="19" />
    <permission-trees />
    <permissions>
        <item name="android.permission.CHANGE_WIFI_MULTICAST_STATE" package="android" protection="1" />
        <item name="android.permission.WRITE_CALL_LOG" package="android" protection="1" />
        <item name="android.permission.CLEAR_APP_CACHE" package="android" protection="1" />
        <item name="android.permission.AUTHENTICATE_ACCOUNTS" package="android" protection="1" />
        <item name="android.permission.ACCESS_WIMAX_STATE" package="android" />
        <item name="android.permission.ASEC_ACCESS" package="android" protection="2" />
        ....
             <item name="android.permission.VIBRATE" package="android" />
        <item name="android.permission.READ_CELL_BROADCASTS" package="android" protection="1" />
    </permissions>
    <package name="com.myapp" codePath="/data/app/com.myapp-2.apk" nativeLibraryPath="/data/app-lib/com.myapp-2" flags="4767302" ft="15e3b437430" it="15e37659f09" ut="15e3b4378f4" version="1" userId="10043">
        <sigs count="1">
            <cert index="0" key="308201dd30820146020101300d06092a864886f70d010105050030373116301406035504030c0d416e64726f69642044656275673110300e060355040a0c07416e64726f6964310b3009060355040613025553301e170d3137303833313...7d6c66ce" />
        </sigs>
        <perms />
        <signing-keyset identifier="1" />
    </package>

所有系统app保存在System/app或System/pri-app/下面。第二个中的service不可以被kill掉。

非系统app保存在data/app/目录下,/data/davik-cache目录下保存了程序执行代码,当程序运行前,Pms会从APK文件中提取出代码文件也就是dex文件,并将该文件存储在该目录下,以便以后能快速运行该程序。

framework库文件,这些文件保存在/system/framework目录下,系统开机时davik虚拟机会加载这些库文件,在pms启动时,将这些文件转换成dex文件,并保存到/data/dalvik-cache目录下。

应用程序使用的数据文件。分别为sharepreference存储、数据库存储和文件存储,前两种文件一般会保存在/data/data/xxx/目录下,xxx代表程序包名,文件存储可以保存在内置存储或者外置存储的任意位置。

未完待续。。。。。。

 

3.PMS服务层

 

1.启动入口

PMS属于系统服务,启动入口在SystemServer中的main方法

public static void main(String[] args) {
    new SystemServer().run();
}
private void run() {
    ...
        traceBeginAndSlog("StartServices");
        //启动引导服务,PMS的启动包含在此
        startBootstrapServices();
        //启动核心服务
        startCoreServices();
        //启动其他服务
        startOtherServices();
    ...
}
private void startBootstrapServices() {
    ...
    //启动安装服务
    traceBeginAndSlog("StartInstaller");
    Installer installer = mSystemServiceManager.startService(Installer.class);
    traceEnd();
    ...
    //启动PMS
    // Start the package manager.
    if (!mRuntimeRestart) {
        MetricsLogger.histogram(null, "boot_package_manager_init_start",
                (int) SystemClock.elapsedRealtime());
    }
    traceBeginAndSlog("StartPackageManagerService");
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();
    traceEnd();
    if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
        MetricsLogger.histogram(null, "boot_package_manager_init_ready",
                (int) SystemClock.elapsedRealtime());
    }
    ...
}
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
            mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

概括来讲,Android系统启动时,会创建SystemServer进程,进程运行会执行SystemServer类中的run方法,在run方法中会启动三类服务,包括引导服务、核心服务和其他服务,PMS包含在引导服务中,在启动引导服务时启动PMS。

 

 

PMS 的构造函数

 

主要作用概述:
1.创建mSettings对象,将PMS的mPackage传入,此集合保存所有apk的数据;

2.调用readLPw()读取data/system/packages.xml文件;

3.调用ScanDirTracedLI()扫描系统apk(system/app    /pri-app);

4.调用ScanDirTracedLI ()扫描第三方apk(vendor/app);

5.调用writeLPw()将扫描的结果重新写入packages.xml;

 public PackageManagerService(Context context, Installer installer,
            boolean factoryTest, boolean onlyCore) {


.....
synchronized (mInstallLock) {
        synchronized (mPackages) {
            // Expose private service for system components to use.
            LocalServices.addService(
                    PackageManagerInternal.class, new PackageManagerInternalImpl());
            sUserManager = new UserManagerService(context, this,
                    new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
            mComponentResolver = new ComponentResolver(sUserManager,
                    LocalServices.getService(PackageManagerInternal.class),
                    mPackages);
            mPermissionManager = PermissionManagerService.create(context,
                    mPackages /*externalLock*/);
            mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
            mSettings = new Settings(Environment.getDataDirectory(),
                    mPermissionManager.getPermissionSettings(), mPackages);
        }
        }
.....


Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "read user settings");
            mFirstBoot = !mSettings.readLPw(sUserManager.getUsers(false));
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

...

 mCacheDir = preparePackageParserCache();

            // Set flag to monitor and not change apk file paths when
            // scanning install directories.
            int scanFlags = SCAN_BOOTING | SCAN_INITIAL;

            if (mIsUpgrade || mFirstBoot) {
                scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
            }

            // Collect vendor/product/product_services overlay packages. (Do this before scanning
            // any apps.)
            // For security and version matching reason, only consider overlay packages if they
            // reside in the right directory.
            scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR,
                    0);
            scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRODUCT,
                    0);


....
// can downgrade to reader
            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "write settings");
            mSettings.writeLPr();
            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
                    SystemClock.uptimeMillis());


...

}

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值