android之基础学习攻克

ContentProvider相关学习(3)-清理相关逻辑

2018-12-12  本文已影响0人  weiinter105

服务端被杀逻辑-可能触发客户端被杀

当服务端死亡时,如果客户端引用的是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进行

上一篇下一篇

猜你喜欢

热点阅读