Loading services/core/java/com/android/server/am/ContentProviderConnection.java +9 −0 Original line number Diff line number Diff line Loading @@ -265,4 +265,13 @@ public final class ContentProviderConnection extends Binder { return mUnstableCount; } } /** * Returns the total number of stable and unstable references. */ int totalRefCount() { synchronized (mLock) { return mStableCount + mUnstableCount; } } } services/core/java/com/android/server/am/ContentProviderHelper.java +45 −20 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.server.RescueParty; Loading Loading @@ -261,7 +262,8 @@ public class ContentProviderHelper { // doesn't kill our process. Slog.wtf(TAG, "Existing provider " + cpr.name.flattenToShortString() + " is crashing; detaching " + r); boolean lastRef = decProviderCountLocked(conn, cpr, token, stable); boolean lastRef = decProviderCountLocked(conn, cpr, token, stable, false, false); if (!lastRef) { // This wasn't the last ref our process had on // the provider... we will be killed during cleaning up, bail. Loading Loading @@ -697,10 +699,7 @@ public class ContentProviderHelper { if (conn == null) { throw new NullPointerException("connection is null"); } if (decProviderCountLocked(conn, null, null, stable)) { mService.updateOomAdjLocked(conn.provider.proc, OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER); } decProviderCountLocked(conn, null, null, stable, true, true); } } finally { Binder.restoreCallingIdentity(ident); Loading Loading @@ -1275,16 +1274,38 @@ public class ContentProviderHelper { @GuardedBy("mService") private boolean decProviderCountLocked(ContentProviderConnection conn, ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) { ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable, boolean enforceDelay, boolean updateOomAdj) { if (conn == null) { cpr.removeExternalProcessHandleLocked(externalProcessToken); return false; } if (conn.decrementCount(stable) != 0) { if (conn.totalRefCount() > 1) { conn.decrementCount(stable); return false; } if (enforceDelay) { // delay the removal of the provider for 5 seconds - this optimizes for those cases // where providers are released and then quickly re-acquired, causing lots of churn. BackgroundThread.getHandler().postDelayed(() -> { handleProviderRemoval(conn, stable, updateOomAdj); }, 5 * 1000); } else { handleProviderRemoval(conn, stable, updateOomAdj); } return true; } cpr = conn.provider; private void handleProviderRemoval(ContentProviderConnection conn, boolean stable, boolean updateOomAdj) { synchronized (mService) { // if the proc was already killed or this is not the last reference, simply exit. if (conn == null || conn.provider == null || conn.decrementCount(stable) != 0) { return; } final ContentProviderRecord cpr = conn.provider; conn.stopAssociation(); cpr.connections.remove(conn); conn.client.conProviders.remove(conn); Loading @@ -1298,7 +1319,11 @@ public class ContentProviderHelper { } mService.stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName); return true; if (updateOomAdj) { mService.updateOomAdjLocked(conn.provider.proc, OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER); } } } /** Loading Loading
services/core/java/com/android/server/am/ContentProviderConnection.java +9 −0 Original line number Diff line number Diff line Loading @@ -265,4 +265,13 @@ public final class ContentProviderConnection extends Binder { return mUnstableCount; } } /** * Returns the total number of stable and unstable references. */ int totalRefCount() { synchronized (mLock) { return mStableCount + mUnstableCount; } } }
services/core/java/com/android/server/am/ContentProviderHelper.java +45 −20 Original line number Diff line number Diff line Loading @@ -62,6 +62,7 @@ import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.server.RescueParty; Loading Loading @@ -261,7 +262,8 @@ public class ContentProviderHelper { // doesn't kill our process. Slog.wtf(TAG, "Existing provider " + cpr.name.flattenToShortString() + " is crashing; detaching " + r); boolean lastRef = decProviderCountLocked(conn, cpr, token, stable); boolean lastRef = decProviderCountLocked(conn, cpr, token, stable, false, false); if (!lastRef) { // This wasn't the last ref our process had on // the provider... we will be killed during cleaning up, bail. Loading Loading @@ -697,10 +699,7 @@ public class ContentProviderHelper { if (conn == null) { throw new NullPointerException("connection is null"); } if (decProviderCountLocked(conn, null, null, stable)) { mService.updateOomAdjLocked(conn.provider.proc, OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER); } decProviderCountLocked(conn, null, null, stable, true, true); } } finally { Binder.restoreCallingIdentity(ident); Loading Loading @@ -1275,16 +1274,38 @@ public class ContentProviderHelper { @GuardedBy("mService") private boolean decProviderCountLocked(ContentProviderConnection conn, ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable) { ContentProviderRecord cpr, IBinder externalProcessToken, boolean stable, boolean enforceDelay, boolean updateOomAdj) { if (conn == null) { cpr.removeExternalProcessHandleLocked(externalProcessToken); return false; } if (conn.decrementCount(stable) != 0) { if (conn.totalRefCount() > 1) { conn.decrementCount(stable); return false; } if (enforceDelay) { // delay the removal of the provider for 5 seconds - this optimizes for those cases // where providers are released and then quickly re-acquired, causing lots of churn. BackgroundThread.getHandler().postDelayed(() -> { handleProviderRemoval(conn, stable, updateOomAdj); }, 5 * 1000); } else { handleProviderRemoval(conn, stable, updateOomAdj); } return true; } cpr = conn.provider; private void handleProviderRemoval(ContentProviderConnection conn, boolean stable, boolean updateOomAdj) { synchronized (mService) { // if the proc was already killed or this is not the last reference, simply exit. if (conn == null || conn.provider == null || conn.decrementCount(stable) != 0) { return; } final ContentProviderRecord cpr = conn.provider; conn.stopAssociation(); cpr.connections.remove(conn); conn.client.conProviders.remove(conn); Loading @@ -1298,7 +1319,11 @@ public class ContentProviderHelper { } mService.stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid, cpr.appInfo.longVersionCode, cpr.name, cpr.info.processName); return true; if (updateOomAdj) { mService.updateOomAdjLocked(conn.provider.proc, OomAdjuster.OOM_ADJ_REASON_REMOVE_PROVIDER); } } } /** Loading