Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f7247f5 authored by Wei Sheng Shih's avatar Wei Sheng Shih Committed by Android (Google) Code Review
Browse files

Merge "Supporting more non-default close activity callback for PB" into main

parents 126c0f33 1f38d0f0
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -62048,6 +62048,11 @@ package android.window {
    method public void markSyncReady();
  }
  @FlaggedApi("com.android.window.flags.predictive_back_system_override_callback") public final class SystemOnBackInvokedCallbacks {
    method @FlaggedApi("com.android.window.flags.predictive_back_system_override_callback") @NonNull public static android.window.OnBackInvokedCallback finishAndRemoveTaskCallback(@NonNull android.app.Activity);
    method @FlaggedApi("com.android.window.flags.predictive_back_system_override_callback") @NonNull public static android.window.OnBackInvokedCallback moveTaskToBackCallback(@NonNull android.app.Activity);
  }
  @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public final class TrustedPresentationThresholds implements android.os.Parcelable {
    ctor @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public TrustedPresentationThresholds(@FloatRange(from=0.0f, fromInclusive=false, to=1.0f) float, @FloatRange(from=0.0f, fromInclusive=false, to=1.0f) float, @IntRange(from=1) int);
    method @FlaggedApi("com.android.window.flags.trusted_presentation_listener_for_window") public int describeContents();
+16 −2
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.window;

import static android.window.SystemOverrideOnBackInvokedCallback.OVERRIDE_UNDEFINED;

import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
@@ -29,19 +31,23 @@ public final class OnBackInvokedCallbackInfo implements Parcelable {
    private final IOnBackInvokedCallback mCallback;
    private @OnBackInvokedDispatcher.Priority int mPriority;
    private final boolean mIsAnimationCallback;
    private final @SystemOverrideOnBackInvokedCallback.OverrideBehavior int mOverrideBehavior;

    public OnBackInvokedCallbackInfo(@NonNull IOnBackInvokedCallback callback,
            int priority,
            boolean isAnimationCallback) {
            boolean isAnimationCallback,
            int overrideBehavior) {
        mCallback = callback;
        mPriority = priority;
        mIsAnimationCallback = isAnimationCallback;
        mOverrideBehavior = overrideBehavior;
    }

    private OnBackInvokedCallbackInfo(@NonNull Parcel in) {
        mCallback = IOnBackInvokedCallback.Stub.asInterface(in.readStrongBinder());
        mPriority = in.readInt();
        mIsAnimationCallback = in.readBoolean();
        mOverrideBehavior = in.readInt();
    }

    @Override
@@ -54,6 +60,7 @@ public final class OnBackInvokedCallbackInfo implements Parcelable {
        dest.writeStrongInterface(mCallback);
        dest.writeInt(mPriority);
        dest.writeBoolean(mIsAnimationCallback);
        dest.writeInt(mOverrideBehavior);
    }

    public static final Creator<OnBackInvokedCallbackInfo> CREATOR =
@@ -70,7 +77,8 @@ public final class OnBackInvokedCallbackInfo implements Parcelable {
            };

    public boolean isSystemCallback() {
        return mPriority == OnBackInvokedDispatcher.PRIORITY_SYSTEM;
        return mPriority == OnBackInvokedDispatcher.PRIORITY_SYSTEM
                || mOverrideBehavior != OVERRIDE_UNDEFINED;
    }

    @NonNull
@@ -87,12 +95,18 @@ public final class OnBackInvokedCallbackInfo implements Parcelable {
        return mIsAnimationCallback;
    }

    @SystemOverrideOnBackInvokedCallback.OverrideBehavior
    public int getOverrideBehavior() {
        return mOverrideBehavior;
    }

    @Override
    public String toString() {
        return "OnBackInvokedCallbackInfo{"
                + "mCallback=" + mCallback
                + ", mPriority=" + mPriority
                + ", mIsAnimationCallback=" + mIsAnimationCallback
                + ", mOverrideBehavior=" + mOverrideBehavior
                + '}';
    }
}
+168 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.window;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.app.Activity;
import android.util.ArrayMap;

import com.android.window.flags.Flags;

import java.lang.ref.WeakReference;

/**
 * Utility class providing {@link OnBackInvokedCallback}s to override the default behavior when
 * system back is invoked. e.g. {@link Activity#finish}
 *
 * <p>By registering these callbacks with the {@link OnBackInvokedDispatcher}, the system can
 * trigger specific behaviors and play corresponding ahead-of-time animations when the back
 * gesture is invoked.
 *
 * <p>For example, to trigger the {@link Activity#moveTaskToBack} behavior:
 * <pre>
 *   OnBackInvokedDispatcher dispatcher = activity.getOnBackInvokedDispatcher();
 *   dispatcher.registerOnBackInvokedCallback(
 *       OnBackInvokedDispatcher.PRIORITY_DEFAULT,
 *       SystemOnBackInvokedCallbacks.moveTaskToBackCallback(activity));
 * </pre>
 */
@SuppressWarnings("SingularCallback")
@FlaggedApi(Flags.FLAG_PREDICTIVE_BACK_SYSTEM_OVERRIDE_CALLBACK)
public final class SystemOnBackInvokedCallbacks {
    private static final OverrideCallbackFactory<Activity> sMoveTaskToBackFactory = new
            MoveTaskToBackCallbackFactory();
    private static final OverrideCallbackFactory<Activity> sFinishAndRemoveTaskFactory = new
            FinishAndRemoveTaskCallbackFactory();

    private SystemOnBackInvokedCallbacks() {
        throw new UnsupportedOperationException("This is a utility class and cannot be "
                + "instantiated");
    }

    /**
     * <p>Get a callback to triggers {@link Activity#moveTaskToBack(boolean)} on the associated
     * {@link Activity}, moving the task containing the activity to the background. The system
     * will play the corresponding transition animation, regardless of whether the activity
     * is the root activity of the task.</p>
     *
     * @param activity The associated {@link Activity}
     * @see Activity#moveTaskToBack(boolean)
     */
    @FlaggedApi(Flags.FLAG_PREDICTIVE_BACK_SYSTEM_OVERRIDE_CALLBACK)
    @NonNull
    public static OnBackInvokedCallback moveTaskToBackCallback(@NonNull Activity activity) {
        return sMoveTaskToBackFactory.getOverrideCallback(activity);
    }

    /**
     * <p>Get a callback to triggers {@link Activity#finishAndRemoveTask()} on the associated
     * {@link Activity}. If the activity is the root activity of its task, the entire task
     * will be removed from the recents task. The activity will be finished in all cases.
     * The system will play the corresponding transition animation.</p>
     *
     * @param activity The associated {@link Activity}
     * @see Activity#finishAndRemoveTask()
     */
    @FlaggedApi(Flags.FLAG_PREDICTIVE_BACK_SYSTEM_OVERRIDE_CALLBACK)
    @NonNull
    public static OnBackInvokedCallback finishAndRemoveTaskCallback(@NonNull Activity activity) {
        return sFinishAndRemoveTaskFactory.getOverrideCallback(activity);
    }

    /**
     * Abstract factory for creating system override {@link SystemOverrideOnBackInvokedCallback}
     * instances.
     *
     * <p>Concrete implementations of this factory are responsible for creating callbacks that
     * override the default system back navigation behavior. These callbacks should be used
     * exclusively for system overrides and should never be invoked directly.</p>
     */
    private abstract static class OverrideCallbackFactory<TYPE> {
        private final ArrayMap<WeakReference<TYPE>,
                WeakReference<SystemOverrideOnBackInvokedCallback>> mObjectMap = new ArrayMap<>();

        protected abstract SystemOverrideOnBackInvokedCallback createCallback(
                @NonNull TYPE context);

        @NonNull SystemOverrideOnBackInvokedCallback getOverrideCallback(@NonNull TYPE object) {
            if (object == null) {
                throw new NullPointerException("Input object cannot be null");
            }
            synchronized (mObjectMap) {
                WeakReference<SystemOverrideOnBackInvokedCallback> callback = null;
                for (int i = mObjectMap.size() - 1; i >= 0; --i) {
                    final WeakReference<TYPE> next = mObjectMap.keyAt(i);
                    if (next.get() == object) {
                        callback = mObjectMap.get(next);
                        break;
                    }
                }
                if (callback != null) {
                    return callback.get();
                }
                final SystemOverrideOnBackInvokedCallback contextCallback = createCallback(object);
                if (contextCallback != null) {
                    mObjectMap.put(new WeakReference<>(object),
                            new WeakReference<>(contextCallback));
                }
                return contextCallback;
            }
        }
    }

    private static class MoveTaskToBackCallbackFactory extends OverrideCallbackFactory<Activity> {
        @Override
        protected SystemOverrideOnBackInvokedCallback createCallback(Activity activity) {
            final WeakReference<Activity> activityRef = new WeakReference<>(activity);
            return new SystemOverrideOnBackInvokedCallback() {
                @Override
                public void onBackInvoked() {
                    if (activityRef.get() != null) {
                        activityRef.get().moveTaskToBack(true /* nonRoot */);
                    }
                }

                @Override
                public int overrideBehavior() {
                    return OVERRIDE_MOVE_TASK_TO_BACK;
                }
            };
        }
    }

    private static class FinishAndRemoveTaskCallbackFactory extends
            OverrideCallbackFactory<Activity> {
        @Override
        protected SystemOverrideOnBackInvokedCallback createCallback(Activity activity) {
            final WeakReference<Activity> activityRef = new WeakReference<>(activity);
            return new SystemOverrideOnBackInvokedCallback() {
                @Override
                public void onBackInvoked() {
                    if (activityRef.get() != null) {
                        activityRef.get().finishAndRemoveTask();
                    }
                }

                @Override
                public int overrideBehavior() {
                    return OVERRIDE_FINISH_AND_REMOVE_TASK;
                }
            };
        }
    }
}
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.window;

import android.annotation.IntDef;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * Non-default ahead-of-time system OnBackInvokedCallback.
 * @hide
 */
public interface SystemOverrideOnBackInvokedCallback extends OnBackInvokedCallback {
    /**
     * No override request
     */
    int OVERRIDE_UNDEFINED = 0;

    /**
     * Navigating back will bring the task to back
     */
    int OVERRIDE_MOVE_TASK_TO_BACK = 1;

    /**
     * Navigating back will finish activity, and remove the task if this activity is root activity.
     */
    int OVERRIDE_FINISH_AND_REMOVE_TASK = 2;

    /** @hide */
    @IntDef({
            OVERRIDE_UNDEFINED,
            OVERRIDE_MOVE_TASK_TO_BACK,
            OVERRIDE_FINISH_AND_REMOVE_TASK,
    })
    @Retention(RetentionPolicy.SOURCE)
    @interface OverrideBehavior {
    }

    /**
     * @return Override type of this callback.
     */
    @OverrideBehavior
    default int overrideBehavior() {
        return OVERRIDE_UNDEFINED;
    }
}
+24 −3
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.window;

import static android.window.SystemOverrideOnBackInvokedCallback.OVERRIDE_UNDEFINED;

import static com.android.window.flags.Flags.predictiveBackSystemOverrideCallback;
import static com.android.window.flags.Flags.predictiveBackPrioritySystemNavigationObserver;
import static com.android.window.flags.Flags.predictiveBackTimestampApi;

@@ -201,6 +204,15 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
                mImeDispatcher.registerOnBackInvokedCallback(priority, callback);
                return;
            }
            if (predictiveBackPrioritySystemNavigationObserver()
                    && predictiveBackSystemOverrideCallback()) {
                if (priority == PRIORITY_SYSTEM_NAVIGATION_OBSERVER
                        && callback instanceof SystemOverrideOnBackInvokedCallback) {
                    Log.e(TAG, "System override callbacks cannot be registered to "
                            + "NAVIGATION_OBSERVER");
                    return;
                }
            }
            if (predictiveBackPrioritySystemNavigationObserver()) {
                if (priority == PRIORITY_SYSTEM_NAVIGATION_OBSERVER) {
                    registerSystemNavigationObserverCallback(callback);
@@ -365,7 +377,8 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
    public void tryInvokeSystemNavigationObserverCallback() {
        OnBackInvokedCallback topCallback = getTopCallback();
        Integer callbackPriority = mAllCallbacks.getOrDefault(topCallback, null);
        if (callbackPriority != null && callbackPriority == PRIORITY_SYSTEM) {
        final boolean isSystemOverride = topCallback instanceof SystemOverrideOnBackInvokedCallback;
        if ((callbackPriority != null && callbackPriority == PRIORITY_SYSTEM) || isSystemOverride) {
            invokeSystemNavigationObserverCallback();
        }
    }
@@ -384,14 +397,22 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
            OnBackInvokedCallbackInfo callbackInfo = null;
            if (callback != null) {
                int priority = mAllCallbacks.get(callback);
                int overrideAnimation = OVERRIDE_UNDEFINED;
                if (callback instanceof SystemOverrideOnBackInvokedCallback) {
                    overrideAnimation = ((SystemOverrideOnBackInvokedCallback) callback)
                            .overrideBehavior();
                }
                final boolean isSystemCallback = priority == PRIORITY_SYSTEM
                        || overrideAnimation != OVERRIDE_UNDEFINED;
                final IOnBackInvokedCallback iCallback = new OnBackInvokedCallbackWrapper(callback,
                        mTouchTracker, mProgressAnimator, mHandler, this::callOnKeyPreIme,
                        this::invokeSystemNavigationObserverCallback,
                        /*isSystemCallback*/ priority == PRIORITY_SYSTEM);
                        isSystemCallback /*isSystemCallback*/);
                callbackInfo = new OnBackInvokedCallbackInfo(
                        iCallback,
                        priority,
                        callback instanceof OnBackAnimationCallback);
                        callback instanceof OnBackAnimationCallback,
                        overrideAnimation);
            }
            mWindowSession.setOnBackInvokedCallbackInfo(mWindow, callbackInfo);
        } catch (RemoteException e) {
Loading