PackageManagerService对象构造过程

来源:互联网 发布:.手机域名在哪里注册 编辑:程序博客网 时间:2024/05/29 18:00

PackageMangerService的构造方法是个比较复杂的过程:(具体构造方法的代码见源码,由于太多了,代码中加了注释,是Android4.0的)。流程见手稿。

先从构造方法一步一步,遇到关键的类,关键的点在说明。

    public PackageManagerService(Context context, boolean factoryTest,
            boolean onlyCore) {
        // PackageManagerService启动开始
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START,
                SystemClock.uptimeMillis());
        // SDK版本检查,final int mSdkVersion = Build.VERSION.SDK_INT
        if (mSdkVersion <= 0) {
            Slog.w(TAG, "**** ro.build.version.sdk not set!");
        }
        // ###//从SystemServer中获取的三个值,从main方法中获取,
        mContext = context;
        mFactoryTest = factoryTest;// 开机模式
        mOnlyCore = onlyCore;

        // 如果编译版本为eng,则不需要dex优化
        mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
        // 获取手机分辨率,加载资源需要
        mMetrics = new DisplayMetrics();
        //###111===========创建Settings对象=====================@@@
        // 存储系统运行过程中的设置信息
        // 创建Settings,有关动态设置的信息持有,Settings构造方法在目录/data/system/下创建package.xml、package.list、package_backup.xml
        mSettings = new Settings();
        /*
         * 创建SharedUserSetting对象并添加到Settings的成员变量mSharedUsers中,在Android系统中,
         * 多个package通过设置sharedUserId属性可以运行在同一个进程,共享同一个UID
         */
        // 添加四个lib
        mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
                ApplicationInfo.FLAG_SYSTEM);
        mSettings.addSharedUserLPw("android.uid.phone",
                MULTIPLE_APPLICATION_UIDS ? RADIO_UID : FIRST_APPLICATION_UID,
                ApplicationInfo.FLAG_SYSTEM);
        mSettings.addSharedUserLPw("android.uid.log",
                MULTIPLE_APPLICATION_UIDS ? LOG_UID : FIRST_APPLICATION_UID,
                ApplicationInfo.FLAG_SYSTEM);
        mSettings.addSharedUserLPw("android.uid.nfc",
                MULTIPLE_APPLICATION_UIDS ? NFC_UID : FIRST_APPLICATION_UID,
                ApplicationInfo.FLAG_SYSTEM);
        //================================@@@

函数首先创建一个Settings对象,用来保存一些设置信息,然后调用addSharedUserLPw向Settings类的成员变量mSharedUsers中添加SharedUserSetting对象,在Android系统中,通过设置android:sharedUserId="android.uid.system"属性可以为应用程序指定UID,SharedUserSetting对象保存同一共享进程UID的所有包信息,Settings对象用于管理Android系统运行过程中的一些设置信息,Settings的成员变量mSharedUsers以键值对的方式保存UID对应的SharedUserSetting对象。在Android系统中,可以通过在AndroidManifest.xml文件中设置sharedUserId属性来设置多个APK运行在同一个进程中。

 在Settings的构造方法中,

Settings对象的构造过程很简单,就是创建一些目录和文件。首先创建/data/system/目录,然后分别创建以下五个文件:

/data/system/packages.xml

/data/system/packages-backup.xml

/data/system/packages.list

/data/system/packages-stopped.xml

/data/system/packages-stopped-backup.xml

Settings通过addSharedUserLPw函数添加向mSharedUsers预先添加SharedUserSetting对象


通过Settings对象调用addSharedUserLPw方法:

    SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags) {
        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);
        s.userId = uid;
        if (addUserIdLPw(uid, s, name)) {
            mSharedUsers.put(name, s);
            return s;
        }
        return null;
    }


    private boolean addUserIdLPw(int uid, Object obj, Object name) {
        // 如果uid大于或者等于系统最大的uid,那么返回false(10000+1000=11000)
        if (uid >= PackageManagerService.FIRST_APPLICATION_UID
                + PackageManagerService.MAX_APPLICATION_UIDS) {
            return false;
        }
        // uid>=1000
        if (uid >= PackageManagerService.FIRST_APPLICATION_UID) {
            int N = mUserIds.size();
            
            final int index = uid - PackageManagerService.FIRST_APPLICATION_UID;
            while (index >= N) {
                mUserIds.add(null);
                N++;
            }
            if (mUserIds.get(index) != null) {
                PackageManagerService.reportSettingsProblem(Log.ERROR,
                        "Adding duplicate user id: " + uid + " name=" + name);
                return false;
            }
            mUserIds.set(index, obj);
        } else {
            if (mOtherUserIds.get(uid) != null) {
                PackageManagerService.reportSettingsProblem(Log.ERROR,
                        "Adding duplicate shared id: " + uid + " name=" + name);
                return false;
            }
            mOtherUserIds.put(uid, obj);
        }
        return true;
    }

而mSharedUsers的类型如:

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

上面的过程主要是:创建Settings对象;将四个默认的共享用户ID添加到HashMap<String, SharedUserSetting> mSharedUsers,还有:private final ArrayList<Object> mUserIds = new ArrayList<Object>()

===========================================================================================

    //222================================@@@
        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;
        }
        //================================@@@
        //333================================@@@
        // 创建Installer,通过Installer与底层进行通信,进行安装,卸载等操作
        mInstaller = new Installer();

        // 获取屏幕尺寸大小
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        Display d = wm.getDefaultDisplay();
        d.getMetrics(mMetrics);


上面主要是,获取系统的配置信息,获取手机分辨率,便于加载资源文件,还有就是创建一个Installer对象,创建Installer对象,用于访问installd服务进程,完成一些apk安装,卸载,优化工作,对于Installer中的方法,都很容易理解,通过,方法:

    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;
    }

来联接底层的操作,没有探讨。。。。。。。