Android4.4——service之bindService

具体可参考“老罗的Android之旅”中的《Android应用程序绑定服务(bindService)的过程源代码分析》一文。


下面跟踪bindService流程。

Step 1、ContextWrapper::bindService()

代码位于frameworks/base/core/java/android/content/ContextWrapper.java。

    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }
    Context mBase;

class ContextImpl extends Context {
      ......
}

其中mBase为一个ContextImpl对象(具体的分析过程请参考startService的文章)。

Step 2、ContextImpl::bindService()

代码位于frameworks/base/core/java/android/app/ContextImpl.java。

    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, Process.myUserHandle());
    }
Step 3、ContextImpl::bindServiceCommon()
代码位于frameworks/base/core/java/android/app/ContextImpl.java。

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
            UserHandle user) {
        IServiceConnection sd;
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
                    mMainThread.getHandler(), flags);//作为ActivityManagerProxy::bindService的参数,将该IServiceConnection对象传递给AMS,后续AMS通过该IServiceConnection与ServiceConnection对象进行通信
        } else {
            throw new RuntimeException("Not supported in system context");
        }
        validateServiceIntent(service);
        try {
            IBinder token = getActivityToken();
            if (token == null && (flags&BIND_AUTO_CREATE) == 0 && mPackageInfo != null
                    && mPackageInfo.getApplicationInfo().targetSdkVersion
                    < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
                flags |= BIND_WAIVE_PRIORITY;
            }
            service.prepareToLeaveProcess();
            int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(),
                service, service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, user.getIdentifier());
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            return false;
        }
    }

ActivityManagerNative.getDefault().bindService通过binder机制,将调用ActivityManagerService::bindService()函数。

这里的mMainThread是一个ActivityThread实例,通过ActivityThread::getHandler()就可以获得一个Handler对象。有了该Handler对象就可以将消息发送到ActivityThread所在进程的消息队列中去。

随后调用了mPackageInfo.getServiceDispatcher函数。mPackageInfo的类型是LoadedApk,因此调用的是LoadedApk::getServiceDispatcher函数。该函数的代码位于frameworks/base/core/java/android/app/LoadedApk.java中。

final class LoadedApk {
	......

	public final IServiceConnection getServiceDispatcher(ServiceConnection c,
			Context context, Handler handler, int flags) {
		synchronized (mServices) {
			LoadedApk.ServiceDispatcher sd = null;
			HashMap 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 HashMap();
					mServices.put(context, map);
				}
				map.put(c, sd);
			} else {
				sd.validate(context, handler);
			}
			return sd.getIServiceConnection();
		}
	}

	......

	static final class ServiceDispatcher {
		private final ServiceDispatcher.InnerConnection mIServiceConnection;
		private final ServiceConnection mConnection;
		private final Handler mActivityThread;
		......

		private static class InnerConnection extends IServiceConnection.Stub {
			final WeakReference mDispatcher;
			......

			InnerConnection(LoadedApk.ServiceDispatcher sd) {
				mDispatcher = new WeakReference(sd);
			}

			......
		}

		......

		ServiceDispatcher(ServiceConnection conn,
				Context context, Handler activityThread, int flags) {
			mIServiceConnection = new InnerConnection(this);
			mConnection = conn;
			mActivityThread = activityThread;
			......
		}

		......

		IServiceConnection getIServiceConnection() {
			return mIServiceConnection;
		}

		......
	}

	......
}
在getServiceDispatcher函数中,传进来的参数context是一个MainActivity实例,先以它为Key值在mServices中查看一下,是不是已经存在相应的ServiceDispatcher实例,如果有了,就不用创建了,直接取出来。在我们这个情景中,需要创建一个新的ServiceDispatcher。在创建新的ServiceDispatcher实例的过程中,将上面传下来ServiceConnection参数c和Hanlder参数保存在了ServiceDispatcher实例的内部,并且创建了一个InnerConnection对象,这是一个Binder对象,一会是要传递给ActivityManagerService的,ActivityManagerServic后续就是要通过这个Binder对象和ServiceConnection通信的。

函数getServiceDispatcher最后就是返回了一个InnerConnection对象给ContextImpl.bindService函数。回到ContextImpl.bindService函数中,它接着就要调用ActivityManagerService的远程接口来进一步处理了。

Step 4、ActivityManagerService::bindService()

代码位于frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中。

    public int bindService(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType,
            IServiceConnection connection, int flags, int userId) {
        enforceNotIsolatedCaller("bindService");
        // Refuse possible leaked file descriptors
        if (service != null && service.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        synchronized(this) {
            return mServices.bindServiceLocked(caller, token, service, resolvedType,
                    connection, flags, userId);
        }
    }

本函数的第二个参数token是由Step 3中ActivityManagerProxy::bindService参数中getActivityToken函数获得。第五个参数connection是通过LoadedApk::getServiceDispatcher函数得到的一个IServiceConnection接口。继续看看ActiveServices::bindServiceLocked函数。

Step 5、ActiveServices::bindServiceLocked()

代码位于frameworks/base/services/java/com/android/server/am/ActiveServices.java文件中。

    int bindServiceLocked(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType,
            IServiceConnection connection, int flags, int userId) {
        if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service
                + " type=" + resolvedType + " conn=" + connection.asBinder()
                + " flags=0x" + Integer.toHexString(flags));
        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);//根据IApplicationThread对象找到ProcessRecord对象
        if (callerApp == null) {
            throw new SecurityException(
                    "Unable to find app for caller " + caller
                    + " (pid=" + Binder.getCallingPid()
                    + ") when binding service " + service);
        }

        ActivityRecord activity = null;
        if (token != null) {
            activity = ActivityRecord.isInStackLocked(token);
            if (activity == null) {
                Slog.w(TAG, "Binding with unknown activity: " + token);
                return 0;
            }
        }

        int clientLabel = 0;
        PendingIntent clientIntent = null;

        if (callerApp.info.uid == Process.SYSTEM_UID) {
            // Hacky kind of thing -- allow system stuff to tell us
            // what they are, so we can report this elsewhere for
            // others to know why certain services are running.
            try {
                clientIntent = (PendingIntent)service.getParcelableExtra(
                        Intent.EXTRA_CLIENT_INTENT);
            } catch (RuntimeException e) {
            }
            if (clientIntent != null) {
                clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
                if (clientLabel != 0) {
                    // There are no useful extras in the intent, trash them.
                    // System code calling with this stuff just needs to know
                    // this will happen.
                    service = service.cloneFilter();
                }
            }
        }

        final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;

        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType,
                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);//从AMS和PMS中,获取或者新建ServiceRecord,随后封装成ServiceLoolupResult对象并返回。
        if (res == null) {
            return 0;
        }
        if (res.record == null) {
            return -1;
        }
        ServiceRecord s = res.record;

        final long origId = Binder.clearCallingIdentity();

        try {
            if (unscheduleServiceRestartLocked(s)) {
                if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: "
                        + s);
            }

            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                if (!s.hasAutoCreateConnections()) {
                    // This is the first binding, let the tracker know.
                    ProcessStats.ServiceState stracker = s.getTracker();
                    if (stracker != null) {
                        stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
                                s.lastActivity);
                    }
                }
            }

            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);//在ServiceRecord的IntentBindRecord列表,AppBindRecord列表中检索AppBindRecor,若没有,则new AppBindRecord并返回
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);

            IBinder binder = connection.asBinder();
            ArrayList clist = s.connections.get(binder);
            if (clist == null) {
                clist = new ArrayList();
                s.connections.put(binder, clist);//将ConnectionRecor放入ServiceRecord.connections列表中,在之后的publishService中依次取出。
            }
            clist.add(c);
            b.connections.add(c);
            if (activity != null) {
                if (activity.connections == null) {
                    activity.connections = new HashSet();
                }
                activity.connections.add(c);
            }
            b.client.connections.add(c);
            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
                b.client.hasAboveClient = true;
            }
            clist = mServiceConnections.get(binder);
            if (clist == null) {
                clist = new ArrayList();
                mServiceConnections.put(binder, clist);
            }
            clist.add(c);

            if ((flags&Context.BIND_AUTO_CREATE) != 0) {//若应用程序使用bindService时传入的参数为该标志时直接调用bringUpServiceLocked
                s.lastActivity = SystemClock.uptimeMillis();
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
                    return 0;
                }
            }

            if (s.app != null) {
                // This could have made the service more important.
                mAm.updateOomAdjLocked(s.app);
            }

            if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b
                    + ": received=" + b.intent.received
                    + " apps=" + b.intent.apps.size()
                    + " doRebind=" + b.intent.doRebind);

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

            getServiceMap(s.userId).ensureNotStartingBackground(s);

        } finally {
            Binder.restoreCallingIdentity(origId);
        }

        return 1;
    }

倘若应用程序中bindService时传入的参数为BIND_AUTO_CREATE时,执行bringUpServiceLocked;这里分析另外一种情况——参数flags不为BIND_AUTO_CREATE的情况。

Step 6、ActiveServices::requestServiceBindingLocked

代码位于frameworks/base/services/java/com/android/am/ActiveServices.java文件中。

    private final boolean requestServiceBindingLocked(ServiceRecord r,
            IntentBindRecord i, boolean execInFg, boolean rebind) {
        if (r.app == null || r.app.thread == null) {//若service未运行,直接返回,不做任何操作
            // If service is not currently running, can't yet bind.
            return false;
        }
        if ((!i.requested || rebind) && i.apps.size() > 0) {//rebind表示是否重新绑定service,requested表示是否已绑定service?
            try {
                bumpServiceExecutingLocked(r, execInFg, "bind");
                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                if (!rebind) {
                    i.requested = true;
                }
                i.hasBound = true;
                i.doRebind = false;
            } catch (RemoteException e) {
                if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);
                return false;
            }
        }
        return true;
    }

这里app.thread是ApplicationThread的代理对象,类型是AppllicationThreadProxy。

Step 7、ApplicationThreadProxy::scheduleBindService

代码位于frameworks/base/core/java/android/app/ActvityThread.java文件中。

        public final void scheduleBindService(IBinder token, Intent intent,
                boolean rebind, int processState) {
            updateProcessState(processState, false);
            BindServiceData s = new BindServiceData();
            s.token = token;
            s.intent = intent;
            s.rebind = rebind;

            if (DEBUG_SERVICE)
                Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
                        + Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
            sendMessage(H.BIND_SERVICE, s);
        }
这里首先将传入的参数封装成一个BindServiceData对象,随后与BIND_SERVICE一并封装后发送至消息队列。消息最终在handleMessage函数中处理。

Step 8、H::handleMessage

代码位于frameworks/base/core/java/android/app/ActvityThread.java文件中。

        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
            switch (msg.what) {
           
                ......

                case BIND_SERVICE:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
                    handleBindService((BindServiceData)msg.obj);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                ......
            }
            if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
        }
Step 9、ActivityThread::handleBindService

代码位于frameworks/base/core/java/android/app/ActvityThread.java文件中。

    private void handleBindService(BindServiceData data) {
        Service s = mServices.get(data.token);
        if (DEBUG_SERVICE)
            Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
        if (s != null) {
            try {
                data.intent.setExtrasClassLoader(s.getClassLoader());
                try {
                    if (!data.rebind) {
                        IBinder binder = s.onBind(data.intent);//获取service的一个Binder对象,然后连同service实例传入AMS
                        ActivityManagerNative.getDefault().publishService(
                                data.token, data.intent, binder);
                    } else {
                        s.onRebind(data.intent);
                        ActivityManagerNative.getDefault().serviceDoneExecuting(
                                data.token, 0, 0, 0);
                    }
                    ensureJitEnabled();
                } catch (RemoteException ex) {
                }
            } catch (Exception e) {
                if (!mInstrumentation.onException(s, e)) {
                    throw new RuntimeException(
                            "Unable to bind to service " + s
                            + " with " + data.intent + ": " + e.toString(), e);
                }
            }
        }
    }

这里的data是一个BindServiceData对象,之前是通过ApllicationThreadProxy的scheduleBindService经由Binder机制传入,通过data.token获取之前已启动了的service实例,即s。

Step 10、ActivityManagerService::publishService

代码位于frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中。

    public void publishService(IBinder token, Intent intent, IBinder service) {
        // Refuse possible leaked file descriptors
        if (intent != null && intent.hasFileDescriptors() == true) {
            throw new IllegalArgumentException("File descriptors passed in Intent");
        }

        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                throw new IllegalArgumentException("Invalid service token");
            }
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }
直接分析mServices.publishServiceLocked函数。

Setp 11、ActiveServices::publishServiceLocked

代码位于frameworks/base/services/java/com/android/server/am/ActiveServices.java文件中。

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        final long origId = Binder.clearCallingIdentity();
        try {
            if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r
                    + " " + intent + ": " + service);
            if (r != null) {
                Intent.FilterComparison filter
                        = new Intent.FilterComparison(intent);
                IntentBindRecord b = r.bindings.get(filter);
                if (b != null && !b.received) {
                    b.binder = service;
                    b.requested = true;
                    b.received = true;
                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
                        ArrayList clist = r.connections.valueAt(conni);
                        for (int i=0; i

每一个ConnectionRecord里面都有一个成员变量conn,它的类型是IServiceConnection,是一个Binder对象的远程接口。函数中体现为c.conn,它是在Step 3中通过LoadedApk::getServiceDispatch创建的LoadedApk.ServiceDispatcher.InnerConnection对象。因此,在调用c.conn.connected(r.name, service)时,进入到了LoadedApk.ServiceDispatcher.InnerConnection.connected函数中去了。

Step 12、InnerConnection::connected

代码位于frameworks/base/core/java/android/app/LoadedApk.java文件中。

final class LoadedApk {
	......

	static final class ServiceDispatcher {
		......

		private static class InnerConnection extends IServiceConnection.Stub {
			......

			public void connected(ComponentName name, IBinder service) throws RemoteException {
				LoadedApk.ServiceDispatcher sd = mDispatcher.get();
				if (sd != null) {
					sd.connected(name, service);
				}
			}
			......
		}

		......
	}

	......
}
随后立即转交给ServiceDspatcher::connected函数。

Step 13、ServiceDspatcher::connected
这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中。

final class LoadedApk {
	......

	static final class ServiceDispatcher {
		......

		public void connected(ComponentName name, IBinder service) {
			if (mActivityThread != null) {
				mActivityThread.post(new RunConnection(name, service, 0));
			} else {
				......
			}
		}

		......
	}

	......
}
这里的mActivityThread在Step 3中mPackageInfo.getServiceDispatcher的第三个参数获得,并辗转传入到本函数,是一个Handler实例。因此,接着进入到Handler::post函数中。

Step 14、Handler::post

这个函数定义在frameworks/base/core/java/android/os/Handler.java文件中。

public class Handler {

	……

    	public final boolean post(Runnable r)
   	{
       		return  sendMessageDelayed(getPostMessage(r), 0);
    	}

	……
}

调用了这个函数之后,这个消息就真正地进入到ActivityThread的消息队列去了,与sendMessage把消息放在消息队列不一样的地方是,post方式发送的消息不是由这个Handler的handleMessage函数来处理的,而是由post的参数Runnable的run函数来处理的。这里传给post的参数是一个RunConnection类型的参数,它继承了Runnable类,因此,最终会调用RunConnection.run函数来处理这个消息。

Step 15、RunConnection::run

这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中。

final class LoadedApk {
	......

	static final class ServiceDispatcher {
			
           private final class RunConnection implements Runnable {
                     RunConnection(ComponentName name, IBinder service, int command) {
                         mName = name;
                         mService = service;
                        mCommand = command;
                     }

               public void run() {
                   if (mCommand == 0) {
                       doConnected(mName, mService);
                   } else if (mCommand == 1) {
                       doDeath(mName, mService);
                   }
               }

                final ComponentName mName;
                final IBinder mService;
                final int mCommand;
             }

		......
	}

	......
}
由Step 13知,函数的command参数为0,故调用doConnected函数。

Step 14、ServiceDispatcher::doConnected

这个函数定义在frameworks/base/core/java/android/app/LoadedApk.java文件中。

final class LoadedApk {
    ......

    static final class ServiceDispatcher {
        ......

        public void doConnected(ComponentName name, IBinder service) {
            ServiceDispatcher.ConnectionInfo old;
            ServiceDispatcher.ConnectionInfo info;

            synchronized (this) {
                if (mForgotten) {
                    // We unbound before receiving the connection; ignore
                    // any connection received.
                    return;
                }
                old = mActiveConnections.get(name);
                if (old != null && old.binder == service) {
                    // Huh, already have this one.  Oh well!
                    return;
                }

                if (service != null) {
                    // A new service is being connected... set it all up.
                    mDied = false;
                    info = new ConnectionInfo();
                    info.binder = service;
                    info.deathMonitor = new DeathMonitor(name, service);
                    try {
                        service.linkToDeath(info.deathMonitor, 0);
                        mActiveConnections.put(name, info);
                    } catch (RemoteException e) {
                        // This service was dead before we got it...  just
                        // don't do anything with it.
                        mActiveConnections.remove(name);
                        return;
                    }

                } else {
                    // The named service is being disconnected... clean up.
                    mActiveConnections.remove(name);
                }

                if (old != null) {
                    old.binder.unlinkToDeath(old.deathMonitor, 0);
                }
            }

            // If there was an old service, it is not disconnected.
            if (old != null) {
                mConnection.onServiceDisconnected(name);
            }
            // If there is a new service, it is now connected.
            if (service != null) {
                mConnection.onServiceConnected(name, service);
            }
        }

        ......
    }

    ......
}
这里主要就是执行成员变量mConnection的onServiceConnected函数,这里的mConnection变量的类型的ServiceConnection,它是在前面的Step 3中mPackageInfo.getServiceDispatcher设置好的,这个ServiceConnection实例是MainActivity类内部创建的,在调用bindService函数时保存在LoadedApk.ServiceDispatcher类中,用它来换取一个IServiceConnection对象,传给ActivityManagerService。











你可能感兴趣的:(Android,Framework)