Merge "Eliminate acquiring WM lock when bind/unbind service" into tm-qpr-dev am: db4b9c58b9 am: 22280a131e

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21537113

Change-Id: I581f35cbb49f53e2dc79f7790114b72b2bfd53ca
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Riddle Hsu
2023-02-23 08:50:41 +00:00
committed by Automerger Merge Worker
5 changed files with 83 additions and 41 deletions

View File

@@ -344,6 +344,7 @@ import android.window.TransitionInfo.AnimationOptions;
import android.window.WindowContainerToken;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
@@ -508,7 +509,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
private RemoteTransition mPendingRemoteTransition;
ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
@GuardedBy("this")
ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
/** @see android.content.Context#BIND_ADJUST_WITH_ACTIVITY */
volatile boolean mVisibleForServiceConnection;
UriPermissionOwner uriPermissions; // current special URI access perms.
WindowProcessController app; // if non-null, hosting application
private State mState; // current state we are in
@@ -557,7 +561,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
long lastLaunchTime; // time of last launch of this activity
ComponentName requestedVrComponent; // the requested component for handling VR mode.
boolean inHistory; // are we in the history task?
/** Whether this activity is reachable from hierarchy. */
volatile boolean inHistory;
final ActivityTaskSupervisor mTaskSupervisor;
final RootWindowContainer mRootWindowContainer;
@@ -1917,7 +1922,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
}
static @Nullable ActivityRecord forTokenLocked(IBinder token) {
/** Gets the corresponding record by the token. Note that it may not exist in the hierarchy. */
@Nullable
static ActivityRecord forToken(IBinder token) {
if (token == null) return null;
final Token activityToken;
try {
@@ -1926,7 +1933,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
Slog.w(TAG, "Bad activity token: " + token, e);
return null;
}
final ActivityRecord r = activityToken.mActivityRef.get();
return activityToken.mActivityRef.get();
}
static @Nullable ActivityRecord forTokenLocked(IBinder token) {
final ActivityRecord r = forToken(token);
return r == null || r.getRootTask() == null ? null : r;
}
@@ -4059,17 +4070,32 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mDisplayContent.getDisplayPolicy().removeRelaunchingApp(this);
}
ActivityServiceConnectionsHolder getOrCreateServiceConnectionsHolder() {
synchronized (this) {
if (mServiceConnectionsHolder == null) {
mServiceConnectionsHolder = new ActivityServiceConnectionsHolder(this);
}
return mServiceConnectionsHolder;
}
}
/**
* Perform clean-up of service connections in an activity record.
*/
private void cleanUpActivityServices() {
if (mServiceConnectionsHolder == null) {
return;
synchronized (this) {
if (mServiceConnectionsHolder == null) {
return;
}
// Throw away any services that have been bound by this activity.
mServiceConnectionsHolder.disconnectActivityFromServices();
// This activity record is removing, make sure not to disconnect twice.
mServiceConnectionsHolder = null;
}
// Throw away any services that have been bound by this activity.
mServiceConnectionsHolder.disconnectActivityFromServices();
// This activity record is removing, make sure not to disconnect twice.
mServiceConnectionsHolder = null;
}
private void updateVisibleForServiceConnection() {
mVisibleForServiceConnection = mVisibleRequested || mState == RESUMED || mState == PAUSING;
}
/**
@@ -5155,6 +5181,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean setVisibleRequested(boolean visible) {
if (!super.setVisibleRequested(visible)) return false;
setInsetsFrozen(!visible);
updateVisibleForServiceConnection();
if (app != null) {
mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */);
}
@@ -5660,6 +5687,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return;
}
}
updateVisibleForServiceConnection();
if (app != null) {
mTaskSupervisor.onProcessActivityStateChanged(app, false /* forceBatch */);
}

View File

@@ -16,14 +16,14 @@
package com.android.server.wm;
import static com.android.server.wm.ActivityRecord.State.PAUSING;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
import java.util.function.Consumer;
@@ -38,8 +38,6 @@ import java.util.function.Consumer;
*/
public class ActivityServiceConnectionsHolder<T> {
private final ActivityTaskManagerService mService;
/** The activity the owns this service connection object. */
private final ActivityRecord mActivity;
@@ -49,19 +47,19 @@ public class ActivityServiceConnectionsHolder<T> {
* on the WM side since we don't perform operations on the object. Mainly here for communication
* and booking with the AM side.
*/
@GuardedBy("mActivity")
private ArraySet<T> mConnections;
/** Whether all connections of {@link #mActivity} are being removed. */
private volatile boolean mIsDisconnecting;
ActivityServiceConnectionsHolder(ActivityTaskManagerService service, ActivityRecord activity) {
mService = service;
ActivityServiceConnectionsHolder(ActivityRecord activity) {
mActivity = activity;
}
/** Adds a connection record that the activity has bound to a specific service. */
public void addConnection(T c) {
synchronized (mService.mGlobalLock) {
synchronized (mActivity) {
if (mIsDisconnecting) {
// This is unlikely to happen because the caller should create a new holder.
if (DEBUG_CLEANUP) {
@@ -79,7 +77,7 @@ public class ActivityServiceConnectionsHolder<T> {
/** Removed a connection record between the activity and a specific service. */
public void removeConnection(T c) {
synchronized (mService.mGlobalLock) {
synchronized (mActivity) {
if (mConnections == null) {
return;
}
@@ -90,20 +88,18 @@ public class ActivityServiceConnectionsHolder<T> {
}
}
/** @see android.content.Context#BIND_ADJUST_WITH_ACTIVITY */
public boolean isActivityVisible() {
synchronized (mService.mGlobalLock) {
return mActivity.isVisibleRequested() || mActivity.isState(RESUMED, PAUSING);
}
return mActivity.mVisibleForServiceConnection;
}
public int getActivityPid() {
synchronized (mService.mGlobalLock) {
return mActivity.hasProcess() ? mActivity.app.getPid() : -1;
}
final WindowProcessController wpc = mActivity.app;
return wpc != null ? wpc.getPid() : -1;
}
public void forEachConnection(Consumer<T> consumer) {
synchronized (mService.mGlobalLock) {
synchronized (mActivity) {
if (mConnections == null || mConnections.isEmpty()) {
return;
}
@@ -118,6 +114,7 @@ public class ActivityServiceConnectionsHolder<T> {
* general, this method is used to clean up if the activity didn't unbind services before it
* is destroyed.
*/
@GuardedBy("mActivity")
void disconnectActivityFromServices() {
if (mConnections == null || mConnections.isEmpty() || mIsDisconnecting) {
return;
@@ -130,16 +127,14 @@ public class ActivityServiceConnectionsHolder<T> {
// still in the message queue, so keep the reference of {@link #mConnections} to make sure
// the connection list is up-to-date.
mIsDisconnecting = true;
mService.mH.post(() -> {
mService.mAmInternal.disconnectActivityFromServices(this);
mActivity.mAtmService.mH.post(() -> {
mActivity.mAtmService.mAmInternal.disconnectActivityFromServices(this);
mIsDisconnecting = false;
});
}
public void dump(PrintWriter pw, String prefix) {
synchronized (mService.mGlobalLock) {
pw.println(prefix + "activity=" + mActivity);
}
pw.println(prefix + "activity=" + mActivity);
}
/** Used by {@link ActivityRecord#dump}. */

View File

@@ -6081,18 +6081,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public ActivityServiceConnectionsHolder getServiceConnectionsHolder(IBinder token) {
synchronized (mGlobalLock) {
final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
if (r == null) {
return null;
}
if (r.mServiceConnectionsHolder == null) {
r.mServiceConnectionsHolder = new ActivityServiceConnectionsHolder(
ActivityTaskManagerService.this, r);
}
return r.mServiceConnectionsHolder;
final ActivityRecord r = ActivityRecord.forToken(token);
if (r == null || !r.inHistory) {
return null;
}
return r.getOrCreateServiceConnectionsHolder();
}
@Override

View File

@@ -1933,7 +1933,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
1f);
mBackScreenshots.put(r.mActivityComponent.flattenToString(), backBuffer);
}
child.asActivityRecord().inHistory = true;
addingActivity.inHistory = true;
task.onDescendantActivityAdded(taskHadActivity, activityType, addingActivity);
}
}

View File

@@ -2323,6 +2323,32 @@ public class ActivityRecordTests extends WindowTestsBase {
assertTrue(activity.pictureInPictureArgs.isLaunchIntoPip());
}
@Test
public void testActivityServiceConnectionsHolder() {
final ActivityRecord activity = new ActivityBuilder(mAtm).setCreateTask(true).build();
final ActivityServiceConnectionsHolder<Object> holder =
mAtm.mInternal.getServiceConnectionsHolder(activity.token);
assertNotNull(holder);
final Object connection = new Object();
holder.addConnection(connection);
assertTrue(holder.isActivityVisible());
final int[] count = new int[1];
final Consumer<Object> c = conn -> count[0]++;
holder.forEachConnection(c);
assertEquals(1, count[0]);
holder.removeConnection(connection);
holder.forEachConnection(c);
assertEquals(1, count[0]);
activity.setVisibleRequested(false);
activity.setState(STOPPED, "test");
assertFalse(holder.isActivityVisible());
activity.removeImmediately();
assertNull(mAtm.mInternal.getServiceConnectionsHolder(activity.token));
}
@Test
public void testTransferLaunchCookieWhenFinishing() {
final ActivityRecord activity1 = createActivityWithTask();