美文网首页android之基础学习攻克
ContentProvider相关学习(3)-清理相关逻辑

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

作者: weiinter105 | 来源:发表于2018-12-12 15:38 被阅读0次

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

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

    相关文章

      网友评论

        本文标题:ContentProvider相关学习(3)-清理相关逻辑

        本文链接:https://www.haomeiwen.com/subject/qccphqtx.html