StartActivity的流程 Activity组件之一Service--- BindService & unBindService

来源:互联网 发布:g71指令编程简单实例 编辑:程序博客网 时间:2024/05/21 13:03

http://blog.csdn.net/siobhan/article/details/8184052

http://blog.csdn.net/siobhan/article/details/8566883


接着上一篇StartService,这章分析一下bindService的一个流程。

在Android developer网站上有三种使用创建Bound Service的方法:

    一种就是继承Binder Class的,这种方法用在当你的Service只会用在自己的进程当中,而不会出现换进程的调用。也就是所谓的LocalService.

   一种是使用Messager,这是通过使用Handler相关的东西,去实现跨进程的调用。

    最后一种就是AIDL,最常用的一种跨进程的Service binder调用。

1. ContextImpl.bindService()

    通常我们想去调用一个Service的时候,会传递一个Intent和一个ServiceConnection还有一个flags参数。ServiceConnection是需要我们继承的。

    flags:Operation options for the binding

    1. 通过mPackageInfo.getServiceDispatcher(conn, getOuterContext(),mMainThread.getHandler(), flags);   

    2. 通过ActivityManagerNative去远程调用AMS。

[java] view plaincopyprint?
  1.     public boolean bindService(Intent service, ServiceConnection conn,int flags) {  
  2.         warnIfCallingFromSystemProcess();  
  3.         return bindService(service, conn, flags, UserHandle.getUserId(Process.myUid()));  
  4.     }  
  5.   
  6.     /** @hide */  
  7.     @Override  
  8.     public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) {  
  9.         IServiceConnection sd;  
  10.   
  11.         try {  
  12.             IBinder token = getActivityToken();  
  13.             if (mPackageInfo != null) {  
  14.             sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),  
  15.                     mMainThread.getHandler(), flags);                                                                                                                 ... ...  
  16.             int res = ActivityManagerNative.getDefault().bindService(  
  17.                 mMainThread.getApplicationThread(), getActivityToken(),  
  18.                 service, service.resolveTypeIfNeeded(getContentResolver()),  
  19.                 sd, flags, userHandle);  
  20.             ... ...  
  21.             return res != 0;  
  22.         } catch (RemoteException e) {  
  23.             return false;  
  24.         }  
  25.     }  

 


1.1 LoaderApk.getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags)

       在ServiceDispatcher会保存着传进来的ServiceConnection,同时有一个InnerConnection对象,而InnerConnection是继承自IServiceConnection.Stub,所以InnerConnection是一个Binder的服务端。sd.getIServiceConnection()返回的就是InnerConnection对象mIServiceConnection。 

       里面有两个Map数组,一个context对应一组(ServiceConnection和ServiceDispatcher的map),一个ServiceConnection对应一个ServiceDispatcher。

[java] view plaincopyprint?
  1. public final IServiceConnection getServiceDispatcher(ServiceConnection c,  
  2.         Context context, Handler handler, int flags) {  
  3.     synchronized (mServices) {  
  4.         LoadedApk.ServiceDispatcher sd = null;  
  5.         HashMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);  
  6.         if (map != null) {  
  7.             sd = map.get(c);  
  8.         }  
  9.         if (sd == null) {  
  10.             sd = new ServiceDispatcher(c, context, handler, flags);  
  11.             if (map == null) {  
  12.                 map = new HashMap<ServiceConnection, LoadedApk.ServiceDispatcher>();  
  13.                 mServices.put(context, map);  
  14.             }  
  15.             map.put(c, sd);  
  16.         } else {  
  17.             sd.validate(context, handler);  
  18.         }  
  19.         return sd.getIServiceConnection();  
  20.     }  
  21. }  



 

[java] view plaincopyprint?
  1. private static class InnerConnection extends IServiceConnection.Stub {  
  2.     final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;  
  3.   
  4.     InnerConnection(LoadedApk.ServiceDispatcher sd) {  
  5.         mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);  
  6.     }  
  7.   
  8.     public void connected(ComponentName name, IBinder service) throws RemoteException {  
  9.         LoadedApk.ServiceDispatcher sd = mDispatcher.get();  
  10.         if (sd != null) {  
  11.             sd.connected(name, service);  
  12.         }  
  13.     }  
  14. }  
  15.   
  16. private final HashMap<ComponentName, ServiceDispatcher.ConnectionInfo> mActiveConnections  
  17.     = new HashMap<ComponentName, ServiceDispatcher.ConnectionInfo>();  
  18.   
  19. ServiceDispatcher(ServiceConnection conn,  
  20.         Context context, Handler activityThread, int flags) {  
  21.     mIServiceConnection = new InnerConnection(this);  
  22.     mConnection = conn;  
  23.     mContext = context;  
  24.     mActivityThread = activityThread;  
  25.     mLocation = new ServiceConnectionLeaked(null);  
  26.     mLocation.fillInStackTrace();  
  27.     mFlags = flags;  
  28. }  

 


2. AMS.bindService(IApplicationThread caller, IBinder token, Intent service, String resolvedType,  IServiceConnection connection, int flags, int userId)

  1. 直接调用mServices.bindServiceLocked

[java] view plaincopyprint?
  1. public int bindService(IApplicationThread caller, IBinder token,  
  2.         Intent service, String resolvedType,  
  3.         IServiceConnection connection, int flags, int userId) {  
  4.     enforceNotIsolatedCaller("bindService");  
  5.     // Refuse possible leaked file descriptors  
  6.     if (service != null && service.hasFileDescriptors() == true) {  
  7.         throw new IllegalArgumentException("File descriptors passed in Intent");  
  8.     }  
  9.   
  10.     synchronized(this) {  
  11.         return mServices.bindServiceLocked(caller, token, service, resolvedType,  
  12.                 connection, flags, userId);  
  13.     }  
  14. }  


 

2.1 ActiveService.bindServiceLocked(IApplicationThread caller, IBinder token,  Intent service, String resolvedType,  IServiceConnection connection, int flags, int userId)

    1. 通过传进来的token值到ActivityStack中查询该token值是不是已经有了,就是调用者Activity的 ActivityRecord

    2. 通过retrieveServiceLocked找到需要bind的service放到新的ServiceRecord中

    3.  新建AppBindRecord, ConnectionRecord, 获取Clinet端传过来的ServiceDispatcher.InnerConnection的IBinder,把IBinder与ConnectionRecord建立关系并保持在对应的connections中。

    4. bringUpServiceLocked, 启动Service // goto 2.1.4 

[java] view plaincopyprint?
  1.     int bindServiceLocked(IApplicationThread caller, IBinder token,  
  2.             Intent service, String resolvedType,  
  3.             IServiceConnection connection, int flags, int userId) {  
  4.   
  5.         ActivityRecord activity = null;  
  6.         if (token != null) {  
  7.             activity = mAm.mMainStack.isInStackLocked(token);  
  8.             if (activity == null) {  
  9.                 Slog.w(TAG, "Binding with unknown activity: " + token);  
  10.                 return 0;  
  11.             }  
  12.         }                                                                                                                                                         ... ...  
  13.         int clientLabel = 0;  
  14.         PendingIntent clientIntent = null;  
  15.         ... ...  
  16.         ServiceLookupResult res =  
  17.             retrieveServiceLocked(service, resolvedType,  
  18.                     Binder.getCallingPid(), Binder.getCallingUid(), userId, true);  
  19.   
  20.         ServiceRecord s = res.record;  
  21.   
  22.         try {  
  23.             AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);  
  24.             ConnectionRecord c = new ConnectionRecord(b, activity,  
  25.                     connection, flags, clientLabel, clientIntent);  
  26.   
  27.             IBinder binder = connection.asBinder();  
  28.             ArrayList<ConnectionRecord> clist = s.connections.get(binder);  
  29.             if (clist == null) {  
  30.                 clist = new ArrayList<ConnectionRecord>();  
  31.                 s.connections.put(binder, clist);  
  32.             }  
  33.             clist.add(c);  
  34.             b.connections.add(c);  
  35.             if (activity != null) {  
  36.                 if (activity.connections == null) {  
  37.                     activity.connections = new HashSet<ConnectionRecord>();  
  38.                 }  
  39.                 activity.connections.add(c);  
  40.             }  
  41.             b.client.connections.add(c);  
  42.             if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {  
  43.                 b.client.hasAboveClient = true;  
  44.             }  
  45.             clist = mServiceConnections.get(binder);  
  46.             if (clist == null) {  
  47.                 clist = new ArrayList<ConnectionRecord>();  
  48.                 mServiceConnections.put(binder, clist);  
  49.             }  
  50.             clist.add(c);  
  51.   
  52.             if ((flags&Context.BIND_AUTO_CREATE) != 0) {  
  53.                 s.lastActivity = SystemClock.uptimeMillis();  
  54.                 if (bringUpServiceLocked(s, service.getFlags(), false) != null) {  
  55.                     return 0;  
  56.                 }  
  57.             }  
  58.   
  59.             if (s.app != null) {  
  60.                 // This could have made the service more important.  
  61.                 mAm.updateOomAdjLocked(s.app);  
  62.             }  
  63.   
  64.             if (s.app != null && b.intent.received) {  
  65.                 // Service is already running, so we can immediately  
  66.                 // publish the connection.  
  67.                 try {  
  68.                     c.conn.connected(s.name, b.intent.binder);  
  69.                 } catch (Exception e) {  
  70.                     Slog.w(TAG, "Failure sending service " + s.shortName  
  71.                             + " to connection " + c.conn.asBinder()  
  72.                             + " (in " + c.binding.client.processName + ")", e);  
  73.                 }  
  74.   
  75.                 // If this is the first app connected back to this binding,  
  76.                 // and the service had previously asked to be told when  
  77.                 // rebound, then do so.  
  78.                 if (b.intent.apps.size() == 1 && b.intent.doRebind) {  
  79.                     requestServiceBindingLocked(s, b.intent, true);  
  80.                 }  
  81.             } else if (!b.intent.requested) {  
  82.                 requestServiceBindingLocked(s, b.intent, false);  
  83.             }  
  84.         } finally {  
  85.             Binder.restoreCallingIdentity(origId);  
  86.         }  
  87.   
  88.         return 1;  
  89.     }  


2.1.4 ActiveServices.bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean whileRestarting)

      1. 如果这个Service所在的进程已经起来了,就直接调用realStartServiceLocked(r, app);   如果这个Service还没有起来就先去mAm.startProcessLocked启动对应的process,然后把需要start的service添加到mPendingServices中,等到进程起来之后会调用attachApplicationLocked去启动相应的service,当然还是调用realStartServiceLocked(sr, proc);

[java] view plaincopyprint?
  1. private final String bringUpServiceLocked(ServiceRecord r,  
  2.             int intentFlags, boolean whileRestarting) {  
  3.   
  4.   
  5.         // Service is now being launched, its package can't be stopped.  
  6.         try {  
  7.             AppGlobals.getPackageManager().setPackageStoppedState(  
  8.                     r.packageName, false, r.userId);  
  9.         } catch (RemoteException e) {  
  10.         } catch (IllegalArgumentException e) {  
  11.             Slog.w(TAG, "Failed trying to unstop package "  
  12.                     + r.packageName + ": " + e);  
  13.         }  
  14.   
  15.         final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;  
  16.         final String procName = r.processName;  
  17.         ProcessRecord app;  
  18.   
  19.         if (!isolated) {  
  20.             app = mAm.getProcessRecordLocked(procName, r.appInfo.uid);  
  21.             if (DEBUG_MU)  
  22.                 Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid + " app=" + app);  
  23.             if (app != null && app.thread != null) {  
  24.                 try {  
  25.                     app.addPackage(r.appInfo.packageName);  
  26.                     realStartServiceLocked(r, app);  
  27.                     return null;  
  28.                 } catch (RemoteException e) {  
  29.                     Slog.w(TAG, "Exception when starting service " + r.shortName, e);  
  30.                 }  
  31.   
  32.                 // If a dead object exception was thrown -- fall through to  
  33.                 // restart the application.  
  34.             }  
  35.         } else {  
  36.             // If this service runs in an isolated process, then each time  
  37.             // we call startProcessLocked() we will get a new isolated  
  38.             // process, starting another process if we are currently waiting  
  39.             // for a previous process to come up.  To deal with this, we store  
  40.             // in the service any current isolated process it is running in or  
  41.             // waiting to have come up.  
  42.             app = r.isolatedProc;  
  43.         }  
  44.   
  45.   
  46.         if (!mPendingServices.contains(r)) {  
  47.             mPendingServices.add(r);  
  48.         }  
  49.   
  50.         return null;  
  51.     }  


 

2.1.4.1 ActiveService.realStartServiceLocked(ServiceRecord r, ProcessRecord app) 

         app.services.add(r);   //把record加到service所在的进程的ProcessRecord的services的数组中
         bumpServiceExecutingLocked(r, "create");   // 把service加到 r.app.executingServices中,说明这个servcie正在执行。

     1) app.thread.scheduleCreateService(r, r.serviceInfo, mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo)); 通过app.thread.scheduleCreateService去调用ActivityThread的scheduleCreateService。在ActivityThread的中通过handle去发送和处理“CREATE_SERVICE”的消息。调用handleCreateService

     2)  requestServiceBindingLock()  //这个函数在BindService的时候才会起作用 

     3)  sendServiceArgsLocked(r, true); //没有传递的参数,在这边没用

[java] view plaincopyprint?
  1.        private final void realStartServiceLocked(ServiceRecord r,  
  2.             ProcessRecord app) throws RemoteException {  
  3.         ... ...  
  4.         app.services.add(r);  
  5.         bumpServiceExecutingLocked(r, "create");  
  6.         mAm.updateLruProcessLocked(app, true);  
  7.   
  8.   
  9.         boolean created = false;  
  10.         try {  
  11.             ... ...  
  12.             EventLog.writeEvent(EventLogTags.AM_CREATE_SERVICE,  
  13.                     r.userId, System.identityHashCode(r), r.shortName,  
  14.                     mAm.mStringBuilder.toString(), r.app.pid);  
  15.             synchronized (r.stats.getBatteryStats()) {  
  16.                 r.stats.startLaunchedLocked();  
  17.             }  
  18.             mAm.ensurePackageDexOpt(r.serviceInfo.packageName);  
  19.             app.thread.scheduleCreateService(r, r.serviceInfo,  
  20.                     mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));  
  21.             r.postNotification();  
  22.             created = true;  
  23.         } finally {  
  24.             if (!created) {  
  25.                 app.services.remove(r);  
  26.                 scheduleServiceRestartLocked(r, false);  
  27.             }  
  28.         }  
  29.   
  30.         requestServiceBindingsLocked(r);  
  31.   
  32.   
  33.         // If the service is in the started state, and there are no  
  34.         // pending arguments, then fake up one so its onStartCommand() will  
  35.         // be called.   
  36.         if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {  
  37.             r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),  
  38.                     nullnull));  
  39.         }  
  40.   
  41.   
  42.         sendServiceArgsLocked(r, true);  
  43.     }  


2.1.4.1.2 ActiveService.requestServiceBindingsLocked(ServiceRecord r) 

     1) 调用 r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind); 去调用ActivityThread的方法

[java] view plaincopyprint?
  1. private final void requestServiceBindingsLocked(ServiceRecord r) {  
  2.     Iterator<IntentBindRecord> bindings = r.bindings.values().iterator();  
  3.     while (bindings.hasNext()) {  
  4.         IntentBindRecord i = bindings.next();  
  5.         if (!requestServiceBindingLocked(r, i, false)) {  
  6.             break;  
  7.         }  
  8.     }  
  9. }  

 

[java] view plaincopyprint?
  1. private final boolean requestServiceBindingLocked(ServiceRecord r,  
  2.         IntentBindRecord i, boolean rebind) {  
  3.     if (r.app == null || r.app.thread == null) {  
  4.         // If service is not currently running, can't yet bind.  
  5.         return false;  
  6.     }  
  7.     if ((!i.requested || rebind) && i.apps.size() > 0) {  
  8.         try {  
  9.             bumpServiceExecutingLocked(r, "bind");  
  10.             r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind);  
  11.             if (!rebind) {  
  12.                 i.requested = true;  
  13.             }  
  14.             i.hasBound = true;  
  15.             i.doRebind = false;  
  16.         } catch (RemoteException e) {  
  17.             if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r);  
  18.             return false;  
  19.         }  
  20.     }  
  21.     return true;  
  22. }  


2.1.4.1.2.1 ActivityThread.handleBindService()

    1) 找到对应的Service,并且调用Service.onBind(自己写的Service都是要实现onBind来返回一个IBinder用来与之交互的), 把返回的IBinder值传回ActiveService, 调用                  ActivityManagerNative.getDefault().publishService( data.token, data.intent, binder);

[java] view plaincopyprint?
  1. private void handleBindService(BindServiceData data) {  
  2.     Service s = mServices.get(data.token);  
  3.     if (DEBUG_SERVICE)  
  4.         Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);  
  5.     if (s != null) {  
  6.         try {  
  7.             data.intent.setExtrasClassLoader(s.getClassLoader());  
  8.             try {  
  9.                 if (!data.rebind) {  
  10.                     IBinder binder = s.onBind(data.intent);  
  11.                     ActivityManagerNative.getDefault().publishService(  
  12.                             data.token, data.intent, binder);  
  13.                 } else {  
  14.                     s.onRebind(data.intent);  
  15.                     ActivityManagerNative.getDefault().serviceDoneExecuting(  
  16.                             data.token, 000);  
  17.                 }  
  18.                 ensureJitEnabled();  
  19.             } catch (RemoteException ex) {  
  20.             }  
  21.         } catch (Exception e) {  
  22.         ... ...  
  23.     }  
  24. }  


2.1.4.1.2.1.1 ActiveServcie.publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) 

   里面的细节先不关注,这里主要看c.conn.connected(r.name, service); 这个就调到我们之前传进来的ServiceDispatcher.InnerConnection的connected(), 最终就用调用mConnection.onServiceConnected(name, service); 也就是ServiceConnection.onServiceConnected。

    ServiceConnection.onServiceConnected传进来的Binder就是Service.onBind()返回的值。

    所以这就建立了ServiceConnection与Service之间的关系。

[java] view plaincopyprint?
  1. void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {  
  2.     final long origId = Binder.clearCallingIdentity();  
  3.     try {  
  4.         if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r  
  5.                 + " " + intent + ": " + service);  
  6.         if (r != null) {  
  7.             Intent.FilterComparison filter  
  8.                     = new Intent.FilterComparison(intent);  
  9.             IntentBindRecord b = r.bindings.get(filter);  
  10.             if (b != null && !b.received) {  
  11.                 b.binder = service;  
  12.                 b.requested = true;  
  13.                 b.received = true;  
  14.                 if (r.connections.size() > 0) {  
  15.                     Iterator<ArrayList<ConnectionRecord>> it  
  16.                             = r.connections.values().iterator();  
  17.                     while (it.hasNext()) {  
  18.                         ArrayList<ConnectionRecord> clist = it.next();  
  19.                         for (int i=0; i<clist.size(); i++) {  
  20.                             ConnectionRecord c = clist.get(i);  
  21.                             if (!filter.equals(c.binding.intent.intent)) {  
  22.                                 if (DEBUG_SERVICE) Slog.v(  
  23.                                         TAG, "Not publishing to: " + c);  
  24.                                 if (DEBUG_SERVICE) Slog.v(  
  25.                                         TAG, "Bound intent: " + c.binding.intent.intent);  
  26.                                 if (DEBUG_SERVICE) Slog.v(  
  27.                                         TAG, "Published intent: " + intent);  
  28.                                 continue;  
  29.                             }  
  30.                             if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c);  
  31.                             try {  
  32.                                 c.conn.connected(r.name, service);  
  33.                             } catch (Exception e) {  
  34.                                 Slog.w(TAG, "Failure sending service " + r.name +  
  35.                                       " to connection " + c.conn.asBinder() +  
  36.                                       " (in " + c.binding.client.processName + ")", e);  
  37.                             }  
  38.                         }  
  39.                     }  
  40.                 }  
  41.             }  
  42.   
  43.             serviceDoneExecutingLocked(r, mStoppingServices.contains(r));  
  44.         }  
  45.     } finally {  
  46.         Binder.restoreCallingIdentity(origId);  
  47.     }  
  48. }  


 

3. ContextImpl.unbindSercie

    1) 通过ActivityManagerNative.getDefault().unbindService(sd); 调用ActiveServices.unbindServiceLocked

[java] view plaincopyprint?
  1. public void unbindService(ServiceConnection conn) {  
  2.     if (conn == null) {  
  3.         throw new IllegalArgumentException("connection is null");  
  4.     }  
  5.     if (mPackageInfo != null) {  
  6.         IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(  
  7.                 getOuterContext(), conn);  
  8.         try {  
  9.             ActivityManagerNative.getDefault().unbindService(sd);  
  10.         } catch (RemoteException e) {  
  11.         }  
  12.     } else {  
  13.         throw new RuntimeException("Not supported in system context");  
  14.     }  
  15. }  


3.1 ActiveServices.unbindServiceLocked(IServiceConnection connection) 

   1) 根据传进来的ServiceDispatcher.InnerConnection的IBinder值获取对应的ConnectionRecord的list,然后依次调用removeConnectionLocked(r, null, null);

[java] view plaincopyprint?
  1. boolean unbindServiceLocked(IServiceConnection connection) {  
  2.     IBinder binder = connection.asBinder();  
  3.     if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder);  
  4.     ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);  
  5.     if (clist == null) {  
  6.         Slog.w(TAG, "Unbind failed: could not find connection for "  
  7.               + connection.asBinder());  
  8.         return false;  
  9.     }  
  10.   
  11.     final long origId = Binder.clearCallingIdentity();  
  12.     try {  
  13.         while (clist.size() > 0) {  
  14.             ConnectionRecord r = clist.get(0);  
  15.             removeConnectionLocked(r, nullnull);  
  16.   
  17.             if (r.binding.service.app != null) {  
  18.                 // This could have made the service less important.  
  19.                 mAm.updateOomAdjLocked(r.binding.service.app);  
  20.             }  
  21.         }  
  22.     } finally {  
  23.         Binder.restoreCallingIdentity(origId);  
  24.     }  
  25.   
  26.     return true;  
  27. }  


3.1.1 ActiveServices.removeConnectionLocked( ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) 

    1) s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent()); 回调ActivityThread的handleUnbindService,在这个函数中会去s.onUnbind 去做service unBind的动作。

    2) bringDownServiceLocked(s, false);  

[java] view plaincopyprint?
  1. void removeConnectionLocked(  
  2.     ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {  
  3.     IBinder binder = c.conn.asBinder();  
  4.     AppBindRecord b = c.binding;  
  5.     ServiceRecord s = b.service;  
  6.     ArrayList<ConnectionRecord> clist = s.connections.get(binder);  
  7.     if (clist != null) {  
  8.         clist.remove(c);  
  9.         if (clist.size() == 0) {  
  10.             s.connections.remove(binder);  
  11.         }  
  12.     }  
  13.     b.connections.remove(c);  
  14.     if (c.activity != null && c.activity != skipAct) {  
  15.         if (c.activity.connections != null) {  
  16.             c.activity.connections.remove(c);  
  17.         }  
  18.     }  
  19.     if (b.client != skipApp) {  
  20.         b.client.connections.remove(c);  
  21.         if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {  
  22.             b.client.updateHasAboveClientLocked();  
  23.         }  
  24.     }  
  25.     clist = mServiceConnections.get(binder);  
  26.     if (clist != null) {  
  27.         clist.remove(c);  
  28.         if (clist.size() == 0) {  
  29.             mServiceConnections.remove(binder);  
  30.         }  
  31.     }  
  32.   
  33.     if (b.connections.size() == 0) {  
  34.         b.intent.apps.remove(b.client);  
  35.     }  
  36.   
  37.     if (!c.serviceDead) {  
  38.         if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent  
  39.                 + ": shouldUnbind=" + b.intent.hasBound);  
  40.         if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0  
  41.                 && b.intent.hasBound) {  
  42.             try {  
  43.                 bumpServiceExecutingLocked(s, "unbind");  
  44.                 mAm.updateOomAdjLocked(s.app);  
  45.                 b.intent.hasBound = false;  
  46.                 // Assume the client doesn't want to know about a rebind;  
  47.                 // we will deal with that later if it asks for one.  
  48.                 b.intent.doRebind = false;  
  49.                 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());  
  50.             } catch (Exception e) {  
  51.                 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);  
  52.                 serviceDoneExecutingLocked(s, true);  
  53.             }  
  54.         }  
  55.   
  56.         if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {  
  57.             bringDownServiceLocked(s, false);  
  58.         }  
  59.     }  
  60. }  


3.1.1.2 ActiveServices.bringDownServiceLocked(ServiceRecord r, boolean force)

    1) 如果force == false也就是并没有要求强制退出,r.connections.size() > 0 说明 这个Service还有其他Client Bind存在就直接return;  要不然r.connections.size() == 0, 说明多有的Client端都已经调用了unbind了,此时就会去把这个Service给destroy掉,通过调用r.app.thread.scheduleStopService(r);

        此时s.onDestroy();就会被调用,也就是一个Service的生命周期结束。

    2) mStoppingServices.add(r);   //加到mStoppingServices数组中。

[java] view plaincopyprint?
  1. private final void bringDownServiceLocked(ServiceRecord r, boolean force) {  
  2.     //Slog.i(TAG, "Bring down service:");   
  3.     //r.dump("  ");   
  4.   
  5.     // Does it still need to run?  
  6.     if (!force && r.startRequested) {  
  7.         return;  
  8.     }  
  9.     if (r.connections.size() > 0) {  
  10.         if (!force) {  
  11.             // XXX should probably keep a count of the number of auto-create  
  12.             // connections directly in the service.  
  13.             Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();  
  14.             while (it.hasNext()) {  
  15.                 ArrayList<ConnectionRecord> cr = it.next();  
  16.                 for (int i=0; i<cr.size(); i++) {  
  17.                     if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {  
  18.                         return;  
  19.                     }  
  20.                 }  
  21.             }  
  22.         }  
  23.   
  24.         // Report to all of the connections that the service is no longer  
  25.         // available.   
  26.         Iterator<ArrayList<ConnectionRecord>> it = r.connections.values().iterator();  
  27.         while (it.hasNext()) {  
  28.             ArrayList<ConnectionRecord> c = it.next();  
  29.             for (int i=0; i<c.size(); i++) {  
  30.                 ConnectionRecord cr = c.get(i);  
  31.                 // There is still a connection to the service that is  
  32.                 // being brought down.  Mark it as dead.  
  33.                 cr.serviceDead = true;  
  34.                 try {  
  35.                     cr.conn.connected(r.name, null);  
  36.                 } catch (Exception e) {  
  37.                     Slog.w(TAG, "Failure disconnecting service " + r.name +  
  38.                           " to connection " + c.get(i).conn.asBinder() +  
  39.                           " (in " + c.get(i).binding.client.processName + ")", e);  
  40.                 }  
  41.             }  
  42.         }  
  43.     }  
  44.     ... ...  
  45.   
  46.     if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent);  
  47.     EventLog.writeEvent(EventLogTags.AM_DESTROY_SERVICE,  
  48.             r.userId, System.identityHashCode(r), r.shortName,  
  49.             (r.app != null) ? r.app.pid : -1);  
  50.   
  51.     mServiceMap.removeServiceByName(r.name, r.userId);  
  52.     mServiceMap.removeServiceByIntent(r.intent, r.userId);  
  53.     r.totalRestartCount = 0;  
  54.     unscheduleServiceRestartLocked(r);  
  55.   
  56.     // Also make sure it is not on the pending list.  
  57.     int N = mPendingServices.size();  
  58.     for (int i=0; i<N; i++) {  
  59.         if (mPendingServices.get(i) == r) {  
  60.             mPendingServices.remove(i);  
  61.             if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r);  
  62.             i--;  
  63.             N--;  
  64.         }  
  65.     }  
  66.   
  67.     r.cancelNotification();  
  68.     r.isForeground = false;  
  69.     r.foregroundId = 0;  
  70.     r.foregroundNoti = null;  
  71.   
  72.     // Clear start entries.   
  73.     r.clearDeliveredStartsLocked();  
  74.     r.pendingStarts.clear();  
  75.   
  76.     if (r.app != null) {  
  77.         synchronized (r.stats.getBatteryStats()) {  
  78.             r.stats.stopLaunchedLocked();  
  79.         }  
  80.         r.app.services.remove(r);  
  81.         if (r.app.thread != null) {  
  82.             try {  
  83.                 bumpServiceExecutingLocked(r, "stop");  
  84.                 mStoppingServices.add(r);     
  85.                 mAm.updateOomAdjLocked(r.app);  
  86.                 r.app.thread.scheduleStopService(r);  
  87.             } catch (Exception e) {  
  88.             ... ...  
  89.         } else {  
  90.             if (DEBUG_SERVICE) Slog.v(  
  91.                 TAG, "Removed service that has no process: " + r);  
  92.         }  
  93.     } else {  
  94.         if (DEBUG_SERVICE) Slog.v(  
  95.             TAG, "Removed service that is not running: " + r);  
  96.     }  
  97.     ... ...  
  98. }  

 


3.1.1.2.1 ActivityThread.handleStopService

       当handleStopService执行完后,还是会调用ActiveServices.serviceDoneExecutingLocked告诉AMS客户端已经执行完成了。

       此时inStopping为true,因为这个ServiceRecord已经加到mStoppingServices中

[java] view plaincopyprint?
  1. void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {  
  2.     boolean inStopping = mStoppingServices.contains(r);  
  3.     if (r != null) {  
  4.         ... ...  
  5.         final long origId = Binder.clearCallingIdentity();  
  6.         serviceDoneExecutingLocked(r, inStopping);  
  7.         Binder.restoreCallingIdentity(origId);  
  8.     } else {  
  9.         Slog.w(TAG, "Done executing unknown service from pid "  
  10.                 + Binder.getCallingPid());  
  11.     }  
  12. }  


 

[java] view plaincopyprint?
  1. private void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping) {  
  2.     if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r  
  3.             + ": nesting=" + r.executeNesting  
  4.             + ", inStopping=" + inStopping + ", app=" + r.app);  
  5.     else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName);  
  6.     r.executeNesting--;  
  7.     if (r.executeNesting <= 0 && r.app != null) {  
  8.         if (DEBUG_SERVICE) Slog.v(TAG,  
  9.                 "Nesting at 0 of " + r.shortName);  
  10.         r.app.executingServices.remove(r);  
  11.         if (r.app.executingServices.size() == 0) {  
  12.             if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG,  
  13.                     "No more executingServices of " + r.shortName);  
  14.             mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app);  
  15.         }  
  16.         if (inStopping) {  
  17.             if (DEBUG_SERVICE) Slog.v(TAG,  
  18.                     "doneExecuting remove stopping " + r);  
  19.             mStoppingServices.remove(r);  
  20.             r.bindings.clear();  
  21.         }  
  22.         mAm.updateOomAdjLocked(r.app);  
  23.     }  
  24. }  

 

0 0
原创粉丝点击