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

Commit 85093f98 authored by An An Yu's avatar An An Yu Committed by Automerger Merge Worker
Browse files

Merge "Add WindowProvider support to WindowLayoutComponentImpl and allow...

Merge "Add WindowProvider support to WindowLayoutComponentImpl and allow WindowProviderService to broadcast configuration changes to listeners." into tm-qpr-dev am: 63cd60ee am: 6e11d27d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20267030



Change-Id: Ib41335c7b1f1c62b566f7953cdba428f1e07eff1
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 90c621e6 6e11d27d
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -15,8 +15,10 @@
 */
package android.window;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Bundle;
import android.os.IBinder;
import android.view.WindowManager.LayoutParams.WindowType;

/**
@@ -36,4 +38,11 @@ public interface WindowProvider {
    /** Gets the launch options of this provider */
    @Nullable
    Bundle getWindowContextOptions();

    /**
     * Gets the WindowContextToken of this provider.
     * @see android.content.Context#getWindowContextToken
     */
    @NonNull
    IBinder getWindowContextToken();
}
+48 −0
Original line number Diff line number Diff line
@@ -27,7 +27,10 @@ import android.annotation.UiContext;
import android.app.ActivityThread;
import android.app.LoadedApk;
import android.app.Service;
import android.content.ComponentCallbacks;
import android.content.ComponentCallbacksController;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.display.DisplayManager;
import android.os.Bundle;
import android.os.IBinder;
@@ -54,6 +57,8 @@ public abstract class WindowProviderService extends Service implements WindowPro
    private final WindowContextController mController = new WindowContextController(mWindowToken);
    private WindowManager mWindowManager;
    private boolean mInitialized;
    private final ComponentCallbacksController mCallbacksController =
            new ComponentCallbacksController();

    /**
     * Returns {@code true} if the {@code windowContextOptions} declares that it is a
@@ -118,6 +123,48 @@ public abstract class WindowProviderService extends Service implements WindowPro
        return mOptions;
    }

    @SuppressLint({"OnNameExpected", "ExecutorRegistration"})
    // Suppress lint because this is a legacy named function and doesn't have an optional param
    // for executor.
    // TODO(b/259347943): Update documentation for U.
    /**
     * Here we override to prevent WindowProviderService from invoking
     * {@link Application.registerComponentCallback}, which will result in callback registered
     * for process-level Configuration change updates.
     */
    @Override
    public void registerComponentCallbacks(@NonNull ComponentCallbacks callback) {
        // For broadcasting Configuration Changes.
        mCallbacksController.registerCallbacks(callback);
    }

    @SuppressLint("OnNameExpected")
    @Override
    public void unregisterComponentCallbacks(@NonNull ComponentCallbacks callback) {
        mCallbacksController.unregisterCallbacks(callback);
    }

    @SuppressLint("OnNameExpected")
    @Override
    public void onConfigurationChanged(@Nullable Configuration configuration) {
        // This is only called from WindowTokenClient.
        mCallbacksController.dispatchConfigurationChanged(configuration);
    }

    /**
     * Override {@link Service}'s empty implementation and listen to {@link ActivityThread} for
     * low memory and trim memory events.
     */
    @Override
    public void onLowMemory() {
        mCallbacksController.dispatchLowMemory();
    }

    @Override
    public void onTrimMemory(int level) {
        mCallbacksController.dispatchTrimMemory(level);
    }

    /**
     * Returns the display ID to launch this {@link WindowProviderService}.
     *
@@ -181,5 +228,6 @@ public abstract class WindowProviderService extends Service implements WindowPro
    public void onDestroy() {
        super.onDestroy();
        mController.detachIfNeeded();
        mCallbacksController.clearCallbacks();
    }
}
+13 −12
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.util.ArrayMap;
import android.window.WindowContext;
import android.window.WindowProvider;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -71,7 +72,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {

    private final List<CommonFoldingFeature> mLastReportedFoldingFeatures = new ArrayList<>();

    private final Map<IBinder, WindowContextConfigListener> mWindowContextConfigListeners =
    private final Map<IBinder, ConfigurationChangeListener> mConfigurationChangeListeners =
            new ArrayMap<>();

    public WindowLayoutComponentImpl(@NonNull Context context) {
@@ -121,21 +122,21 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
        }
        if (!context.isUiContext()) {
            throw new IllegalArgumentException("Context must be a UI Context, which should be"
                    + " an Activity or a WindowContext");
                    + " an Activity, WindowContext or InputMethodService");
        }
        mFoldingFeatureProducer.getData((features) -> {
            // Get the WindowLayoutInfo from the activity and pass the value to the layoutConsumer.
            WindowLayoutInfo newWindowLayout = getWindowLayoutInfo(context, features);
            consumer.accept(newWindowLayout);
        });
        mWindowLayoutChangeListeners.put(context, consumer);

        if (context instanceof WindowContext) {
        // TODO(b/258065175) Further extend this to ContextWrappers.
        if (context instanceof WindowProvider) {
            final IBinder windowContextToken = context.getWindowContextToken();
            final WindowContextConfigListener listener =
                    new WindowContextConfigListener(windowContextToken);
            final ConfigurationChangeListener listener =
                    new ConfigurationChangeListener(windowContextToken);
            context.registerComponentCallbacks(listener);
            mWindowContextConfigListeners.put(windowContextToken, listener);
            mConfigurationChangeListeners.put(windowContextToken, listener);
        }
    }

@@ -150,10 +151,10 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
            if (!mWindowLayoutChangeListeners.get(context).equals(consumer)) {
                continue;
            }
            if (context instanceof WindowContext) {
            if (context instanceof WindowProvider) {
                final IBinder token = context.getWindowContextToken();
                context.unregisterComponentCallbacks(mWindowContextConfigListeners.get(token));
                mWindowContextConfigListeners.remove(token);
                context.unregisterComponentCallbacks(mConfigurationChangeListeners.get(token));
                mConfigurationChangeListeners.remove(token);
            }
            break;
        }
@@ -349,10 +350,10 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent {
        }
    }

    private final class WindowContextConfigListener implements ComponentCallbacks {
    private final class ConfigurationChangeListener implements ComponentCallbacks {
        final IBinder mToken;

        WindowContextConfigListener(IBinder token) {
        ConfigurationChangeListener(IBinder token) {
            mToken = token;
        }