Android4.4 Component Analysis-service component-bindService source code analysis, android4 major components

Source: Internet
Author: User

Android4.4 Component Analysis-service component-bindService source code analysis, android4 major components
6.1.1. bindService

Because the code implementation process of startService is analyzed earlier, the Code Analysis of bindService is not described in detail. When introducing the process, you should pay more attention to some details.

 

First, bindService also uses ContextWrapper. bindService to bindService of ContextImpl, and then bindServiceCommon. Note that the incoming ServiceConnection is converted to IServiceConnection,

Private boolean bindServiceCommon (Intent service, ServiceConnection conn, int flags,

UserHandle user ){

IServiceConnection sd;

...

Sd = mPackageInfo. getServiceDispatcher (conn, getOuterContext (),

MMainThread. getHandler (), flags );

...

Int res = ActivityManagerNative. getDefault (). bindService (

MMainThread. getApplicationThread (), getActivityToken (),

Service, service. resolveTypeIfNeeded (getContentResolver ()),

Sd, flags, user. getIdentifier ());

}

 

Next, access the bindService of AMS and call the bindServiceLocked of ActiveServices. java. It stores the IServiceConnection instance in ConnectionRecord and executes bringUpServiceLocked,

Int bindServiceLocked (IApplicationThread caller, IBinder token,

Intent service, String resolvedType,

IServiceConnection connection, int flags, int userId ){

...

ConnectionRecord c = new ConnectionRecord (B, activity,

Connection, flags, clientLabel, clientIntent );

 

IBinder binder = connection. asBinder ();

 

If (flags & Context. BIND_AUTO_CREATE )! = 0 ){

S. lastActivity = SystemClock. uptimeMillis ();

If (bringUpServiceLocked (s, service. getFlags (), callerFg, false )! = Null ){

Return 0;

}

}

...

If (s. app! = Null & B. intent. received ){

// Service is already running, so we can immediately

// Publish the connection.

Try {

C. conn. connected (s. name, B. intent. binder );

} Catch (Exception e ){

Slog. w (TAG, "Failure sending service" + s. shortName

+ "To connection" + c. conn. asBinder ()

+ "(In" + c. binding. client. processName + ")", e );

}

 

// If this is the first app connected back to this binding,

// And the service had previusly asked to be told when

// Rebound, then do so.

If (B. intent. apps. size () = 1 & B. intent. doRebind ){

RequestServiceBindingLocked (s, B. intent, callerFg, true );

}

} Else if (! B. intent. requested ){

RequestServiceBindingLocked (s, B. intent, callerFg, false );

}

}

 

 

According to the previous analysis, ServiceLocked will call realStartServiceLocked, while realStartServiceLocked will call scheduleCreateService to complete service creation and Oncreate () execution, and then execute requestServiceBindingsLocked, which is related to bind services, the last is sendServiceArgsLocked, which is the processing of the Start service.

Private final void realStartServiceLocked (ServiceRecord r,

ProcessRecord app, boolean execInFg) throws RemoteException {

...

App. thread. scheduleCreateService (r, r. serviceInfo, mAm. compatibilityInfoForPackageLocked (r. serviceInfo. applicationInfo), app. repProcState );

...

RequestServiceBindingsLocked (r, execInFg );

SendServiceArgsLocked (r, execInFg, true );

...

}

 

 

RequestServiceBindingsLocked then calls the ActivityThread method scheduleBindService. In ActivityThread. java, it sends a BIND_SERVICE event, which is processed by handleBindService,

Private void handleBindService (BindServiceData data ){

...

If (! Data. rebind ){

IBinder binder = s. onBind (data. intent );

ActivityManagerNative. getDefault (). publishService (

Data. token, data. intent, binder );

} Else {

S. onRebind (data. intent );

ActivityManagerNative. getDefault (). serviceDoneExecuting (

Data. token, 0, 0, 0 );

}

...

The onBind method of the service is called first. Because the service is overloaded, the method of the specific service class is executed and the binder instance in the service is returned. This binder will be used later,

The publishService method of AMS is called. In ActivityManagerService. java, the publishServiceLocked of ActiveServices. java is called,

Void publishServiceLocked (ServiceRecord r, Intent intent, IBinder service ){

...

For (int conni = r. connections. size ()-1; conni> = 0; conni --){

ArrayList <ConnectionRecord> clist = r. connections. valueAt (conni );

For (int I = 0; I <clist. size (); I ++ ){

ConnectionRecord c = clist. get (I );

...

Try {

C. conn. connected (r. name, service );

}...

 

ServiceDoneExecutingLocked (r, mDestroyingServices. contains (r), false );

Here we call c. conn. connected. c is ConnectionRecord, and its member conn is an IServiceConnection instance. As mentioned above, connected is the method of its implementation class.

 

For IServiceConnection, it is an interface located in (frameworks \ base): core/java/android/app/IServiceConnection. aidl. The definition of aidl is as follows. It has only one interface method connected,

Oneway interface IServiceConnection {

Void connected (in ComponentName name, IBinder service );

}

 

Its server implementation is in LoadedApk. java, as shown below, the InnerConnection class is the internal class of ServiceDispatcher and instantiated in the ServiceDispatcher constructor. Its method connected is also the method of calling ServiceDispatcher connected,

Private static class InnerConnection extendsIServiceConnection. Stub {

Final WeakReference <LoadedApk. ServiceDispatcher> mDispatcher;

 

InnerConnection (LoadedApk. ServiceDispatcher sd ){

MDispatcher = new WeakReference <LoadedApk. ServiceDispatcher> (sd );

}

 

Public void connected (ComponentName name, IBinder service) throws RemoteException {

LoadedApk. ServiceDispatcher sd = mDispatcher. get ();

If (sd! = Null ){

Sd. connected (name, service );

}

}

}

 

ServiceDispatcher (ServiceConnection conn,

Context context, Handler activityThread, int flags ){

MIServiceConnection = new InnerConnection (this );

MConnection = conn;

MContext = context;

MActivityThread = activityThread;

MLocation = new ServiceConnectionLeaked (null );

MLocation. fillInStackTrace ();

MFlags = flags;

}

 

Here we will return to the bindServiceCommon method in ContextImpl. When ServiceConnection is converted to IServiceConnection, mPackageInfo. getServiceDispatcher is called, and mPackageInfo is a LoadedApk instance,

/* Package */LoadedApk mPackageInfo;

 

Private boolean bindServiceCommon (Intent service, ServiceConnection conn, int flags,

UserHandle user ){

IServiceConnection sd;

 

Sd = mPackageInfo. getServiceDispatcher (conn, getOuterContext (),

MMainThread. getHandler (), flags );

}

 

Therefore, getServiceDispatcher will create a ServiceDispatcher instance, form a KV pair between the ServiceDispatcher instance and the ServiceConnection instance, and assign ServiceConnection instance c to the ServiceConnection member variable mConnection in the ServiceDispatcher constructor,

Public final IServiceConnection getServiceDispatcher (ServiceConnection c,

Context context, Handler handler, int flags ){

Synchronized (mServices ){

LoadedApk. ServiceDispatcher sd = null;

ArrayMap <ServiceConnection, LoadedApk. ServiceDispatcher> map = mServices. get (context );

If (map! = Null ){

Sd = map. get (c );

}

If (sd = null ){

Sd = new ServiceDispatcher (c, context, handler, flags );

If (map = null ){

Map = new ArrayMap <ServiceConnection, LoadedApk. ServiceDispatcher> ();

MServices. put (context, map );

}

Map. put (c, sd );

...

}

 

 

In this way, when the ServiceDispatcher's connected method is executed, the ServiceConnection

OnServiceConnected to complete the binding of ServiceConnection.

Public void doConnected (ComponentName name, IBinder service ){

...

If (old! = Null ){

MConnection. onServiceDisconnected (name );

}

// If there is a new service, it is now connected.

If (service! = Null ){

MConnection. onServiceConnected (name, service );

}

}

 

So far, the main process of bindService has been completed.

 

We will use a picture below to summarize the process,





Is the service in android the same thread as the component that enables the service?

The same process, but not the same thread, should know the difference between the Process and the thread, but it is not recommended to modify it.

Why didn't the onServiceConnected () method be called when bindService () is used in android to start the service,

It's amazing that you wrote this. I saw it for the first time. Shouldn't there be a class for the extends Service? I saw it for the first time using Activity to implement serviceConnection. It's hard to evaluate whether you are right or not.

Related Article

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.