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:
@@ -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 */);
|
||||
}
|
||||
|
||||
@@ -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}. */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user