Droidplugin Source Analysis Service and the processing of static broadcast

Source: Internet
Author: User

The previous article analyzed Droidplugin's handling of the activity, and had to admire the Droidplugin engineers, so is it possible for the service to be treated like the process of activity? As mentioned earlier, each agent process just pre-defined a service, if there is more than one service in a plug-in, wouldn't it be a single service run at a time? This makes it possible to determine that the processing of the service is different from the activity.

On the one hand: usually use activity is mainly used for display interface and user interaction, activity life cycle may be controlled by the user, when the user interface into the new interface or return interface. It may also be controlled by the system, when it enters the lock screen or when it comes to the phone. This means that the activity life cycle is strongly related to both the user and the system. and the service? Start or stop, it is entirely up to us to control, that is, the service and the user and the system are weak relations. So we can get him to run without having to manually invoke the service's life cycle through the system.

On the other hand: we have always said service is running in the background to provide services. It is not the service that is being served, but the binder local object instantiated in the service. The life cycle of the service includes services for binder local objects as well. In other words, we can instantiate multiple binders in a service, so we can run multiple services within a service by manually controlling the service life cycle. The premise is that we need to manage these service.

With the above understanding, the next is to take StartService as an example to analyze the processing of droidplugin service.
StartService and StartActivity are all requesting AMS services by invoking the AMS proxy object. So not much to say directly look at distributing Hooks AMS Class Iactivitymanagerhookhandle's inner class StartService's Beforeinvoke function.
Only the Replacefirstserviceintentofargs function is called in the Beforeinvoke function:

    Private StaticServiceInfoReplacefirstserviceintentofargs(object[] args)throwsremoteexception {intIntentofargindex = Findfirstintentindexinargs (args);if(Args! =NULL&& args.length >1&& Intentofargindex >=0{Intent Intent = (Intent) Args[intentofargindex]; ServiceInfo serviceinfo = Resolveservice (Intent);if(ServiceInfo! =NULL&& Ispackageplugin (Serviceinfo.packagename)) {ServiceInfo Proxyservice = Selectproxyservice (Intent );if(Proxyservice! =NULL) {Intent newintent =NewIntent (); Newintent.setaction (Proxyservice.name +NewRandom (). Nextint ());                    Newintent.setclassname (Proxyservice.packagename, proxyservice.name);                    Newintent.putextra (Env.extra_target_intent, INTENT);                    Newintent.setflags (Intent.getflags ()); Args[intentofargindex] = newintent;returnServiceInfo; }            }        }return NULL;}

Analyzing the process of activity, this function is not difficult to analyze:
The main work is as follows:
1 Find the location of the intent from the parameter, then remove the intent object and get the corresponding ServiceInfo object from the intent object.
2 Determine whether the package name of the current service is a plugin APK package name that is nearly installed.
3 Select an appropriate proxy service to replace the target service that you want to start. The process of selection before the analysis of Activity,service basically similar here do not do too much analysis, here need to specifically say that the choice of service is necessarily inherited from the abstractservicestub. After analyzing this function, Abstractservicestub hidden secret.
4 Create a intent, set the start service as the Proxy service, and save the target service to the agent service intent.
5 Replace the newly created proxy intent with the location of the original parameter intent. This allows you to cheat the system check.

At this point, the target service has been replaced by the proxy service, after AMS started, it will invoke the proxy service OnCreate, OnStart.
As mentioned earlier, all predefined proxy services are inherited from Abstractservicestub. Next, look at the hidden secrets.
The OnCreate function of abstractservicestub
This function does not do a lot of things, just set isrunning to true.
The OnStart function of Abstractservicestub is as follows:

     Public void OnStart(Intent Intent,intStartid) {Try{if(Intent! =NULL) {if(Intent.getbooleanextra ("Actionkillself",false)) {startkillself ();if(! Servcesmanager.getdefault (). hasservicerunning ()) {stopself (Startid);BooleanStopService = Getapplication (). StopService (Intent); }                }Else{Mcreator.onstart ( This, Intent,0, Startid); }            }        }Catch(Throwable e)        {handleexception (e); }Super. OnStart (Intent, Startid);}

This function mainly does the following work:
Do you remember when analyzing the process management when the number of activity in a process is zero and the service number is nonzero is sent a intent setting actionkillself to true to see if there is a plug-in service running, If not, shut down the service while the kill process is in progress.

1 determines if the actionkillself parameter is present in the intent and is true.
If true, start a thread and wait for the service to Destory before invoking the pre-defined plug-in process that runs the service.
2 Determine if there is a plug-in service running in the process, if there is a return, stop the current service if it does not. This will naturally invoke the service's ondestory function, so that the first-step thread will continue to execute and then stop the process.
3 in StartService, actionkillself is not, or false, so it executes
Mcreator.onstart (this, intent, 0, Startid); the line of code.
Mcreator is a Servcesmanager class object.
Next look at Servcesmanager's OnStart function.

     Public int OnStart(context context, Intent Intent,intFlagsintStartid) throws Exception {Intent targetintent = Intent.getparcelableextra (env.extra_target_intent);if(Targetintent! =NULL) {ServiceInfo targetinfo = Pluginmanager.getinstance (). Resolveserviceinfo (Targetintent,0);if(Targetinfo! =NULL) {Service service = Mnameservice.Get(Targetinfo.name);if(Service = =NULL) {Handlecreateserviceone (context, intent, targetinfo);            } handleonstartone (Targetintent, Flags, Startid); }        }return-1; }

This function mainly does the following work:
1 Locate the target intent to start with intent. The target service's serviceinfo is then found through the target intent.
2 Find out whether the target service to start is started with the name of the target service from Mnameservice.
3 If it is not started, call Handlecreateserviceone to create the service.
4 If the target service is already cached, the description is already started, or after the target service is created, call the OnStart function of the Handleonstartone call service

The process of creating a service by analyzing the Handlecreateserviceone function first

private void Handlecreateserviceone (Context hostcontext, Intent stubintent, serviceinfo info) throws Exception {Re Solveinfo ResolveInfo = Hostcontext. Getpackagemanager(). Resolveservice(Stubintent,0);ServiceInfo Stubinfo = resolveInfo! = null? ResolveInfo. ServiceInfo: null;PlugInManager. getinstance(). Reportmyprocessname(Stubinfo. ProcessName, info. ProcessName, info. PackageName);Pluginprocessmanager. preloadapk(Hostcontext, info);Object Activitythread = Activitythreadcompat. Currentactivitythread();IBinder Faketoken = new Myfakeibinder ();Class Createservicedata = Class. forname(Activitythreadcompat. Activitythreadclass(). GetName() +"$CreateServiceData");Constructor init = Createservicedata. Getdeclaredconstructor();if (!init. Isaccessible()) {init. Setaccessible(true);} Object data = Init. newinstance();Fieldutils. Writefield(Data,"token", Faketoken);Fieldutils. Writefield(Data,"Info", info);if (VERSION. SDK_int >= Version_codes. Honeycomb) {Fieldutils. Writefield(Data,"Compatinfo", Compatibilityinfocompat. DEFAULT_compatibility_info ());} method = Activitythread. GetClass(). Getdeclaredmethod("Handlecreateservice", Createservicedata);if (!method. Isaccessible()) {method. Setaccessible(true);} method. Invoke(Activitythread, data);Object Mservice = fieldutils. Readfield(Activitythread,"Mservices");Service service = (service) methodutils. InvokeMethod(Mservice,"Get", Faketoken);Methodutils. InvokeMethod(Mservice,"Remove", Faketoken);Mtokenservices. Put(Faketoken, service);Mnameservice. Put(Info. Name, service);if (stubinfo! = null) {PlugInManager. getinstance(). onservicecreated(Stubinfo, info);}}

The basic work of this function is as follows:
1 Locate the Proxy service ServiceInfo first, and then call Pluginmanager.getinstance (). Reportmyprocessname (Stubinfo.processname, Info.processName , info.packagename); Associated package name and target process and agent process information for easy management. Analyzed in the process management article.

2 pluginprocessmanager.preloadapk (Hostcontext, info) set loadedapk, as well as ClassLoader, which has been analyzed in the plugin's handling of activity.

3 by looking at the source code can understand the following information, when starting a service, back to the application space to run the service (in fact, the process of running the service), the process of creating the service is created by Activitythread's Handlecreateservice function, At the same time call this function when you need to pass in the Createservicedata data class, in this data class has a IBinder object, this object is actually in Activitymanagerservice is a servicerecord, Mainly used to record a service information. When you call Activitythread's function Handlecreateservice create the service,

A: The OnCreate function of the service is called.
B: The service will servicerecord this IBinder object as the key service object as value in the Mservice member variable of Activitythread.
With these insights, the following code mainly accomplishes the following:

4 The target service is actually not started in Activitymanager, so there is no Servicerecord object, so a IBinder object Myfakeibinder will be forged first.

5 Create a Createservicedata class object. And the forged IBinder object and the target serviceinfo are saved to the data object.

6 Call the Activitythread function Handlecreateservice create the target service object.

7 from the Activitythread member variable Mservice, take the previously forged IBinder object as key to remove the service just created from the inside.

8 A forged IBinder object and a target service class name key are saved to the ServiceManager member variables mtokenservices and Mnameservice respectively.

9 Call Pluginmanager.getinstance (). onservicecreated (Stubinfo, info), manage the service that is just started, and the process that runs the service. The previous process management article already has the activity analysis, the service basically similar.

Handleonstartone the process of invoking the service's OnStart function.

    Private void Handleonstartone(Intent Intent,intFlagsintStartids) throws Exception {serviceinfo info = pluginmanager.getinstance (). Resolveserviceinfo (Intent,0);if(Info! =NULL) {Service service = Mnameservice.Get(Info.name);if(Service! =NULL) {ClassLoader ClassLoader = getClassLoader (Info.applicationinfo);                Intent.setextrasclassloader (ClassLoader);                Object token = findtokenbyservice (service); Integer integer = mservicetaskids.Get(token);if(Integer = =NULL) {integer =-1; }intStartid = integer +1; Mservicetaskids.put (token, startid);intres = Service.onstartcommand (Intent, flags, Startid);            Queuedworkcompat.waittofinish (); }        }}

The main work of this function is as follows:
1 Locate the ServiceInfo through intent, and then locate the service from Mnameservice through the name ServiceInfo.
Gets the ClassLoader of the ClassLoader settings intent.
2 Use the service to find tokens, and then use token to see if the Startid is set in Mservicetaskids.
3 if empty, set Startid to value as the token key to the Servicemanger member variable mservicetaskids.
4 finally call the Service,onstartcommend function.
5 Call Queuedwork.waittofinish wait for completion.
This completes the processing analysis of the service by the plugin.

Droidplugin handling of static broadcasts:
As already stated in Droidplugin's documentation, their handling of static broadcasts is accomplished through dynamic registration. This means that droidplugin only resolves the static broadcast in the plugin apk androidmanifest file for dynamic registration.
The specific registration process is when calling the application OnCreate function.
When loadedapk calls the Makeapplication function, Instrumentation.callapplicationoncreate is called, and instrumentation has been tampered with plugininstrumentation. It's in the Callapplicationoncreate function of plugininstrumentation. The pluginprocessmanager.registerstaticreceiver is called. The specific function is relatively simple, you can see for yourself.

Droidplugin Source Analysis service and static broadcast processing

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.