Android PMS概述


本文属个人原创,如需转载请联系作者!!!
Package Manager Service(简称PMS,下文中均使用PMS表示)顾名思义是Android Package管理服务,其主要管理Android系统中App的安装包等信息。为详细了解PMS的实现机制和其提供的服务,本文从以下几个方面对PMS进行学习: 1.对于Android系统的实现者而言,PMS是什么? 2.PMS初始化过程? 3.对于Android Framework其他的Service而言,PMS提供什么服务? 4.对于Android App开发者而言,如何使用PMS提供的服务?

1. PMS是什么?

本节主要从系统实现角度来剖析PMS,主要内容包括以下几个方面: 1.PMS的实现类图 2.Android AIDL介绍 3.Android ServiceManager与PMS关系

1.1 PMS实现类图

PMS类结构图如下图所示: PMS类结构图 PMS相关的类有IPackageManager.java,PackageManagerService.java,Binder.java,IInterface.java等,PMS类结构有以下特点:

  • IPackageManager接口继承自IInterface.java接口。在IInterface.java接口定义了方法asBinder(),其作用是将IPackageManager转换成IBinder对象.
  • 在IPackageManager接口中有一个内部类Stub类;Stub类实现IBinder和IPackageManager接口。 1.Stub类定义了asInterface(IBinder)方法; 该方法将IBinder对象转换成IPackageManager类型对象,如果需要则返回的是Stub.Proxy类对象。 2.Stub类重写Binder类的onTransact()方法;该方法根据命令类型,处理数据传输。 3.Stub中实现了asBinder()方法,该方法直接返回Stub类对象。 4.Stub未实现IPackageManager中定义的方法。
  • Stub包含一个内部类Proxy,其中Proxy类实现IPackageManager接口。 1.Stub.Proxy类持有一个mRemote对象,该对象是对Stub类的引用。 2.Stub.Proxy类实现了IPackageManager的方法,这些方法通过mRemote调用Binder中的transact()方法,最终调用Stub类的onTransact方法处理。 3.Stub.Proxy类也实现了IInterface.java中定义的asBinder方法,该方法返回的mRemote。

1.2 AIDL介绍

AIDL是Android Interface Definition Language的简称,主要用于生成可以在Android设备上可以跨进程通信的服务接口,该项服务包含Client端和Service端。这些远程的Service可发布成为一个library。具体介绍可参考Android AIDL。 本文介绍AIDL主要是因为AOSP(Android Open Source Project)在生成IPackageManager的过程中使用了该技术。其中在AOSP工程中,只是定义IPackageManager.aidl文件,并没有编写IPackageManager.java文件。AOSP在编译的过程中,自动解析IPackageManager.aidl文件,并最终生成IPackageManager.java文件。 其实在AOSP中,Android Framework层的绝大部分的Service都采用了AIDL技术来生成IXXXService.java,比如PowerManagerService.java、InputManagerService.java、WindowManagerService.java等。只有极少数的Service需要特殊处理的才编写了Java文件,比如IServiceManager.java和IActivityManager.java等。 AIDL的使用有以下限制:

  • 仅当你的Client端需要从不同的Application中通过IPC (interprocess communication)访问Service,且需要Service能够处理多线程的时候,才考虑使用AIDL;
  • 如果你不需要在不同的Application之间实现并发的IPC的话,可以通过继承Binder类来实现IPC通信功能;
  • 如果你需要实现进程间通信,但是不需要处理多线程(multiprocessing)问题,可以考虑使用Messager技术.

AIDL使用案例可参考以下实例: 1.百度浏览器frame模块中的AIDL的使用; 2.android跨进程通信(IPC):使用AIDL; 3.Services with AIDL in Android; 注:AIDL实现机制待调研。

1.3 ServiceManager与PMS关系

1.3.1 ServiceManager是什么?

ServiceManager顾名思义是Service的管理者,该类具有一个HashMap<String, IBinder>持有已经注册的Service,并提供相应的方法以便FrameWork层调用。如果发现某个Service未注册,则会通过ServiceManagerNative.java这个Service获取。其中ServiceManager的UML类图如下图所示: ServiceManager类结构图

ServiceManager提供的public方法都是静态方法,这些方法实现大同小异。这里以getService(String)方法实现为例进行说明,其代码如下:


public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return getIServiceManager().getService(name);
        }
    } catch (RemoteException e) {
        Log.e(TAG, "error in getService", e);
    }
    return null;
}
其中mRemote是一个ServiceNativeManager对象。 从上述实现我们发现,getService方法在执行的过程中,可能会调用ServiceManager类中getIServiceManager()用于创建ServiceManagerNative对象,其方法代码如下:


private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }
    // Find the service manager
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}
其中ServiceManagerNative.asInterface(XXX)方法,该方法实际返回IServiceManager对象,其实际上是一个ServiceManagerNative.Proxy对象。 ServiceManagerNative.java中addService(),getService()都是native方法,最终会调用service_manager.c类的相应方法。

1.3.2 PackageManagerService注册

在Android启动的过程中,会启动SystemServer进程。在SystemServer启动的过程中,会调用PackageManagerService main()函数来初始化一个PackageManagerService对象。其中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;
}
该方法会通过PackageManagerService的构造函数创建一个对象,并将该对象返回。

2. PMS初始化过程

2.1 PMS初始化流程图

PMS的初始化过程,如以下流程图(本流程图是基于SDK 19绘制): PMS初始化过程

1.第一步先创建Settings对象mSettings,并添加相关的SharedUser信息。该步骤添加的是Linux共享用户组,添加的共享用户组有: | UID名称 | 变量名 | 变量取值 | | :------------- |:--------- |:---------: | | android.uid.system | SYSTEM_UID | 1000 | | android.uid.phone | PHONE_UID | 1001 | | android.uid.log | LOG_UID | 1007 | | android.uid.nfc | NFC_UID | 1027 | | android.uid.bluetooth | BLUETOOTH_UID| 1002 | | android.uid.shell | SHELL_UID | 2000 | 2.第二步解析系统的配置信息,如Display的信息;该过程通过WMS(WindowManagerService)实现的。 3.创建一个HanlderThread.java对象mHandlerThread.java,并用此对象获取Looper对象以初始化一个PackageHandler.java对象mHandler。该对象处理Package的安装、卸载、清除缓存等命令。 4.创建UserManagerService.java对象mUserManagerService,在其构造函数中会解析/data/system/users/目录下的userlist.xml和.xml文件等。 5.调用readPermissions()函数解析/system/etc/permissions/目录下的文件platform.xml文件,以及设备相关的文件。 6.调用Settings.readLpw()读取platform.xml等文件,这些文件包含系统已经安装的App信息、SharedUser等信息。 7.进行dexOpt操作; 8.调用scanDirLI()读取以下几个文件夹中所有APK文件信息,其中前三者为系统级的App:

  • /system/framework/
  • /system/app/
  • /vendor/app/
  • /data/app/
  • /data/app-private/

9.调用Settings.writeLPr()保存信息。

2.2 PMS初始化过程代码解析

PMS初始化过程中的,第1步、第4步处理与用户相关的信息;第5步、第6步、第8步与权限管理相关。本文主要讲解第5步、第6步和第8步过程;第3步和第7步后续讲解:

2.2.1 第6步解析

第6步中的readLPw()实现如下:

boolean readLPw(PackageManagerService service, List users, int sdkVersion,boolean     onlyCore) {
    FileInputStream str = null;
    // 判断是否存在packages-backup.xml文件,如果存在删除packages.xml
    if (mBackupSettingsFilename.exists()) {
        try {
            str = new FileInputStream(mBackupSettingsFilename);
            .......
               if (mSettingsFilename.exists()) {
                mSettingsFilename.delete();
            }
        } catch (java.io.IOException e) {
        }
    }
    ......
    try {
        if (str == null) { // 如果不存在packages-backup.xml文件
            if (!mSettingsFilename.exists()) { //如果packages.xml 不存在
                ......
                mInternalSdkPlatform = mExternalSdkPlatform = sdkVersion;
                return false;
            }
            str = new FileInputStream(mSettingsFilename);
        }
        XmlPullParser parser = Xml.newPullParser();
        parser.setInput(str, null);
        // 解析packages.xml文件
        String tagName = parser.getName();
        if (tagName.equals("package")) {
            readPackageLPw(parser);
        } else if (tagName.equals("permissions")) {
            readPermissionsLPw(mPermissions, parser);
        } else if (tagName.equals("permission-trees")) {
            readPermissionsLPw(mPermissionTrees, parser);
        } else if (tagName.equals("shared-user")) {
            readSharedUserLPw(parser);
        } else if (tagName.equals("preferred-packages")) {
            // no longer used.
        } else if (tagName.equals("preferred-activities")) {
            readPreferredActivitiesLPw(parser, 0);
        } else if (tagName.equals("updated-package")) {
            readDisabledSysPackageLPw(parser);
        } else if (tagName.equals("cleaning-package")) {
          ....
        } else if (tagName.equals("renamed-package")) {
            String nname = parser.getAttributeValue(null, "new");
            String oname = parser.getAttributeValue(null, "old");
            if (nname != null && oname != null) {
                mRenamedPackages.put(nname, oname);
            }
        } else if (tagName.equals("last-platform-version")) {
          ....
        } else if (tagName.equals("verifier")) {
          ....
        } else if (TAG_READ_EXTERNAL_STORAGE.equals(tagName)) {
           final String enforcement = parser.getAttributeValue(null,  
           ATTR_ENFORCEMENT);
           mReadExternalStorageEnforced = "1".equals(enforcement);
        } else if (tagName.equals("keyset-settings")) {
          mKeySetManager.readKeySetsLPw(parser);
        } else {
          ....
          XmlUtils.skipCurrentTag(parser);
        }
    }
    // 关闭文件流
    str.close();
    } catch (XmlPullParserException e) {
    .....
    }
    ....
    // 如果存在, packages-stopped-backup.xml文件
    if (mBackupStoppedPackagesFilename.exists()
            || mStoppedPackagesFilename.exists()) {
        // Read old file
        readStoppedLPw();
        mBackupStoppedPackagesFilename.delete();
        mStoppedPackagesFilename.delete();
        // Migrate to new file format
        writePackageRestrictionsLPr(0);
    } else {
        if (users == null) {
            readPackageRestrictionsLPr(0);
        } else {
            for (UserInfo user : users) {
                readPackageRestrictionsLPr(user.id);
            }
        }
    }
}

2.2.2 第8步解析

PMS中的第8个步骤调用scanDirLI(...)解析所有APK信息。其代码如下:

private void scanDirLI(File dir, int flags, int scanMode, long currentTime) {
    String[] files = dir.list();
    if (files == null) {
        Log.d(TAG, "No files in app dir " + dir);
        return;
    }
    ...
    for (int i=0; i<files.length; i++) {
        File file = new File(dir, files[i]);
        if (!isPackageFilename(files[i])) {
           // Ignore entries which are not apk's
           continue;
        }
        //调用scanPackageLI解析具体的APK信息
        PackageParser.Package pkg = scanPackageLI(file, flags 
        | PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
        // Don't mess around with apps in system partition.
        if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
        mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
            // Delete the apk
            Slog.w(TAG, "Cleaning up failed install of " + file);
            file.delete();
        }
    }
}
解析后的信息存如下表所示: | 变量名 | 变量类型 | 说明 | | :------------- |:--------- |:--------- | | mAppDirs |HashMap |Key为APK的绝对路径,Value为PackageParser.Package对象 | | mPackages |HashMap |Key为Package的名称,Value为PackageParser.Package对象 | | mSystemPermissions |SparseArray> |存放Android系统定义的Permission | | mSharedLibraries |HashMap |Key为共享lib的名称,Value为SharedLibraryEntry对象,这些共享Lib从/etc/permissions.xml解析得到 | | mAvailableFeatures |HashMap |Key为Feature的名称,Value为FeatureInfo对象 | | mProvidersByAuthority |HashMap |Key为Provider的URI,Value为PackageParser.Provider对象 | | mInstrumentation |HashMap |Key为ComponentName对象,Value为PackageParser.Instrumentation对象 | | mPermissionGroups |HashMap |Key为Permission的名称,Value为PackageParser.PermissionGroup对象 | | mRunningInstalls |SparseArray |正在安装的包 |

3.PMS提供的服务

通过PMS启动过程的分析分析,我们可以发现PMS将设备的Settings信息、Users信息、Permission信息、每个APK信息等加载到内存中,这些信息是系统中的初始信息(第一手资料)。Android framework中的其他Service的信息都是从PMS的信息加工获取的。 PMS对外部提供的信息的接口来源有:

  1. IPackageManager.java中定义的接口;
  2. IInterface.java定义的接口asBinder();
  3. Binder.java中定义的public接口;
  4. IPackageManager.Stub类中定义的asInterface()等public接口;
  5. PackageManagerService.java中自定义的Public接口。 | 接口名称 | 返回类型 | 来源 | | :------------- |:--------- |:--------- | | asBinder |IBinder |IInterface.java | | transact |boolean |Binder.java | | isProxy |boolean |Binder.java | | getCallingPid |int |Binder.java | | getCallingUid |int |Binder.java | | getInterfaceDescriptor |String |Binder.java | | isBinderAlive |boolean |Binder.java | | queryLocalInterface |IInterface |Binder.java | | onTransact |boolean |IPackageManager.Stub | | asInterface |IPackageManager|IPackageManager.Stub |

IPackageManager.java中定义的接口较多,请直接参考IPackageManager.java类。 其他FrameWork Service在获取IPackageManager对象时,获取的是PackageManagerService.java类型对象,而不是其代理对象。

4.Android App获取PMS服务

  1. 通过Context的getPackageManager()方法获取,其实现在ContextImpl.java中,该方法代码如下:
    
    public PackageManager getPackageManager() {
     if (mPackageManager != null){ return mPackageManager;
     }
     IPackageManager pm = ActivityThread.getPackageManager();
     if (pm != null) { return (mPackageManager = new ApplicationPackageManager(this, pm));
     }
     return null;
    }
    </code></pre>
    该方法通过ActivityThread.getPackageManager()方法获取IPackageManager对象,获取的对象其实是IPackageManager.Stub.Proxy对象。
  2. 获取其他的服务,通过Content.getSystemService(String).在ContextImpl.java中,有一段静态代码来获取常用的FrameWork Service:
    static {
     ......
     // ActivityService注册
     registerService(ACTIVITY_SERVICE, new ServiceFetcher() {     public Object createService(ContextImpl ctx) {
             return new ActivityManager(ctx.getOuterContext(), ctx.mMainThread.getHandler());
         }
     });
     ......
     // PowerService注册
     registerService(POWER_SERVICE, new ServiceFetcher() {     public Object createService(ContextImpl ctx) {
             IBinder b = ServiceManager.getService(POWER_SERVICE);
             IPowerManager service = IPowerManager.Stub.asInterface(b);
             return new PowerManager(ctx.getOuterContext(),
                     service, ctx.mMainThread.getHandler());
         }
     });
     ......
     // WifiService注册
     registerService(WIFI_SERVICE, new ServiceFetcher() {     public Object createService(ContextImpl ctx) {
             IBinder b = ServiceManager.getService(WIFI_SERVICE);
             IWifiManager service = IWifiManager.Stub.asInterface(b);
             return new WifiManager(ctx.getOuterContext(), service);
         }
     });
     ......
     // WindowService注册
     registerService(WINDOW_SERVICE, new ServiceFetcher() {     Display mDefaultDisplay;
         public Object getService(ContextImpl ctx) {
             Display display = ctx.mDisplay;
             if (display == null) {
                 if (mDefaultDisplay == null) {
                     DisplayManager dm = (DisplayManager)ctx.getOuterContext().
                             getSystemService(Context.DISPLAY_SERVICE);
                     mDefaultDisplay = dm.getDisplay(Display.DEFAULT_DISPLAY);
                 }
                 display = mDefaultDisplay;
             }
             return new WindowManagerImpl(display);
         }
     });
     ......
     // UserService注册
     registerService(USER_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) {
         IBinder b = ServiceManager.getService(USER_SERVICE);
         IUserManager service = IUserManager.Stub.asInterface(b);
         return new UserManager(ctx, service);
     }
     });
     ......
    }
    </code></pre>
    从上述代码也可以看出,其他的Service也都是获取Stub.Proxy对象.

results matching ""

    No results matching ""