diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java index 84ecd24b8c557..d9305acb65e65 100644 --- a/core/java/android/app/ActivityClient.java +++ b/core/java/android/app/ActivityClient.java @@ -451,8 +451,20 @@ public class ActivityClient { return sInstance.get(); } + /** + * If system server has passed the controller interface, store it so the subsequent access can + * speed up. + */ + public static IActivityClientController setActivityClientController( + IActivityClientController activityClientController) { + // No lock because it is no harm to encounter race condition. The thread safe Singleton#get + // will take over that case. + return INTERFACE_SINGLETON.mKnownInstance = activityClientController; + } + private static IActivityClientController getActivityClientController() { - return sActivityClientController.get(); + final IActivityClientController controller = INTERFACE_SINGLETON.mKnownInstance; + return controller != null ? controller : INTERFACE_SINGLETON.get(); } private static final Singleton sInstance = new Singleton() { @@ -462,8 +474,17 @@ public class ActivityClient { } }; - private static final Singleton sActivityClientController = - new Singleton() { + private static final ActivityClientControllerSingleton INTERFACE_SINGLETON = + new ActivityClientControllerSingleton(); + + private static class ActivityClientControllerSingleton + extends Singleton { + /** + * A quick look up to reduce potential extra binder transactions. E.g. getting activity + * task manager from service manager and controller from activity task manager. + */ + IActivityClientController mKnownInstance; + @Override protected IActivityClientController create() { try { @@ -472,5 +493,5 @@ public class ActivityClient { throw e.rethrowFromSystemServer(); } } - }; + } } diff --git a/core/java/android/app/servertransaction/LaunchActivityItem.java b/core/java/android/app/servertransaction/LaunchActivityItem.java index 7f08bfbef2895..3758cb49e2d0e 100644 --- a/core/java/android/app/servertransaction/LaunchActivityItem.java +++ b/core/java/android/app/servertransaction/LaunchActivityItem.java @@ -20,8 +20,10 @@ import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.ActivityClient; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; +import android.app.IActivityClientController; import android.app.ProfilerInfo; import android.app.ResultInfo; import android.compat.annotation.UnsupportedAppUsage; @@ -67,6 +69,11 @@ public class LaunchActivityItem extends ClientTransactionItem { private boolean mIsForward; private ProfilerInfo mProfilerInfo; private IBinder mAssistToken; + /** + * It is only non-null if the process is the first time to launch activity. It is only an + * optimization for quick look up of the interface so the field is ignored for comparison. + */ + private IActivityClientController mActivityClientController; private FixedRotationAdjustments mFixedRotationAdjustments; @Override @@ -74,6 +81,9 @@ public class LaunchActivityItem extends ClientTransactionItem { client.countLaunchingActivities(1); client.updateProcessState(mProcState, false); client.updatePendingConfiguration(mCurConfig); + if (mActivityClientController != null) { + ActivityClient.setActivityClientController(mActivityClientController); + } } @Override @@ -105,14 +115,16 @@ public class LaunchActivityItem extends ClientTransactionItem { String referrer, IVoiceInteractor voiceInteractor, int procState, Bundle state, PersistableBundle persistentState, List pendingResults, List pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo, - IBinder assistToken, FixedRotationAdjustments fixedRotationAdjustments) { + IBinder assistToken, IActivityClientController activityClientController, + FixedRotationAdjustments fixedRotationAdjustments) { LaunchActivityItem instance = ObjectPool.obtain(LaunchActivityItem.class); if (instance == null) { instance = new LaunchActivityItem(); } setValues(instance, intent, ident, info, curConfig, overrideConfig, compatInfo, referrer, voiceInteractor, procState, state, persistentState, pendingResults, - pendingNewIntents, isForward, profilerInfo, assistToken, fixedRotationAdjustments); + pendingNewIntents, isForward, profilerInfo, assistToken, activityClientController, + fixedRotationAdjustments); return instance; } @@ -120,7 +132,7 @@ public class LaunchActivityItem extends ClientTransactionItem { @Override public void recycle() { setValues(this, null, 0, null, null, null, null, null, null, 0, null, null, null, null, - false, null, null, null); + false, null, null, null, null); ObjectPool.recycle(this); } @@ -146,6 +158,7 @@ public class LaunchActivityItem extends ClientTransactionItem { dest.writeBoolean(mIsForward); dest.writeTypedObject(mProfilerInfo, flags); dest.writeStrongBinder(mAssistToken); + dest.writeStrongInterface(mActivityClientController); dest.writeTypedObject(mFixedRotationAdjustments, flags); } @@ -162,6 +175,7 @@ public class LaunchActivityItem extends ClientTransactionItem { in.createTypedArrayList(ReferrerIntent.CREATOR), in.readBoolean(), in.readTypedObject(ProfilerInfo.CREATOR), in.readStrongBinder(), + IActivityClientController.Stub.asInterface(in.readStrongBinder()), in.readTypedObject(FixedRotationAdjustments.CREATOR)); } @@ -266,6 +280,7 @@ public class LaunchActivityItem extends ClientTransactionItem { int procState, Bundle state, PersistableBundle persistentState, List pendingResults, List pendingNewIntents, boolean isForward, ProfilerInfo profilerInfo, IBinder assistToken, + IActivityClientController activityClientController, FixedRotationAdjustments fixedRotationAdjustments) { instance.mIntent = intent; instance.mIdent = ident; @@ -283,6 +298,7 @@ public class LaunchActivityItem extends ClientTransactionItem { instance.mIsForward = isForward; instance.mProfilerInfo = profilerInfo; instance.mAssistToken = assistToken; + instance.mActivityClientController = activityClientController; instance.mFixedRotationAdjustments = fixedRotationAdjustments; } } diff --git a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java index 4654f63a2a911..b2b34d64b12c4 100644 --- a/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/ObjectPoolTests.java @@ -26,6 +26,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; +import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; @@ -43,6 +44,8 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.function.Supplier; + /** * Tests for {@link ObjectPool}. * @@ -144,24 +147,22 @@ public class ObjectPoolTests { persistableBundle.putInt("k", 4); IBinder assistToken = new Binder(); - LaunchActivityItem emptyItem = LaunchActivityItem.obtain(null, 0, null, null, null, null, - null, null, 0, null, null, null, null, false, null, null, null); - LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo, - config(), overrideConfig, compat, referrer, null /* voiceInteractor */, - procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(), - true /* isForward */, null /* profilerInfo */, assistToken, - null /* fixedRotationAdjustments */); + Supplier itemSupplier = () -> new LaunchActivityItemBuilder() + .setIntent(intent).setIdent(ident).setInfo(activityInfo).setCurConfig(config()) + .setOverrideConfig(overrideConfig).setCompatInfo(compat).setReferrer(referrer) + .setProcState(procState).setState(bundle).setPersistentState(persistableBundle) + .setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList()) + .setIsForward(true).setAssistToken(assistToken).build(); + + LaunchActivityItem emptyItem = new LaunchActivityItemBuilder().build(); + LaunchActivityItem item = itemSupplier.get(); assertNotSame(item, emptyItem); assertFalse(item.equals(emptyItem)); item.recycle(); assertEquals(item, emptyItem); - LaunchActivityItem item2 = LaunchActivityItem.obtain(intent, ident, activityInfo, - config(), overrideConfig, compat, referrer, null /* voiceInteractor */, - procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(), - true /* isForward */, null /* profilerInfo */, assistToken, - null /* fixedRotationAdjustments */); + LaunchActivityItem item2 = itemSupplier.get(); assertSame(item, item2); assertFalse(item2.equals(emptyItem)); } diff --git a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java index d125fe790ebac..7e9933c8d9dff 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TestUtils.java +++ b/core/tests/coretests/src/android/app/servertransaction/TestUtils.java @@ -18,11 +18,19 @@ package android.app.servertransaction; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; +import android.app.ProfilerInfo; import android.app.ResultInfo; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.res.CompatibilityInfo; import android.content.res.Configuration; +import android.os.Bundle; +import android.os.IBinder; +import android.os.PersistableBundle; import android.util.MergedConfiguration; +import android.view.DisplayAdjustments.FixedRotationAdjustments; +import com.android.internal.app.IVoiceInteractor; import com.android.internal.content.ReferrerIntent; import java.util.ArrayList; @@ -81,4 +89,117 @@ class TestUtils { return referrerIntents; } + + static class LaunchActivityItemBuilder { + private Intent mIntent; + private int mIdent; + private ActivityInfo mInfo; + private Configuration mCurConfig; + private Configuration mOverrideConfig; + private CompatibilityInfo mCompatInfo; + private String mReferrer; + private IVoiceInteractor mVoiceInteractor; + private int mProcState; + private Bundle mState; + private PersistableBundle mPersistentState; + private List mPendingResults; + private List mPendingNewIntents; + private boolean mIsForward; + private ProfilerInfo mProfilerInfo; + private IBinder mAssistToken; + private FixedRotationAdjustments mFixedRotationAdjustments; + + LaunchActivityItemBuilder setIntent(Intent intent) { + mIntent = intent; + return this; + } + + LaunchActivityItemBuilder setIdent(int ident) { + mIdent = ident; + return this; + } + + LaunchActivityItemBuilder setInfo(ActivityInfo info) { + mInfo = info; + return this; + } + + LaunchActivityItemBuilder setCurConfig(Configuration curConfig) { + mCurConfig = curConfig; + return this; + } + + LaunchActivityItemBuilder setOverrideConfig(Configuration overrideConfig) { + mOverrideConfig = overrideConfig; + return this; + } + + LaunchActivityItemBuilder setCompatInfo(CompatibilityInfo compatInfo) { + mCompatInfo = compatInfo; + return this; + } + + LaunchActivityItemBuilder setReferrer(String referrer) { + mReferrer = referrer; + return this; + } + + LaunchActivityItemBuilder setVoiceInteractor(IVoiceInteractor voiceInteractor) { + mVoiceInteractor = voiceInteractor; + return this; + } + + LaunchActivityItemBuilder setProcState(int procState) { + mProcState = procState; + return this; + } + + LaunchActivityItemBuilder setState(Bundle state) { + mState = state; + return this; + } + + LaunchActivityItemBuilder setPersistentState(PersistableBundle persistentState) { + mPersistentState = persistentState; + return this; + } + + LaunchActivityItemBuilder setPendingResults(List pendingResults) { + mPendingResults = pendingResults; + return this; + } + + LaunchActivityItemBuilder setPendingNewIntents(List pendingNewIntents) { + mPendingNewIntents = pendingNewIntents; + return this; + } + + LaunchActivityItemBuilder setIsForward(boolean isForward) { + mIsForward = isForward; + return this; + } + + LaunchActivityItemBuilder setProfilerInfo(ProfilerInfo profilerInfo) { + mProfilerInfo = profilerInfo; + return this; + } + + LaunchActivityItemBuilder setAssistToken(IBinder assistToken) { + mAssistToken = assistToken; + return this; + } + + LaunchActivityItemBuilder setFixedRotationAdjustments(FixedRotationAdjustments fra) { + mFixedRotationAdjustments = fra; + return this; + } + + LaunchActivityItem build() { + return LaunchActivityItem.obtain(mIntent, mIdent, mInfo, + mCurConfig, mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, + mProcState, mState, mPersistentState, mPendingResults, mPendingNewIntents, + mIsForward, mProfilerInfo, mAssistToken, null /* activityClientController */, + mFixedRotationAdjustments); + } + } } diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java index 0ae789af477c1..32f892924ac5b 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java @@ -41,6 +41,7 @@ import android.app.Activity; import android.app.ActivityThread.ActivityClientRecord; import android.app.ClientTransactionHandler; import android.app.servertransaction.ActivityLifecycleItem.LifecycleState; +import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder; import android.os.IBinder; import android.os.Parcel; import android.os.Parcelable; @@ -263,13 +264,7 @@ public class TransactionExecutorTests { // A previous queued launch transaction runs on main thread (execute). final ClientTransaction launchTransaction = ClientTransaction.obtain(null /* client */, token /* activityToken */); - final LaunchActivityItem launchItem = spy(LaunchActivityItem.obtain( - null /* intent */, 0 /* ident */, null /* info */, null /* curConfig */, - null, /* overrideConfig */ null /* compatInfo */, null /* referrer */ , - null /* voiceInteractor */, 0 /* procState */, null /* state */, - null /* persistentState */, null /* pendingResults */, - null /* pendingNewIntents */, false /* isForward */, null /* profilerInfo */, - null /* assistToken */, null /* fixedRotationAdjustments */)); + final LaunchActivityItem launchItem = spy(new LaunchActivityItemBuilder().build()); launchTransaction.addCallback(launchItem); mExecutor.execute(launchTransaction); diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java index 7e992989426d6..e1c7146908d67 100644 --- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java +++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java @@ -29,6 +29,7 @@ import android.app.IApplicationThread; import android.app.IInstrumentationWatcher; import android.app.IUiAutomationConnection; import android.app.ProfilerInfo; +import android.app.servertransaction.TestUtils.LaunchActivityItemBuilder; import android.content.AutofillOptions; import android.content.ComponentName; import android.content.ContentCaptureOptions; @@ -195,11 +196,14 @@ public class TransactionParcelTests { FixedRotationAdjustments fixedRotationAdjustments = new FixedRotationAdjustments( Surface.ROTATION_90, 1920, 1080, DisplayCutout.NO_CUTOUT); - LaunchActivityItem item = LaunchActivityItem.obtain(intent, ident, activityInfo, - config(), overrideConfig, compat, referrer, null /* voiceInteractor */, - procState, bundle, persistableBundle, resultInfoList(), referrerIntentList(), - true /* isForward */, null /* profilerInfo */, new Binder(), - fixedRotationAdjustments); + LaunchActivityItem item = new LaunchActivityItemBuilder() + .setIntent(intent).setIdent(ident).setInfo(activityInfo).setCurConfig(config()) + .setOverrideConfig(overrideConfig).setCompatInfo(compat).setReferrer(referrer) + .setProcState(procState).setState(bundle).setPersistentState(persistableBundle) + .setPendingResults(resultInfoList()).setPendingNewIntents(referrerIntentList()) + .setIsForward(true).setAssistToken(new Binder()) + .setFixedRotationAdjustments(fixedRotationAdjustments).build(); + writeAndPrepareForReading(item); // Read from parcel and assert diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index 73d99724c65ff..370ee265bc007 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -88,6 +88,7 @@ import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.ActivityOptions; import android.app.AppOpsManager; +import android.app.IActivityClientController; import android.app.ProfilerInfo; import android.app.ResultInfo; import android.app.WaitResult; @@ -795,6 +796,11 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { + " old=" + r.app + " new=" + proc); } + // Send the controller to client if the process is the first time to launch activity. + // So the client can save binder transactions of getting the controller from activity + // task manager service. + final IActivityClientController activityClientController = + proc.hasEverLaunchedActivity() ? null : mService.mActivityClientController; r.launchCount++; r.lastLaunchTime = SystemClock.uptimeMillis(); proc.setLastActivityLaunchTime(r.lastLaunchTime); @@ -863,7 +869,8 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { r.launchedFromPackage, task.voiceInteractor, proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(), results, newIntents, dc.isNextTransitionForward(), proc.createProfilerInfoIfNeeded(), - r.assistToken, r.createFixedRotationAdjustmentsIfNeeded())); + r.assistToken, activityClientController, + r.createFixedRotationAdjustmentsIfNeeded())); // Set desired final state. final ActivityLifecycleItem lifecycleItem; diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java index 8f8fea34e620f..f3fa978f35dc6 100644 --- a/services/core/java/com/android/server/wm/WindowProcessController.java +++ b/services/core/java/com/android/server/wm/WindowProcessController.java @@ -463,6 +463,10 @@ public class WindowProcessController extends ConfigurationContainer 0; + } + void setLastActivityLaunchTime(long launchTime) { if (launchTime <= mLastActivityLaunchTime) { if (launchTime < mLastActivityLaunchTime) {