Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -3802,6 +3802,7 @@ package android.app { method @Deprecated public void onStateNotSaved(); method @CallSuper protected void onStop(); method protected void onTitleChanged(CharSequence, int); method public void onTopResumedActivityChanged(boolean); method public boolean onTouchEvent(android.view.MotionEvent); method public boolean onTrackballEvent(android.view.MotionEvent); method public void onTrimMemory(int); core/java/android/app/Activity.java +23 −0 Original line number Diff line number Diff line Loading @@ -1808,6 +1808,29 @@ public class Activity extends ContextThemeWrapper mCalled = true; } /** * Called when activity gets or looses the top resumed position in the system. * * <p>Starting with {@link android.os.Build.VERSION_CODES#Q} multiple activities can be resumed * at the same time in multi-window and multi-display modes. This callback should be used * instead of {@link #onResume()} as an indication that the activity can try to open * exclusive-access devices like camera.</p> * * <p>It will always be delivered after the activity was resumed and before it is paused. In * some cases it might be skipped and activity can go straight from {@link #onResume()} to * {@link #onPause()} without receiving the top resumed state.</p> * * @param isTopResumedActivity {@code true} if it's the topmost resumed activity in the system, * {@code false} otherwise. A call with this as {@code true} will * always be followed by another one with {@code false}. * * @see #onResume() * @see #onPause() * @see #onWindowFocusChanged(boolean) */ public void onTopResumedActivityChanged(boolean isTopResumedActivity) { } void setVoiceInteractor(IVoiceInteractor voiceInteractor) { if (mVoiceInteractor != null) { for (Request activeRequest: mVoiceInteractor.getActiveRequests()) { Loading core/java/android/app/ActivityThread.java +56 −5 Original line number Diff line number Diff line Loading @@ -449,6 +449,14 @@ public final class ActivityThread extends ClientTransactionHandler { ViewRootImpl.ActivityConfigCallback configCallback; ActivityClientRecord nextIdle; // Indicates whether this activity is currently the topmost resumed one in the system. // This holds the last reported value from server. boolean isTopResumedActivity; // This holds the value last sent to the activity. This is needed, because an update from // server may come at random time, but we always need to report changes between ON_RESUME // and ON_PAUSE to the app. boolean lastReportedTopResumedState; ProfilerInfo profilerInfo; @UnsupportedAppUsage Loading Loading @@ -3295,16 +3303,14 @@ public final class ActivityThread extends ClientTransactionHandler { final boolean resumed = !r.paused; if (resumed) { r.activity.mTemporaryPause = true; mInstrumentation.callActivityOnPause(r.activity); performPauseActivityIfNeeded(r, "performNewIntents"); } checkAndBlockForNetworkAccess(); deliverNewIntents(r, intents); if (resumed) { r.activity.performResume(false, "performNewIntents"); performResumeActivity(token, false, "performNewIntents"); r.activity.mTemporaryPause = false; } if (r.paused && andPause) { } else if (andPause) { // In this case the activity was in the paused state when we delivered the intent, // to guarantee onResume gets called after onNewIntent we temporarily resume the // activity and pause again as the caller wanted. Loading Loading @@ -3957,6 +3963,8 @@ public final class ActivityThread extends ClientTransactionHandler { r.state = null; r.persistentState = null; r.setState(ON_RESUME); reportTopResumedActivityChanged(r, r.isTopResumedActivity); } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException("Unable to resume activity " Loading Loading @@ -4111,6 +4119,45 @@ public final class ActivityThread extends ClientTransactionHandler { Looper.myQueue().addIdleHandler(new Idler()); } @Override public void handleTopResumedActivityChanged(IBinder token, boolean onTop, String reason) { ActivityClientRecord r = mActivities.get(token); if (r == null || r.activity == null) { Slog.w(TAG, "Not found target activity to report position change for token: " + token); return; } if (DEBUG_ORDER) { Slog.d(TAG, "Received position change to top: " + onTop + " for activity: " + r); } if (r.isTopResumedActivity == onTop) { throw new IllegalStateException("Activity top position already set to onTop=" + onTop); } r.isTopResumedActivity = onTop; if (r.getLifecycleState() == ON_RESUME) { reportTopResumedActivityChanged(r, onTop); } else { if (DEBUG_ORDER) { Slog.d(TAG, "Won't deliver top position change in state=" + r.getLifecycleState()); } } } /** * Call {@link Activity#onTopResumedActivityChanged(boolean)} if its top resumed state changed * since the last report. */ private void reportTopResumedActivityChanged(ActivityClientRecord r, boolean onTop) { if (r.lastReportedTopResumedState != onTop) { r.lastReportedTopResumedState = onTop; r.activity.onTopResumedActivityChanged(onTop); } } @Override public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, PendingTransactionActions pendingActions, String reason) { Loading Loading @@ -4202,6 +4249,10 @@ public final class ActivityThread extends ClientTransactionHandler { return; } // Always reporting top resumed position loss when pausing an activity. If necessary, it // will be restored in performResumeActivity(). reportTopResumedActivityChanged(r, false /* onTop */); try { r.activity.mCalled = false; mInstrumentation.callActivityOnPause(r.activity); Loading core/java/android/app/ClientTransactionHandler.java +10 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,16 @@ public abstract class ClientTransactionHandler { public abstract void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason); /** * Notify the activity about top resumed state change. * @param token Target activity token. * @param isTopResumedActivity Current state of the activity, {@code true} if it's the * topmost resumed activity in the system, {@code false} otherwise. * @param reason Reason for performing this operation. */ public abstract void handleTopResumedActivityChanged(IBinder token, boolean isTopResumedActivity, String reason); /** * Stop the activity. * @param token Target activity token. Loading core/java/android/app/servertransaction/TopResumedActivityChangeItem.java 0 → 100644 +112 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.servertransaction; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import android.app.ClientTransactionHandler; import android.os.IBinder; import android.os.Parcel; import android.os.Trace; /** * Top resumed activity changed callback. * @hide */ public class TopResumedActivityChangeItem extends ClientTransactionItem { private boolean mOnTop; @Override public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "topResumedActivityChangeItem"); client.handleTopResumedActivityChanged(token, mOnTop, "topResumedActivityChangeItem"); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } // ObjectPoolItem implementation private TopResumedActivityChangeItem() {} /** Obtain an instance initialized with provided params. */ public static TopResumedActivityChangeItem obtain(boolean onTop) { TopResumedActivityChangeItem instance = ObjectPool.obtain(TopResumedActivityChangeItem.class); if (instance == null) { instance = new TopResumedActivityChangeItem(); } instance.mOnTop = onTop; return instance; } @Override public void recycle() { mOnTop = false; ObjectPool.recycle(this); } // Parcelable implementation /** Write to Parcel. */ @Override public void writeToParcel(Parcel dest, int flags) { dest.writeBoolean(mOnTop); } /** Read from Parcel. */ private TopResumedActivityChangeItem(Parcel in) { mOnTop = in.readBoolean(); } public static final Creator<TopResumedActivityChangeItem> CREATOR = new Creator<TopResumedActivityChangeItem>() { public TopResumedActivityChangeItem createFromParcel(Parcel in) { return new TopResumedActivityChangeItem(in); } public TopResumedActivityChangeItem[] newArray(int size) { return new TopResumedActivityChangeItem[size]; } }; @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } final TopResumedActivityChangeItem other = (TopResumedActivityChangeItem) o; return mOnTop == other.mOnTop; } @Override public int hashCode() { int result = 17; result = 31 * result + (mOnTop ? 1 : 0); return result; } @Override public String toString() { return "TopResumedActivityChangeItem{onTop=" + mOnTop + "}"; } } Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -3802,6 +3802,7 @@ package android.app { method @Deprecated public void onStateNotSaved(); method @CallSuper protected void onStop(); method protected void onTitleChanged(CharSequence, int); method public void onTopResumedActivityChanged(boolean); method public boolean onTouchEvent(android.view.MotionEvent); method public boolean onTrackballEvent(android.view.MotionEvent); method public void onTrimMemory(int);
core/java/android/app/Activity.java +23 −0 Original line number Diff line number Diff line Loading @@ -1808,6 +1808,29 @@ public class Activity extends ContextThemeWrapper mCalled = true; } /** * Called when activity gets or looses the top resumed position in the system. * * <p>Starting with {@link android.os.Build.VERSION_CODES#Q} multiple activities can be resumed * at the same time in multi-window and multi-display modes. This callback should be used * instead of {@link #onResume()} as an indication that the activity can try to open * exclusive-access devices like camera.</p> * * <p>It will always be delivered after the activity was resumed and before it is paused. In * some cases it might be skipped and activity can go straight from {@link #onResume()} to * {@link #onPause()} without receiving the top resumed state.</p> * * @param isTopResumedActivity {@code true} if it's the topmost resumed activity in the system, * {@code false} otherwise. A call with this as {@code true} will * always be followed by another one with {@code false}. * * @see #onResume() * @see #onPause() * @see #onWindowFocusChanged(boolean) */ public void onTopResumedActivityChanged(boolean isTopResumedActivity) { } void setVoiceInteractor(IVoiceInteractor voiceInteractor) { if (mVoiceInteractor != null) { for (Request activeRequest: mVoiceInteractor.getActiveRequests()) { Loading
core/java/android/app/ActivityThread.java +56 −5 Original line number Diff line number Diff line Loading @@ -449,6 +449,14 @@ public final class ActivityThread extends ClientTransactionHandler { ViewRootImpl.ActivityConfigCallback configCallback; ActivityClientRecord nextIdle; // Indicates whether this activity is currently the topmost resumed one in the system. // This holds the last reported value from server. boolean isTopResumedActivity; // This holds the value last sent to the activity. This is needed, because an update from // server may come at random time, but we always need to report changes between ON_RESUME // and ON_PAUSE to the app. boolean lastReportedTopResumedState; ProfilerInfo profilerInfo; @UnsupportedAppUsage Loading Loading @@ -3295,16 +3303,14 @@ public final class ActivityThread extends ClientTransactionHandler { final boolean resumed = !r.paused; if (resumed) { r.activity.mTemporaryPause = true; mInstrumentation.callActivityOnPause(r.activity); performPauseActivityIfNeeded(r, "performNewIntents"); } checkAndBlockForNetworkAccess(); deliverNewIntents(r, intents); if (resumed) { r.activity.performResume(false, "performNewIntents"); performResumeActivity(token, false, "performNewIntents"); r.activity.mTemporaryPause = false; } if (r.paused && andPause) { } else if (andPause) { // In this case the activity was in the paused state when we delivered the intent, // to guarantee onResume gets called after onNewIntent we temporarily resume the // activity and pause again as the caller wanted. Loading Loading @@ -3957,6 +3963,8 @@ public final class ActivityThread extends ClientTransactionHandler { r.state = null; r.persistentState = null; r.setState(ON_RESUME); reportTopResumedActivityChanged(r, r.isTopResumedActivity); } catch (Exception e) { if (!mInstrumentation.onException(r.activity, e)) { throw new RuntimeException("Unable to resume activity " Loading Loading @@ -4111,6 +4119,45 @@ public final class ActivityThread extends ClientTransactionHandler { Looper.myQueue().addIdleHandler(new Idler()); } @Override public void handleTopResumedActivityChanged(IBinder token, boolean onTop, String reason) { ActivityClientRecord r = mActivities.get(token); if (r == null || r.activity == null) { Slog.w(TAG, "Not found target activity to report position change for token: " + token); return; } if (DEBUG_ORDER) { Slog.d(TAG, "Received position change to top: " + onTop + " for activity: " + r); } if (r.isTopResumedActivity == onTop) { throw new IllegalStateException("Activity top position already set to onTop=" + onTop); } r.isTopResumedActivity = onTop; if (r.getLifecycleState() == ON_RESUME) { reportTopResumedActivityChanged(r, onTop); } else { if (DEBUG_ORDER) { Slog.d(TAG, "Won't deliver top position change in state=" + r.getLifecycleState()); } } } /** * Call {@link Activity#onTopResumedActivityChanged(boolean)} if its top resumed state changed * since the last report. */ private void reportTopResumedActivityChanged(ActivityClientRecord r, boolean onTop) { if (r.lastReportedTopResumedState != onTop) { r.lastReportedTopResumedState = onTop; r.activity.onTopResumedActivityChanged(onTop); } } @Override public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, PendingTransactionActions pendingActions, String reason) { Loading Loading @@ -4202,6 +4249,10 @@ public final class ActivityThread extends ClientTransactionHandler { return; } // Always reporting top resumed position loss when pausing an activity. If necessary, it // will be restored in performResumeActivity(). reportTopResumedActivityChanged(r, false /* onTop */); try { r.activity.mCalled = false; mInstrumentation.callActivityOnPause(r.activity); Loading
core/java/android/app/ClientTransactionHandler.java +10 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,16 @@ public abstract class ClientTransactionHandler { public abstract void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward, String reason); /** * Notify the activity about top resumed state change. * @param token Target activity token. * @param isTopResumedActivity Current state of the activity, {@code true} if it's the * topmost resumed activity in the system, {@code false} otherwise. * @param reason Reason for performing this operation. */ public abstract void handleTopResumedActivityChanged(IBinder token, boolean isTopResumedActivity, String reason); /** * Stop the activity. * @param token Target activity token. Loading
core/java/android/app/servertransaction/TopResumedActivityChangeItem.java 0 → 100644 +112 −0 Original line number Diff line number Diff line /* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.servertransaction; import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER; import android.app.ClientTransactionHandler; import android.os.IBinder; import android.os.Parcel; import android.os.Trace; /** * Top resumed activity changed callback. * @hide */ public class TopResumedActivityChangeItem extends ClientTransactionItem { private boolean mOnTop; @Override public void execute(ClientTransactionHandler client, IBinder token, PendingTransactionActions pendingActions) { Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "topResumedActivityChangeItem"); client.handleTopResumedActivityChanged(token, mOnTop, "topResumedActivityChangeItem"); Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER); } // ObjectPoolItem implementation private TopResumedActivityChangeItem() {} /** Obtain an instance initialized with provided params. */ public static TopResumedActivityChangeItem obtain(boolean onTop) { TopResumedActivityChangeItem instance = ObjectPool.obtain(TopResumedActivityChangeItem.class); if (instance == null) { instance = new TopResumedActivityChangeItem(); } instance.mOnTop = onTop; return instance; } @Override public void recycle() { mOnTop = false; ObjectPool.recycle(this); } // Parcelable implementation /** Write to Parcel. */ @Override public void writeToParcel(Parcel dest, int flags) { dest.writeBoolean(mOnTop); } /** Read from Parcel. */ private TopResumedActivityChangeItem(Parcel in) { mOnTop = in.readBoolean(); } public static final Creator<TopResumedActivityChangeItem> CREATOR = new Creator<TopResumedActivityChangeItem>() { public TopResumedActivityChangeItem createFromParcel(Parcel in) { return new TopResumedActivityChangeItem(in); } public TopResumedActivityChangeItem[] newArray(int size) { return new TopResumedActivityChangeItem[size]; } }; @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } final TopResumedActivityChangeItem other = (TopResumedActivityChangeItem) o; return mOnTop == other.mOnTop; } @Override public int hashCode() { int result = 17; result = 31 * result + (mOnTop ? 1 : 0); return result; } @Override public String toString() { return "TopResumedActivityChangeItem{onTop=" + mOnTop + "}"; } }