How the package is parsed in Android--parsing ContentProvider

Source: Internet
Author: User
Tags tagname

If you know about the Android startup process, we know that Android will parse the APK that already exists under/data/system and/data/app when it is launched.

So where do you start to parse these packages?

1.

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;    }
When Android starts, it executes the main method in Packagemanagerservice according to the init.rc configuration file.

The operation of this method is simple, which is to generate an Packagemanagerservice object and then load it into the ServiceManager process for management.

From here we can see that the ServiceManager process is used to manage some system service in the framework layer of Android.


2.

The code in the main method is very small, so where does Packagemanagerservice parse the package?

In fact, the existing apk is parsed when new Packagemanagerservice the object.

Below we do an analysis of the APK parsing process under/data/app/.

Synchronized (mpackages) {            mhandlerthread.start ();            Mhandler = new Packagehandler (Mhandlerthread.getlooper ());            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");            Susermanager = new Usermanagerservice (context, this,                    Minstalllock, mpackages);
Here are some of the Android path to get, here we see the android Default User installation path Mappinstalldir is/data/app/.

Knowing the path of the user's apk, you can go through all the apk under that path and parse it.

            if (!monlycore) {                eventlog.writeevent (Eventlogtags.boot_progress_pms_data_scan_start,                        Systemclock.uptimemillis ());                Mappinstallobserver = new Appdirobserver (                    Mappinstalldir.getpath (), observer_events, false);                Mappinstallobserver.startwatching ();                Scandirli (mappinstalldir, 0, Scanmode, 0);                    Mdrmappinstallobserver = new Appdirobserver (                    Mdrmappprivateinstalldir.getpath (), observer_events, false);                Mdrmappinstallobserver.startwatching ();                Scandirli (Mdrmappprivateinstalldir, Packageparser.parse_forward_lock,                        scanmode, 0);

Use the Scandirli method above to traverse the/data/app/apk below.
    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        } if (debug_package_scanning) {log.d (TAG, "scanning app dir" + dir);        } int i;            for (i=0; i<files.length; i++) {File File = new file (dir, files[i]);            if (!ispackagefilename (Files[i])) {//Ignore entries which is not apk ' s continue; } packageparser.package pkg = Scanpackageli (file, flags|            packageparser.parse_must_be_apk, Scanmode, currenttime, NULL);            Don ' t mess around with the 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 (); }        }    }
Through Dir.list () we get/data/app/all the file names, and then in the later for loop to determine whether it is a *.apk file, if so, call Scanpackageli to parse;

If not, continue looping to find the next apk file.


Enter Scanpackageli below

    Private Packageparser.package Scanpackageli (File scanfile,            int parseflags, int scanmode, long currenttime, Userhandle user) {        mlastscanerror = packagemanager.install_succeeded;        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);        if (pkg = = null) {            mlastscanerror = Pp.getparseerror ();            return null;        }        packagesetting PS = null;        Packagesetting updatedpkg;

Scanpackageli returns the value of the Packageparser.package type, which stores the parsed information of the corresponding apk.

Final Packageparser.package pkg = pp.parsepackage (scanfile,                Scanpath, Mmetrics, parseflags);
Here is to parse the apk file, from Scanpackageli code to see that PP is actually a Packageparser object.


3. Packageparser.java

The above pp.parsepackage will be called as follows:

        try {            //XXXX todo:need to correct configuration.            pkg = parsepackage (res, parser, flags, errorText);        } catch (Exception e) {            errorexception = e;            Mparseerror = packagemanager.install_parse_failed_unexpected_exception;        }

The overloaded Parsepackage method is called here.

Go back in here and parse the Androidmanifest.xml file, and when you get to the application tag, go back and parse the controls that exist below.

            if (Tagname.equals ("Application")) {                if (Foundapp) {                    if (rigid_parser) {                        outerror[0] = "<manifest> Have more than one <application> ";                        Mparseerror = packagemanager.install_parse_failed_manifest_malformed;                        return null;                    } else {                        SLOG.W (TAG, "<manifest> have more than one <application>");                        Xmlutils.skipcurrenttag (parser);                        Continue;                    }                }                Foundapp = true;                if (!parseapplication (pkg, res, parser, attrs, Flags, Outerror)) {                    return null;                }
Parseapplication is to parse the resources in the tags <application>.

Let's take a look at how parseapplication resolves provider.

       while (type = Parser.next ())! = Xmlpullparser.end_document && (type! = Xmlpullparser.end_ta G | |                Parser.getdepth () > Innerdepth)) {if (type = = Xmlpullparser.end_tag | | type = = xmlpullparser.text) {            Continue            } String TagName = Parser.getname (); if (Tagname.equals ("activity")) {Activity A = parseactivity (owner, RES, parser, attrs, flags, Outerror, FA                LSE, hardwareaccelerated);                    if (a = = null) {mparseerror = packagemanager.install_parse_failed_manifest_malformed;                return false;            } owner.activities.add (a); } else if (Tagname.equals ("receiver")) {Activity a = parseactivity (owner, RES, parser, attrs, flags, outEr                Ror, True, false);       if (a = = null) {mparseerror = packagemanager.install_parse_failed_manifest_malformed;             return false;            } owner.receivers.add (a); } else if (Tagname.equals ("service")) {service s = parseservice (owner, RES, parser, attrs, flags, Outerror                );                    if (s = = null) {mparseerror = packagemanager.install_parse_failed_manifest_malformed;                return false;            } owner.services.add (s); } else if (Tagname.equals ("provider")) {provider P = Parseprovider (owner, RES, parser, attrs, flags, outEr                ROR);                    if (p = = null) {mparseerror = packagemanager.install_parse_failed_manifest_malformed;                return false;            } owner.providers.add (P); }

We can see that the above will parse different things according to the different tag files obtained.

When our tag is provider, we call Parseprovider to parse it. Once the parsing is complete, the resulting provider will be added to the Owner.provider.


    Private Provider Parseprovider (package owner, Resources Res, Xmlpullparser parser, attributeset attrs, int Flags, string[] outerror) throws Xmlpullparserexception, IOException {TypedArray sa = Res.obtainattribu        TES (Attrs, Com.android.internal.r.styleable.androidmanifestprovider);                    if (Mparseproviderargs = = null) {Mparseproviderargs = new Parsecomponentargs (owner, Outerror, Com.android.internal.r.styleable.androidmanifestprovider_name, Com.android.internal.r.styleable.andr                    Oidmanifestprovider_label, Com.android.internal.r.styleable.androidmanifestprovider_icon,                    Com.android.internal.r.styleable.androidmanifestprovider_logo, Mseparateprocesses, Com.android.internal.r.styleable.androidmanifestprovider_process, com.android.internal.r.styleable .                 Androidmanifestprovider_description,   com.android.internal.r.styleable.androidmanifestprovider_enabled);        Mparseproviderargs.tag = "<provider>";        } mparseproviderargs.sa = sa;                Mparseproviderargs.flags = flags;        Provider p = new Provider (Mparseproviderargs, New Providerinfo ());            if (outerror[0]! = null) {sa.recycle ();        return null;        } Boolean providerexporteddefault = false; if (Owner.applicationInfo.targetSdkVersion < build.version_codes. JELLY_BEAN_MR1) {//For compatibility, applications targeting API level or lower//should has            Their content providers exported by default, unless they//specify otherwise.        Providerexporteddefault = true; } p.info.exported = Sa.getboolean (com.android.internal.r.styleable.androidmanifestprovider_exported        , Providerexporteddefault);     String CPName = sa.getnonconfigurationstring (           Com.android.internal.r.styleable.androidmanifestprovider_authorities, 0);                p.info.issyncable = Sa.getboolean (com.android.internal.r.styleable.androidmanifestprovider_syncable,        FALSE); String Permission = sa.getnonconfigurationstring (com.android.internal.r.styleable.androidmanifestprovider_        permission, 0); String str = sa.getnonconfigurationstring (com.android.internal.r.styleable.androidmanifestprovider_readper        Mission, 0);        if (str = = null) {str = permission;        } if (str = = null) {p.info.readpermission = owner.applicationInfo.permission;        } else {p.info.readpermission = str.length () > 0? str.tostring (). Intern (): null; } str = sa.getnonconfigurationstring (com.android.internal.r.styleable.androidmanifestprovider_write        Permission, 0);   if (str = = null) {str = permission;     } if (str = = null) {p.info.writepermission = owner.applicationInfo.permission;        } else {p.info.writepermission = str.length () > 0? str.tostring (). Intern (): null; } p.info.granturipermissions = Sa.getboolean (com.android.internal.r.styleable.androidmanifestprovid        Er_granturipermissions, false);                 p.info.multiprocess = Sa.getboolean (com.android.internal.r.styleable.androidmanifestprovider_multiprocess,        FALSE);                P.info.initorder = Sa.getint (Com.android.internal.r.styleable.androidmanifestprovider_initorder,        0);        p.info.flags = 0; if (Sa.getboolean (Com.android.internal.r.styleable.androidmanifestprovider_singleuser, Fals            e) {p.info.flags |= providerinfo.flag_single_user; if (p.info.exported) {SLOG.W (TAG, "Provider exported request IGNored due to SingleUser: "+ P.classname +" at "+ Marchivesourcepath +" "                + parser.getpositiondescription ());            p.info.exported = false;        }} sa.recycle (); if ((owner.applicationinfo.flags&applicationinfo.flag_cant_save_state)! = 0) {//A heavy-weight Applicatio            n can not has providers in it main process//We can do direct compare because we intern all strings. if (P.info.processname = = Owner.packagename) {outerror[0] = "Heavy-weight applications can not has P                Roviders in main process ";            return null; }} if (cpname = = null) {outerror[0] = "<provider> does not include authorities at            Tribute ";        return null;        } p.info.authority = Cpname.intern ();        if (!parseprovidertags (res, parser, Attrs, p, Outerror)) {return null; } return P }

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

How the package is parsed in Android--parsing ContentProvider

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.