/* * Copyright (C) 2022 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.NonNull; import android.annotation.Nullable; import android.content.Context; import android.util.Log; import android.util.Pair; import android.window.WindowOnBackInvokedDispatcher.Checker; import java.util.ArrayList; import java.util.List; /** * {@link OnBackInvokedDispatcher} only used to hold callbacks while an actual * dispatcher becomes available. It does not dispatch the back events. *
* Once the actual {@link OnBackInvokedDispatcher} becomes available, * {@link #setActualDispatcher(OnBackInvokedDispatcher)} needs to * be called and this {@link ProxyOnBackInvokedDispatcher} will pass the callback registrations * onto it. *
* This dispatcher will continue to keep track of callback registrations and when a dispatcher is
* removed or set it will unregister the callbacks from the old one and register them on the new
* one unless {@link #reset()} is called before.
*
* @hide
*/
public class ProxyOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
/**
* List of pair representing an {@link OnBackInvokedCallback} and its associated priority.
*
* @see OnBackInvokedDispatcher#registerOnBackInvokedCallback(int, OnBackInvokedCallback)
*/
private final List
* The callbacks are registered on the dispatcher in the same order as they were added on this
* proxy dispatcher.
*/
private void transferCallbacksToDispatcher() {
if (mActualDispatcher == null) {
return;
}
if (DEBUG) {
Log.v(TAG, String.format("Proxy transferring %d callbacks to %s", mCallbacks.size(),
mActualDispatcher));
}
if (mImeDispatcher != null) {
mActualDispatcher.setImeOnBackInvokedDispatcher(mImeDispatcher);
}
for (Pair
* Using this method means that when setting a new {@link OnBackInvokedDispatcher}, the
* callbacks registered on the old one won't be removed from it and won't be registered on
* the new one.
*/
public void reset() {
if (DEBUG) {
Log.v(TAG, "Proxy: reset callbacks");
}
synchronized (mLock) {
mCallbacks.clear();
mImeDispatcher = null;
}
}
/**
* Sets the actual {@link OnBackInvokedDispatcher} onto which the callbacks will be registered.
*
* If any dispatcher was already present, all the callbacks that were added via this
* {@link ProxyOnBackInvokedDispatcher} will be unregistered from the old one and registered
* on the new one if it is not null.
*
* If you do not wish for the previously registered callbacks to be reassigned to the new
* dispatcher, {@link #reset} must be called beforehand.
*/
public void setActualDispatcher(@Nullable OnBackInvokedDispatcher actualDispatcher) {
if (DEBUG) {
Log.v(TAG, String.format("Proxy setActual %s. Current %s",
actualDispatcher, mActualDispatcher));
}
synchronized (mLock) {
if (actualDispatcher == mActualDispatcher) {
return;
}
clearCallbacksOnDispatcher();
mActualDispatcher = actualDispatcher;
transferCallbacksToDispatcher();
}
}
@Override
public void setImeOnBackInvokedDispatcher(
@NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
if (mActualDispatcher != null) {
mActualDispatcher.setImeOnBackInvokedDispatcher(imeDispatcher);
} else {
mImeDispatcher = imeDispatcher;
}
}
}