梳理unbindService的相关流程
ContextImpl#unbindService
1642 @Override
1643 public void unbindService(ServiceConnection conn) {
1644 if (conn == null) {
1645 throw new IllegalArgumentException("connection is null");
1646 }
1647 if (mPackageInfo != null) {
1648 IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
1649 getOuterContext(), conn); //sd为ServiceConnection对应的binder对象
1650 try {
1651 ActivityManager.getService().unbindService(sd);
1652 } catch (RemoteException e) {
1653 throw e.rethrowFromSystemServer();
1654 }
1655 } else {
1656 throw new RuntimeException("Not supported in system context");
1657 }
1658 }
LoadedApk#forgetServiceDispatcher
1446 public final IServiceConnection forgetServiceDispatcher(Context context,
1447 ServiceConnection c) {
1448 synchronized (mServices) {
1449 ArrayMap map
1450 = mServices.get(context);
1451 LoadedApk.ServiceDispatcher sd = null;
1452 if (map != null) {
1453 sd = map.get(c);
1454 if (sd != null) {
1455 if (DEBUG) Slog.d(TAG, "Removing dispatcher " + sd + " for conn " + c);
1456 map.remove(c); //从客户端的缓存中移除ServiceConnection
1457 sd.doForget();
1458 if (map.size() == 0) {
1459 mServices.remove(context);
1460 }
1461 if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
1462 ArrayMap holder
1463 = mUnboundServices.get(context);
1464 if (holder == null) {
1465 holder = new ArrayMap();
1466 mUnboundServices.put(context, holder);
1467 }
1468 RuntimeException ex = new IllegalArgumentException(
1469 "Originally unbound here:");
1470 ex.fillInStackTrace();
1471 sd.setUnbindLocation(ex);
1472 holder.put(c, sd);
1473 }
1474 return sd.getIServiceConnection();
1475 }
1476 }
1477 ArrayMap holder
1478 = mUnboundServices.get(context); //mUnboundServices相当于缓存已经unbind的ServiceConnection
1479 if (holder != null) {
1480 sd = holder.get(c);
1481 if (sd != null) {
1482 RuntimeException ex = sd.getUnbindLocation();
1483 throw new IllegalArgumentException(
1484 "Unbinding Service " + c
1485 + " that was already unbound", ex);
1486 }
1487 }
1488 if (context == null) {
1489 throw new IllegalStateException("Unbinding Service " + c
1490 + " from Context that is no longer in use: " + context);
1491 } else {
1492 throw new IllegalArgumentException("Service not registered: " + c);
1493 }
1494 }
1495 }
LoadedApk.ServiceDispatcher#doForget
在客户端本地先将ServiceConnection对象保存的Service实例的binder对象都去掉
1559 void doForget() {
1560 synchronized(this) {
1561 for (int i=0; i
从上面的代码可以看出,在将解绑请求发往AMS之前,客户端所在进程的LoadApk会先清除ServiceConnection相关的记录信息
ActivityManagerService#unBindService
客户端-调用方定了;unbindService(ServiceConnection)也定了,那么三要素满足两个;剩下Intent,Intent不同,绑定的Service不同,那么需要解绑的也不同;不同的ServiceRecord,不同的IntetBindRecord
//bindService时客户端固定,指定了Intent和ServiceConnection,相当于固定了一个ConnectionRecord和对应的ServiceRecord
//而unbindService时,只固定了客户端和ServiceConnection,就是说一次unbind不同Intent绑定的不同ServiceRecord
19012 public boolean unbindService(IServiceConnection connection) {
19013 synchronized (this) {
19014 return mServices.unbindServiceLocked(connection);
19015 }
19016 }
ActiveServices#unbindServiceLocked
1592 boolean unbindServiceLocked(IServiceConnection connection) {
1593 IBinder binder = connection.asBinder();
1594 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "unbindService: conn=" + binder);
//得到Connection对应的ConnectionRecord
//这里其实也说明了,一个ServiceConnection(一个binder)可以绑定多个服务
//每个Service有对应的ConnectionRecord
//一个ServiceConnection可能绑定多个Service实例,这样就有多个ConnectionRecord
1595 ArrayList clist = mServiceConnections.get(binder);
1596 if (clist == null) {
1597 Slog.w(TAG, "Unbind failed: could not find connection for "
1598 + connection.asBinder());
1599 return false;
1600 }
1601
1602 final long origId = Binder.clearCallingIdentity(); //暂时清除uid,pid
1603 try {
1604 while (clist.size() > 0) {
//对ServiceConnection绑定的所有Service进行操作
1605 ConnectionRecord r = clist.get(0);
//进行清除操作
1606 removeConnectionLocked(r, null, null); //对客户端进程的ServiceConnection绑定的所有ConnectionRecord(此时与ServiceRecord一一对应)进行清理,解绑等操作
1607 if (clist.size() > 0 && clist.get(0) == r) {
1608 // In case it didn't get removed above, do it now.
1609 Slog.wtf(TAG, "Connection " + r + " not removed for binder " + binder);
1610 clist.remove(0);
1611 }
1612
1613 if (r.binding.service.app != null) { //r.binding.service.app 绑定Service所在的进程ProcessRecord
1614 if (r.binding.service.app.whitelistManager) {
1615 updateWhitelistManagerLocked(r.binding.service.app);
1616 }
1617 // This could have made the service less important.
1618 if ((r.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
1619 r.binding.service.app.treatLikeActivity = true;
1620 mAm.updateLruProcessLocked(r.binding.service.app,
1621 r.binding.service.app.hasClientActivities
1622 || r.binding.service.app.treatLikeActivity, null);
1623 }
1624 mAm.updateOomAdjLocked(r.binding.service.app, false); //调整进程优先级
1625 }
1626 }
1627
1628 mAm.updateOomAdjLocked();
1629
1630 } finally {
1631 Binder.restoreCallingIdentity(origId);
1632 }
1633
1634 return true;
1635 }
ActiveServices#removeConnectionLocked
针对ServiceConnection对应的ConnectionRecord(可能有多个,对应绑定多个Service的情况),该函数针对单个ConnectionRecord做相关清理工作
2737 void removeConnectionLocked(
2738 ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct) {
2739 IBinder binder = c.conn.asBinder(); //IServiceConnection对应的binder对象
//Serviceconnection对应的binder对象
2740 AppBindRecord b = c.binding; //ConnectionRecord所依赖的AppBindRecord(客户端)
2741 ServiceRecord s = b.service;
//ConnectionRecord固定之后,AppBindRecord和IntentBindRecord,ServiceRecord都固定了,ConnectionRecord是最小的;
//通过对应的AppBindRecord找到相应的ServiceRecord对象
2742 ArrayList clist = s.connections.get(binder); // IBinder -> ConnectionRecord of all bound clients
2743 if (clist != null) {
2744 clist.remove(c); //从ServiceConnection保存的ConnectionRecord队列中移除当前ConnectionRecord
2745 if (clist.size() == 0) {
2746 s.connections.remove(binder); //ServiceConnection对应的ConnectionRecord list为空时,将IServiceConnection也移除
2747 }
2748 }
2749 b.connections.remove(c); //从AppBindRecord保存的ConnectionRecord队列中移除当前ConnectionRecord
2750 if (c.activity != null && c.activity != skipAct) {
2751 if (c.activity.connections != null) {
2752 c.activity.connections.remove(c);
2753 }
2754 }
2755 if (b.client != skipApp) {
2756 b.client.connections.remove(c);
2757 if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
2758 b.client.updateHasAboveClientLocked();
2759 }
2760 // If this connection requested whitelist management, see if we should
2761 // now clear that state.
2762 if ((c.flags&Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
2763 s.updateWhitelistManager();
2764 if (!s.whitelistManager && s.app != null) {
2765 updateWhitelistManagerLocked(s.app);
2766 }
2767 }
2768 if (s.app != null) {
2769 updateServiceClientActivitiesLocked(s.app, c, true);
2770 }
2771 }
2772 clist = mServiceConnections.get(binder); //将ActiveServices中的保存的>中移除ConnectionRecord
2773 if (clist != null) {
2774 clist.remove(c);
2775 if (clist.size() == 0) {
2776 mServiceConnections.remove(binder);
2777 }
2778 }
2779 //上面主要就是在AMS保存的数据结构中移除ConnectionRecord
2780 mAm.stopAssociationLocked(b.client.uid, b.client.processName, s.appInfo.uid, s.name); //取消客户端和服务端之间的关联性
2781
2782 if (b.connections.size() == 0) {
2783 b.intent.apps.remove(b.client); //将对应的IntentBindRecord中移除对应客户端进程
2784 }
2785 //以上都是些准备工作
2786 if (!c.serviceDead) { //在bringDownServiceLocked中会将Service中保存的所有ConnectionRecord.serviceDead置为true
2787 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Disconnecting binding " + b.intent
2788 + ": shouldUnbind=" + b.intent.hasBound);
2789 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
2790 && b.intent.hasBound) {
//可见,只有IntentBindRecord(与ServiceRecord对应)保存的所有客户端AppBindRecord都unbind或被杀死时,相应的Service才会调用onUnbind
//参考https://blog.csdn.net/ithouse/article/details/79085648
2791 try {
2792 bumpServiceExecutingLocked(s, false, "unbind");
2793 if (b.client != s.app && (c.flags&Context.BIND_WAIVE_PRIORITY) == 0
2794 && s.app.setProcState <= ActivityManager.PROCESS_STATE_RECEIVER) {
2795 // If this service's process is not already in the cached list,
2796 // then update it in the LRU list here because this may be causing
2797 // it to go down there and we want it to start out near the top.
2798 mAm.updateLruProcessLocked(s.app, false, null);
2799 }
2800 mAm.updateOomAdjLocked(s.app, true);
2801 b.intent.hasBound = false;
2802 // Assume the client doesn't want to know about a rebind;
2803 // we will deal with that later if it asks for one.
2804 b.intent.doRebind = false;
//调用ApplicationThread的scheduleUnbindService函数
2805 s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
2806 } catch (Exception e) {
2807 Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
2808 serviceProcessGoneLocked(s);
2809 }
2810 }
2811
2812 // If unbound while waiting to start, remove the pending service
2813 mPendingServices.remove(s);
2814
2815 if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
//如果是以BIND_AUTO_CREATE启动的服务
//flag为BIND_AUTO_CREATE的ConnectionRecord又减少了一个时,则可能会需要完全destory service
//当前Service是否还有flag为BIND_AUTO_CREATE的binded客户端,如果还有则不能销毁
2816 boolean hasAutoCreate = s.hasAutoCreateConnections();
2817 if (!hasAutoCreate) {
2818 if (s.tracker != null) {
2819 s.tracker.setBound(false, mAm.mProcessStats.getMemFactorLocked(),
2820 SystemClock.uptimeMillis());
2821 }
2822 }
//与Unbounded Service一样,调用bringDownServiceIfNeededLocked判断是否需要结束服务
//真正调用bringDownService是有条件的
2823 bringDownServiceIfNeededLocked(s, true, hasAutoCreate);
2824 }
2825 }
2826 }
ActivityThread#scheduleUnbindService
85 public final void scheduleUnbindService(IBinder token, Intent intent) {
886 BindServiceData s = new BindServiceData();
887 s.token = token; //ServiceRecord
888 s.intent = intent; //对应的intent
889
890 sendMessage(H.UNBIND_SERVICE, s);
891 }
892
1712 case UNBIND_SERVICE:
1713 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
1714 handleUnbindService((BindServiceData)msg.obj);
1715 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1716 break;
3425 private void handleUnbindService(BindServiceData data) {
3426 Service s = mServices.get(data.token); //ServiceRecord对应的Service实例
3427 if (s != null) {
3428 try {
3429 data.intent.setExtrasClassLoader(s.getClassLoader());
3430 data.intent.prepareToEnterProcess();
3431 boolean doRebind = s.onUnbind(data.intent); //调用onUnbind
// * @return Return true if you would like to have the service's
//* {@link #onRebind} method later called when new clients bind to it.
//return true,则当有新客户端bind时,调用Service的onRebind
3432 try {
3433 if (doRebind) {
3434 ActivityManager.getService().unbindFinished(
3435 data.token, data.intent, doRebind);
3436 } else {
3437 ActivityManager.getService().serviceDoneExecuting(
3438 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
3439 }
3440 } catch (RemoteException ex) {
3441 throw ex.rethrowFromSystemServer();
3442 }
3443 } catch (Exception e) {
3444 if (!mInstrumentation.onException(s, e)) {
3445 throw new RuntimeException(
3446 "Unable to unbind to service " + s
3447 + " with " + data.intent + ": " + e.toString(), e);
3448 }
3449 }
3450 }
3451 }
ActivityManagerService#unbindFinished
19032 public void unbindFinished(IBinder token, Intent intent, boolean doRebind) {
19033 // Refuse possible leaked file descriptors
19034 if (intent != null && intent.hasFileDescriptors() == true) {
19035 throw new IllegalArgumentException("File descriptors passed in Intent");
19036 }
19037
19038 synchronized(this) {
19039 mServices.unbindFinishedLocked((ServiceRecord)token, intent, doRebind); //doRebind = true
19040 }
19041 }
ActiveServices#unbindFinishedLocked
1637 void unbindFinishedLocked(ServiceRecord r, Intent intent, boolean doRebind) {
1638 final long origId = Binder.clearCallingIdentity();
1639 try {
1640 if (r != null) {
1641 Intent.FilterComparison filter
1642 = new Intent.FilterComparison(intent);//创建Intent相应的Intent.FilterComparison
1643 IntentBindRecord b = r.bindings.get(filter); //找到对应的IntentBindRecord
1644 if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "unbindFinished in " + r
1645 + " at " + b + ": apps="
1646 + (b != null ? b.apps.size() : 0));
1647
1648 boolean inDestroying = mDestroyingServices.contains(r);
1649 if (b != null) {
1650 if (b.apps.size() > 0 && !inDestroying) {
//走到这里时本来b.apps.size()==0,而不等于null说明又有客户端bind了
1651 // Applications have already bound since the last
1652 // unbind, so just rebind right here.
1653 boolean inFg = false;
1654 for (int i=b.apps.size()-1; i>=0; i--) {
1655 ProcessRecord client = b.apps.valueAt(i).client;
1656 if (client != null && client.setSchedGroup
1657 != ProcessList.SCHED_GROUP_BACKGROUND) {
1658 inFg = true;
1659 break;
1660 }
1661 }
1662 try {
1663 requestServiceBindingLocked(r, b, inFg, true);
//由于rebind为true,最终会调用Sevice.onRebind
1664 } catch (TransactionTooLargeException e) {
1665 // Don't pass this back to ActivityThread, it's unrelated.
1666 }
1667 } else {
1668 // Note to tell the service the next time there is
1669 // a new client.
1670 b.doRebind = true;
1671 }
1672 }
1673
1674 serviceDoneExecutingLocked(r, inDestroying, false);
1675 }
1676 } finally {
1677 Binder.restoreCallingIdentity(origId);
1678 }
1679 }
onUnbind返回true时最终调用Service实例的onRebind,逻辑在:
3550 private void handleBindService(BindServiceData data) {
3551 Service s = mServices.get(data.token);
3552 if (DEBUG_SERVICE)
3553 Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
3554 if (s != null) {
3555 try {
3556 data.intent.setExtrasClassLoader(s.getClassLoader());
3557 data.intent.prepareToEnterProcess();
3558 try {
3559 if (!data.rebind) {
3560 IBinder binder = s.onBind(data.intent); //调用Service的onBind函数,返回一个binder对象
3561 ActivityManager.getService().publishService(
3562 data.token, data.intent, binder); //调用AMS的pushService函数,发布服务,binder代表Service实例的binder对象
3563 } else {
3564 s.onRebind(data.intent);
3565 ActivityManager.getService().serviceDoneExecuting(
3566 data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
3567 }
3568 ensureJitEnabled();
3569 } catch (RemoteException ex) {
3570 throw ex.rethrowFromSystemServer();
3571 }
3572 } catch (Exception e) {
3573 if (!mInstrumentation.onException(s, e)) {
3574 throw new RuntimeException(
3575 "Unable to bind to service " + s
3576 + " with " + data.intent + ": " + e.toString(), e);
3577 }
3578 }
3579 }
3580 }
调用bringDownServiceIfNeededLocked,直到真正调用bringDownServiceLocked,bringDownServiceLocked里面的逻辑,包括对ServiceRecord包含的所有ConnectionRecord客户端调用其onServiceDisconnected接口;以及调用onDestroy方法销毁服务端Service实例,参考 Service相关流程学习-Unbouned Stop Service
unbindService流程图
参考:
Android 7.0 ActivityManagerService(6) Service相关流程分析