服务端被杀逻辑-可能触发客户端被杀
当服务端死亡时,如果客户端引用的是unstable provider,则不会影响客户端进程(前面已经说过),客户端清一下缓存,服务端自杀即可;但如果是stable provider ref,那么就会造成客户端被杀,逻辑大致如下:
以ProcessRecord.kill为例:
ProcessRecord.kill
656 void kill(String reason, boolean noisy) {
657 if (!killedByAm) {
658 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "kill");
659 BoostFramework ux_perf = new BoostFramework();
660 if (noisy) {
661 Slog.i(TAG, "Killing " + toShortString() + " (adj " + setAdj + "): " + reason);
662 }
665
666 EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason);
667 Process.killProcessQuiet(pid);
668 ActivityManagerService.killProcessGroup(uid, pid);
669 if (!persistent) {
670 killed = true;
671 killedByAm = true;
672 }
673 if (ux_perf != null) {
674 ux_perf.perfUXEngine_events(4, 0, this.processName, 0);
675 }
676 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
677 }
678 }
当进程死亡后,将会调用当初在attachApplication时注册的死亡回调
ActivityManangerService#attachApplicationLocked
7050 private final boolean attachApplicationLocked(IApplicationThread thread,
7051 int pid) {
7052
7053 // Find the application record that is being attached... either via
7054 // the pid if we are running in multiple processes, or just pull the
7055 // next app record if we are emulating process with anonymous threads.
7056 ProcessRecord app;
7057 long startTime = SystemClock.uptimeMillis();
7058 if (pid != MY_PID && pid >= 0) {
7059 synchronized (mPidsSelfLocked) {
7060 app = mPidsSelfLocked.get(pid);
7061 }
7062 } else {
7063 app = null;
7064 }
7065
7066 if (app == null) {
7067 Slog.w(TAG, "No pending application record for pid " + pid
7068 + " (IApplicationThread " + thread + "); dropping process");
7069 EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
7070 if (pid > 0 && pid != MY_PID) {
7074
7075 killProcessQuiet(pid);
7076 //TODO: killProcessGroup(app.info.uid, pid);
7077 } else {
7078 try {
7079 thread.scheduleExit();
7080 } catch (Exception e) {
7081 // Ignore exceptions.
7082 }
7083 }
7084 return false;
7085 }
7086
7087 // If this application record is still attached to a previous
7088 // process, clean it up now.
7089 if (app.thread != null) {
7090 handleAppDiedLocked(app, true, true);
7091 }
7092
7093 // Tell the process all about itself.
7094
7095 if (DEBUG_ALL) Slog.v(
7096 TAG, "Binding process pid " + pid + " to record " + app);
7097
7098 final String processName = app.processName;
7099 try {
7100 AppDeathRecipient adr = new AppDeathRecipient(
7101 app, pid, thread);
7102 thread.asBinder().linkToDeath(adr, 0);
7103 app.deathRecipient = adr;
7104 } catch (RemoteException e) {
7105 app.resetPackageList(mProcessStats);
7106 startProcessLocked(app, "link fail", processName);
7107 return false;
7108 }
ActivityManagerService#AppDeathRecipient
1675 private final class AppDeathRecipient implements IBinder.DeathRecipient {
1676 final ProcessRecord mApp;
1677 final int mPid;
1678 final IApplicationThread mAppThread;
1679
1680 AppDeathRecipient(ProcessRecord app, int pid,
1681 IApplicationThread thread) {
1682 if (DEBUG_ALL) Slog.v(
1683 TAG, "New death recipient " + this
1684 + " for thread " + thread.asBinder());
1685 mApp = app;
1686 mPid = pid;
1687 mAppThread = thread;
1688 }
1689
1690 @Override
1691 public void binderDied() {
1692 if (DEBUG_ALL) Slog.v(
1693 TAG, "Death received in " + this
1694 + " for thread " + mAppThread.asBinder());
1695 synchronized(ActivityManagerService.this) {
//当进程死亡后,会调用到这里面
1696 appDiedLocked(mApp, mPid, mAppThread, true);
1697 }
1698 }
1699 }
ActivityManagerService#appDiedLocked
5659 final void appDiedLocked(ProcessRecord app, int pid, IApplicationThread thread,
5660 boolean fromBinderDied) {
5661 // First check if this ProcessRecord is actually active for the pid.
5662 synchronized (mPidsSelfLocked) {
5663 ProcessRecord curProc = mPidsSelfLocked.get(pid);
5664 if (curProc != app) {
5665 Slog.w(TAG, "Spurious death for " + app + ", curProc for " + pid + ": " + curProc);
5666 return;
5667 }
5668 }
5669 BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
5670 synchronized (stats) {
5671 stats.noteProcessDiedLocked(app.info.uid, pid);
5672 }
5673
5674 if (!app.killed) {
5675 if (!fromBinderDied) {
5679
5680 killProcessQuiet(pid);
5681 }
5682 killProcessGroup(app.uid, pid);
5683 app.killed = true;
5684 }
5685
5686 // Clean up already done if the process has been re-started.
5687 if (app.pid == pid && app.thread != null &&
5688 app.thread.asBinder() == thread.asBinder()) {
5689 boolean doLowMem = app.instr == null;
5690 boolean doOomAdj = doLowMem;
5691 if (!app.killedByAm) {
5692 Slog.i(TAG, "Process " + app.processName + " (pid " + pid + ") has died: "
5693 + ProcessList.makeOomAdjString(app.setAdj)
5694 + ProcessList.makeProcStateString(app.setProcState));
5695 mAllowLowerMemLevel = true;
5696 if (mEnableNetOpts) {
5697 networkOptsCheck(1, app.processName);
5698 }
5699 } else {
5700 // Note that we always want to do oom adj to update our state with the
5701 // new number of procs.
5702 mAllowLowerMemLevel = false;
5703 doLowMem = false;
5704 }
5705 if (mUxPerf != null) {
5706 mUxPerf.perfUXEngine_events(4, 0, app.processName, 0);
5707 }
5711 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName,
5712 app.setAdj, app.setProcState);
5713 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
5714 "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
5715
5716 //handleAppDiedLocked(app, false, true);
5717 handleAppDiedLocked(app, false, ActivityManagerServiceInjector.restartDiedAppOrNot(app,app==mHomeProcess,true,fromBinderDied));
5718
5719 if (doOomAdj) {
5720 updateOomAdjLocked();
5721 }
5722 if (doLowMem) {
5723 doLowMemReportIfNeededLocked(app);
5724 }
5725 } else if (app.pid != pid) {
5726 // A new process has already been started.
5727 Slog.i(TAG, "Process " + app.processName + " (pid " + pid
5728 + ") has died and restarted (pid " + app.pid + ").");
5731 EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName, app.curProcState);
5732 } else if (DEBUG_PROCESSES) {
5733 Slog.d(TAG_PROCESSES, "Received spurious death notification for thread "
5734 + thread.asBinder());
5735 }
5736 }
ActivityManagerService#handleAppDiedLocked
5510 private final void handleAppDiedLocked(ProcessRecord app,
5511 boolean restarting, boolean allowRestart) {
5512 int pid = app.pid;
5513 boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1,
5514 false /*replacingPid*/);
5515 if (!kept && !restarting) {
5516 removeLruProcessLocked(app);
5517 if (pid > 0) {
5518 ProcessList.remove(pid);
5519 }
5520 }
5521
5522 if (mProfileProc == app) {
5523 clearProfilerLocked();
5524 }
5525
5526 // Remove this application's activities from active lists.
5527 boolean hasVisibleActivities = mStackSupervisor.handleAppDiedLocked(app);
5528
5529 app.activities.clear();
5530
5531 if (app.instr != null) {
5532 Slog.w(TAG, "Crash of app " + app.processName
5533 + " running instrumentation " + app.instr.mClass);
5534 Bundle info = new Bundle();
5535 info.putString("shortMsg", "Process crashed.");
5536 finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
5537 }
5538
5539 mWindowManager.deferSurfaceLayout();
5540 try {
5541 if (!restarting && hasVisibleActivities
5542 && !mStackSupervisor.resumeFocusedStackTopActivityLocked()) {
5543 // If there was nothing to resume, and we are not already restarting this process, but
5544 // there is a visible activity that is hosted by the process... then make sure all
5545 // visible activities are running, taking care of restarting this process.
5546 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
5547 }
5548 } finally {
5549 mWindowManager.continueSurfaceLayout();
5550 }
5551 }
ActivityManagerService#cleanUpApplicationRecordLocked
清除被杀进程中保存的相应Record对象
18461 /**
18462 * Main code for cleaning up a process when it has gone away. This is
18463 * called both as a result of the process dying, or directly when stopping
18464 * a process when running in single process mode.
18465 *
18466 * @return Returns true if the given process has been restarted, so the
18467 * app that was passed in must remain on the process lists.
18468 */
18469 private final boolean cleanUpApplicationRecordLocked(ProcessRecord app,
18470 boolean restarting, boolean allowRestart, int index, boolean replacingPid) {
18471 if (index >= 0) {
18472 removeLruProcessLocked(app);
18473 ProcessList.remove(app.pid);
18474 }
18475
18476 mProcessesToGc.remove(app);
18477 mPendingPssProcesses.remove(app);
18478
18479 // Dismiss any open dialogs.
18480 if (app.crashDialog != null && !app.forceCrashReport) {
18481 app.crashDialog.dismiss();
18482 app.crashDialog = null;
18483 }
18484 if (app.anrDialog != null) {
18485 app.anrDialog.dismiss();
18486 app.anrDialog = null;
18487 }
18488 if (app.waitDialog != null) {
18489 app.waitDialog.dismiss();
18490 app.waitDialog = null;
18491 }
18492
18493 app.crashing = false;
18494 app.notResponding = false;
18495
18496 app.resetPackageList(mProcessStats);
18497 app.unlinkDeathRecipient();
18498 app.makeInactive(mProcessStats);
18499 app.waitingToKill = null;
18500 app.forcingToImportant = null;
18501 updateProcessForegroundLocked(app, false, false);
18502 app.foregroundActivities = false;
18503 app.hasShownUi = false;
18504 app.treatLikeActivity = false;
18505 app.hasAboveClient = false;
18506 app.hasClientActivities = false;
18510
18511 mServices.killServicesLocked(app, allowRestart);
18512
18513 boolean restart = false;
18514
18515 // Remove published content providers.
18516 for (int i = app.pubProviders.size() - 1; i >= 0; i--) {
18517 ContentProviderRecord cpr = app.pubProviders.valueAt(i);
18518 final boolean always = app.bad || !allowRestart;
18519 boolean inLaunching = removeDyingProviderLocked(app, cpr, always);
//清除安装的ContentProviderRecord
18520 if ((inLaunching || always) && cpr.hasConnectionOrHandle()) {
18521 // We left the provider in the launching list, need to
18522 // restart it.
18523 restart = true;
18524 }
18525
18526 cpr.provider = null;
18527 cpr.proc = null;
18528 }
18529 app.pubProviders.clear();
18530
18531 // Take care of any launching providers waiting for this process.
18532 if (cleanupAppInLaunchingProvidersLocked(app, false)) {
18533 restart = true;
18534 }
18535
18536 // Unregister from connected content providers.
18537 if (!app.conProviders.isEmpty()) {
18538 for (int i = app.conProviders.size() - 1; i >= 0; i--) {
18539 ContentProviderConnection conn = app.conProviders.get(i);
18540 conn.provider.connections.remove(conn);
//清除保存的ContentProviderConnection list
18541 stopAssociationLocked(app.uid, app.processName, conn.provider.uid,
18542 conn.provider.name);
18543 }
18544 app.conProviders.clear();
18545 }
18546
18547 // At this point there may be remaining entries in mLaunchingProviders
18548 // where we were the only one waiting, so they are no longer of use.
18549 // Look for these and clean up if found.
18550 // XXX Commented out for now. Trying to figure out a way to reproduce
18551 // the actual situation to identify what is actually going on.
18552 if (false) {
18553 for (int i = mLaunchingProviders.size() - 1; i >= 0; i--) {
18554 ContentProviderRecord cpr = mLaunchingProviders.get(i);
18555 if (cpr.connections.size() <= 0 && !cpr.hasExternalProcessHandles()) {
18556 synchronized (cpr) {
18557 cpr.launchingApp = null;
18558 cpr.notifyAll();
18559 }
18560 }
18561 }
18562 }
18563
18564 skipCurrentReceiverLocked(app);
18565
18566 // Unregister any receivers.
18567 for (int i = app.receivers.size() - 1; i >= 0; i--) {
18568 removeReceiverLocked(app.receivers.valueAt(i));
18569 }
18570 app.receivers.clear();
18571
18572 // If the app is undergoing backup, tell the backup manager about it
18573 if (mBackupTarget != null && app.pid == mBackupTarget.app.pid) {
18574 if (DEBUG_BACKUP || DEBUG_CLEANUP) Slog.d(TAG_CLEANUP, "App "
18575 + mBackupTarget.appInfo + " died during backup");
18576 mHandler.post(new Runnable() {
18577 @Override
18578 public void run(){
18579 try {
18580 IBackupManager bm = IBackupManager.Stub.asInterface(
18581 ServiceManager.getService(Context.BACKUP_SERVICE));
18582 bm.agentDisconnected(app.info.packageName);
18583 } catch (RemoteException e) {
18584 // can't happen; backup manager is local
18585 }
18586 }
18587 });
18588 }
18589
18590 for (int i = mPendingProcessChanges.size() - 1; i >= 0; i--) {
18591 ProcessChangeItem item = mPendingProcessChanges.get(i);
18592 if (item.pid == app.pid) {
18593 mPendingProcessChanges.remove(i);
18594 mAvailProcessChanges.add(item);
18595 }
18596 }
18597 mUiHandler.obtainMessage(DISPATCH_PROCESS_DIED_UI_MSG, app.pid, app.info.uid,
18598 null).sendToTarget();
18599
18600 // If the caller is restarting this app, then leave it in its
18601 // current lists and let the caller take care of it.
18602 if (restarting) {
18603 return false;
18604 }
18605
18606 if (!app.persistent || app.isolated) {
18607 if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
18608 "Removing non-persistent process during cleanup: " + app);
18609 if (!replacingPid) {
18610 removeProcessNameLocked(app.processName, app.uid, app);
18611 }
18612 if (mHeavyWeightProcess == app) {
18613 mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG,
18614 mHeavyWeightProcess.userId, 0));
18615 mHeavyWeightProcess = null;
18616 }
18617 } else if (!app.removed) {
18618 // This app is persistent, so we need to keep its record around.
18619 // If it is not already on the pending app list, add it there
18620 // and start a new process for it.
18621 if (mPersistentStartingProcesses.indexOf(app) < 0) {
18622 mPersistentStartingProcesses.add(app);
18623 restart = true;
18624 }
18625 }
18626 if ((DEBUG_PROCESSES || DEBUG_CLEANUP) && mProcessesOnHold.contains(app)) Slog.v(
18627 TAG_CLEANUP, "Clean-up removing on hold: " + app);
18628 mProcessesOnHold.remove(app);
18629
18630 if (app == mHomeProcess) {
18631 mHomeProcess = null;
18632 }
18633 if (app == mPreviousProcess) {
18634 mPreviousProcess = null;
18635 }
18636
18637 if (restart && !app.isolated) {
18638 // We have components that still need to be running in the
18639 // process, so re-launch it.
18640 if (index < 0) {
18641 ProcessList.remove(app.pid);
18642 }
18643 addProcessNameLocked(app);
18644 startProcessLocked(app, "restart", app.processName);
18645 return true;
18646 } else if (app.pid > 0 && app.pid != MY_PID) {
18647 // Goodbye!
18648 boolean removed;
18649 synchronized (mPidsSelfLocked) {
18650 mPidsSelfLocked.remove(app.pid);
18651 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
18652 }
18653 mBatteryStatsService.noteProcessFinish(app.processName, app.info.uid);
18654 if (app.isolated) {
18655 mBatteryStatsService.removeIsolatedUid(app.uid, app.info.uid);
18656 }
18657 app.setPid(0);
18658 }
18659 return false;
18660 }
ActivityManangerService#removeDyingProviderLocked
18402 private final boolean removeDyingProviderLocked(ProcessRecord proc,
18403 ContentProviderRecord cpr, boolean always) {
18404 final boolean inLaunching = mLaunchingProviders.contains(cpr);
18405
18406 if (!inLaunching || always) {
18407 synchronized (cpr) {
18408 cpr.launchingApp = null;
18409 cpr.notifyAll();
18410 }
18411 mProviderMap.removeProviderByClass(cpr.name, UserHandle.getUserId(cpr.uid));
18412 String names[] = cpr.info.authority.split(";");
18413 for (int j = 0; j < names.length; j++) {
18414 mProviderMap.removeProviderByName(names[j], UserHandle.getUserId(cpr.uid));
18415 }
18416 }
//清理AMS中保存的相关ContentProviderRecord
18417
18418 for (int i = cpr.connections.size() - 1; i >= 0; i--) {
//其对应的客户端ContentProviderConnection
18419 ContentProviderConnection conn = cpr.connections.get(i);
18420 if (conn.waiting) {
18421 // If this connection is waiting for the provider, then we don't
18422 // need to mess with its process unless we are always removing
18423 // or for some reason the provider is not currently launching.
18424 if (inLaunching && !always) {
18425 continue;
18426 }
18427 }
//获取到客户端进程
18428 ProcessRecord capp = conn.client;
18429 conn.dead = true;
18430 if (conn.stableCount > 0) {
//这个connection的stable计数大于0才会杀死其客户端
18431 if (!capp.persistent && capp.thread != null
18432 && capp.pid != 0
18433 && capp.pid != MY_PID) {
//如果这个app不是常驻进程且正在运行中,那么会将客户端进程杀掉
18436 capp.kill("depends on provider "
18437 + cpr.name.flattenToShortString()
18438 + " in dying proc " + (proc != null ? proc.processName : "??")
18439 + " (adj " + (proc != null ? proc.setAdj : "??") + ")", true);
18440 }
18441 } else if (capp.thread != null && conn.provider.provider != null) {
18442 try {
//如果stable计数为0,那么调用unstableProviderDied清理客户端缓存即可,无需杀死客户端进程
18443 capp.thread.unstableProviderDied(conn.provider.provider.asBinder());
18444 } catch (RemoteException e) {
18445 }
18446 // In the protocol here, we don't expect the client to correctly
18447 // clean up this connection, we'll just remove it.
18448 cpr.connections.remove(i);
18449 if (conn.client.conProviders.remove(conn)) {
18450 stopAssociationLocked(capp.uid, capp.processName, cpr.uid, cpr.name);
18451 }
18452 }
18453 }
18454
18455 if (inLaunching && always) {
18456 mLaunchingProviders.remove(cpr);
18457 }
18458 return inLaunching;
18459 }
provider中,query操作首次是使用unstableProvider,失败一次后会使用stableProvider;其余insert, update, delete操作直接使用的是stableProvider
联级存在的意义在于保护provider客户端与服务端的数据一致性;因为插入,删除这些操作会涉及到数据更新,所以如果provider出现了异常,为了保证客户端维护的数据是正确了,只能强迫客户端进程直接死亡再重新启动恢复数据
ContentProvider_kill.png
客户端releaseProvider
前面我们已经分析,acquireProvider会增加stable的引用计数,而provider服务端死亡时,如果stable计数大于0,那么provider客户端也会收到波及被杀死。那什么时候会stable的计数会减少呢,答案在releaseProvider这个方法中
触发时机
1.对于query,其返回的Cursor对象,当客户端调用close之后才会调用到releaseProvider
2.对于其他操作,如insert,update;调用过实例对象的函数之后会调用releaseProvider
ContentResolver#releaseProvider->ActivityThread#releaseProvider
6147 public final boolean releaseProvider(IContentProvider provider, boolean stable) {
6148 if (provider == null) {
6149 return false;
6150 }
6151
6152 IBinder jBinder = provider.asBinder();
6153 synchronized (mProviderMap) {
6154 ProviderRefCount prc = mProviderRefCountMap.get(jBinder);
6155 if (prc == null) {
6156 // The provider has no ref count, no release is needed.
6157 return false;
6158 }
6159
6160 boolean lastRef = false;
6161 if (stable) {
6162 if (prc.stableCount == 0) {
6163 if (DEBUG_PROVIDER) Slog.v(TAG,
6164 "releaseProvider: stable ref count already 0, how?");
6165 return false;
6166 }
6167 prc.stableCount -= 1;
//减少客户端保存的引用计数
6168 if (prc.stableCount == 0) {
6169 // What we do at this point depends on whether there are
6170 // any unstable refs left: if there are, we just tell the
6171 // activity manager to decrement its stable count; if there
6172 // aren't, we need to enqueue this provider to be removed,
6173 // and convert to holding a single unstable ref while
6174 // doing so.
6175 lastRef = prc.unstableCount == 0;
6176 try {
6177 if (DEBUG_PROVIDER) {
6178 Slog.v(TAG, "releaseProvider: No longer stable w/lastRef="
6179 + lastRef + " - " + prc.holder.info.name);
6180 }
//减少AMS中的ContentProviderConnection的引用计数
6181 ActivityManager.getService().refContentProvider(
6182 prc.holder.connection, -1, lastRef ? 1 : 0);
6183 } catch (RemoteException e) {
6184 //do nothing content provider object is dead any way
6185 }
6186 }
6187 } else {
6188 if (prc.unstableCount == 0) {
6189 if (DEBUG_PROVIDER) Slog.v(TAG,
6190 "releaseProvider: unstable ref count already 0, how?");
6191 return false;
6192 }
6193 prc.unstableCount -= 1;
6194 if (prc.unstableCount == 0) {
6195 // If this is the last reference, we need to enqueue
6196 // this provider to be removed instead of telling the
6197 // activity manager to remove it at this point.
6198 lastRef = prc.stableCount == 0;
6199 if (!lastRef) {
6200 try {
6201 if (DEBUG_PROVIDER) {
6202 Slog.v(TAG, "releaseProvider: No longer unstable - "
6203 + prc.holder.info.name);
6204 }
6205 ActivityManager.getService().refContentProvider(
6206 prc.holder.connection, 0, -1);
6207 } catch (RemoteException e) {
6208 //do nothing content provider object is dead any way
6209 }
6210 }
6211 }
6212 }
6213
6214 if (lastRef) {
//当stable unstable的引用计数均为0
6215 if (!prc.removePending) {
6216 // Schedule the actual remove asynchronously, since we don't know the context
6217 // this will be called in.
6218 // TODO: it would be nice to post a delayed message, so
6219 // if we come back and need the same provider quickly
6220 // we will still have it available.
6221 if (DEBUG_PROVIDER) {
6222 Slog.v(TAG, "releaseProvider: Enqueueing pending removal - "
6223 + prc.holder.info.name);
6224 }
6225 prc.removePending = true;
6226 Message msg = mH.obtainMessage(H.REMOVE_PROVIDER, prc);
6227 mH.sendMessage(msg);
6228 } else {
6229 Slog.w(TAG, "Duplicate remove pending of provider " + prc.holder.info.name);
6230 }
6231 }
6232 return true;
6233 }
6234 }
ActivityThread相应逻辑
移除客户端缓存中的ProviderRefCount 和ProviderClientRecord,以及AMS缓存中的ContentProviderConnection
1790 case REMOVE_PROVIDER:
1791 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
1792 completeRemoveProvider((ProviderRefCount)msg.obj);
1793 Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
1794 break;
6236 final void completeRemoveProvider(ProviderRefCount prc) {
6237 synchronized (mProviderMap) {
6238 if (!prc.removePending) {
6239 // There was a race! Some other client managed to acquire
6240 // the provider before the removal was completed.
6241 // Abort the removal. We will do it later.
6242 if (DEBUG_PROVIDER) Slog.v(TAG, "completeRemoveProvider: lost the race, "
6243 + "provider still in use");
6244 return;
6245 }
6246
6247 // More complicated race!! Some client managed to acquire the
6248 // provider and release it before the removal was completed.
6249 // Continue the removal, and abort the next remove message.
6250 prc.removePending = false;
6251
6252 final IBinder jBinder = prc.holder.provider.asBinder();
6253 ProviderRefCount existingPrc = mProviderRefCountMap.get(jBinder);
6254 if (existingPrc == prc) {
6255 mProviderRefCountMap.remove(jBinder);
6256 }
6257
6258 for (int i=mProviderMap.size()-1; i>=0; i--) {
6259 ProviderClientRecord pr = mProviderMap.valueAt(i);
6260 IBinder myBinder = pr.mProvider.asBinder();
6261 if (myBinder == jBinder) {
6262 mProviderMap.removeAt(i);
6263 }
6264 }
6265 }
6266
6267 try {
6268 if (DEBUG_PROVIDER) {
6269 Slog.v(TAG, "removeProvider: Invoking ActivityManagerService."
6270 + "removeContentProvider(" + prc.holder.info.name + ")");
6271 }
6272 ActivityManager.getService().removeContentProvider(
6273 prc.holder.connection, false);
6274 } catch (RemoteException e) {
6275 //do nothing content provider object is dead any way
6276 }
6277 }
ActivityMannagerService#removeContentProvider
移除AMS中的ContentProviderConnection,通过复用decProviderCountLocked(减少ContentProviderConnection引用计数,为0时从缓存中移除)
12237 public void removeContentProvider(IBinder connection, boolean stable) {
12238 enforceNotIsolatedCaller("removeContentProvider");
12239 long ident = Binder.clearCallingIdentity();
12240 try {
12241 synchronized (this) {
12242 ContentProviderConnection conn;
12243 try {
12244 conn = (ContentProviderConnection)connection;
12245 } catch (ClassCastException e) {
12246 String msg ="removeContentProvider: " + connection
12247 + " not a ContentProviderConnection";
12248 Slog.w(TAG, msg);
12249 throw new IllegalArgumentException(msg);
12250 }
12251 if (conn == null) {
12252 throw new NullPointerException("connection is null");
12253 }
12254 if (decProviderCountLocked(conn, null, null, stable)) {
12255 updateOomAdjLocked();
12256 }
12257 }
12258 } finally {
12259 Binder.restoreCallingIdentity(ident);
12260 }
12261 }
release逻辑就是减小数据,等stable/unstable refcount均为0,移除客户端和AMS中相应的缓存结构
这里有个特殊的方法:call,它的不同之处在于数据传输的方式。其它的query, insert, update, delete这些操作是使用binder+ashmem结合的方式进行数据传输,而call纯粹使用的是binder进行
网友评论