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

Commit 1b740560 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Consolidate configuraton dispatching logic" into main

parents 30d94b94 f23ceff6
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.content.ComponentCallbacks;
import android.content.res.Configuration;

/**
 * Indicates a {@link android.content.Context} could propagate the
 * {@link android.content.res.Configuration} from the server side and users may listen to the
 * updates through {@link android.content.Context#registerComponentCallbacks(ComponentCallbacks)}.
 *
 * @hide
 */
public interface ConfigurationDispatcher {

    /**
     * Called when there's configuration update from the server side.
     */
    void dispatchConfigurationChanged(@NonNull Configuration configuration);

    /**
     * Indicates that if this dispatcher should report the change even if it's not
     * {@link Configuration#diffPublicOnly}.
     */
    default boolean shouldReportPrivateChanges() {
        return false;
    }
}
+9 −4
Original line number Diff line number Diff line
@@ -17,8 +17,6 @@ package android.window;

import static android.view.WindowManagerImpl.createWindowContextWindowManager;

import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UiContext;
@@ -46,7 +44,8 @@ import java.lang.ref.Reference;
 * @hide
 */
@UiContext
public class WindowContext extends ContextWrapper implements WindowProvider {
public class WindowContext extends ContextWrapper implements WindowProvider,
        ConfigurationDispatcher {
    private final WindowManager mWindowManager;
    @WindowManager.LayoutParams.WindowType
    private final int mType;
@@ -155,7 +154,7 @@ public class WindowContext extends ContextWrapper implements WindowProvider {
    }

    /** Dispatch {@link Configuration} to each {@link ComponentCallbacks}. */
    @VisibleForTesting(visibility = PACKAGE)
    @Override
    public void dispatchConfigurationChanged(@NonNull Configuration newConfig) {
        mCallbacksController.dispatchConfigurationChanged(newConfig);
    }
@@ -170,4 +169,10 @@ public class WindowContext extends ContextWrapper implements WindowProvider {
    public Bundle getWindowContextOptions() {
        return mOptions;
    }

    @Override
    public boolean shouldReportPrivateChanges() {
        // Always dispatch config changes to WindowContext.
        return true;
    }
}
+0 −1
Original line number Diff line number Diff line
@@ -86,7 +86,6 @@ public class WindowContextController {
     * @param token The token used to attach to a window manager node. It is usually from
     *              {@link Context#getWindowContextToken()}.
     */
    @VisibleForTesting
    public WindowContextController(@NonNull WindowTokenClient token) {
        mToken = token;
    }
+13 −1
Original line number Diff line number Diff line
@@ -49,9 +49,11 @@ import android.view.WindowManagerImpl;
 *
 * @hide
 */
@SuppressWarnings("HiddenSuperclass")
@TestApi
@UiContext
public abstract class WindowProviderService extends Service implements WindowProvider {
public abstract class WindowProviderService extends Service implements WindowProvider,
        ConfigurationDispatcher {

    private static final String TAG = WindowProviderService.class.getSimpleName();

@@ -240,4 +242,14 @@ public abstract class WindowProviderService extends Service implements WindowPro
        mController.detachIfNeeded();
        mCallbacksController.clearCallbacks();
    }

    /**
     * {@inheritDoc}
     *
     * @hide
     */
    @Override
    public void dispatchConfigurationChanged(@NonNull Configuration configuration) {
        onConfigurationChanged(configuration);
    }
}
+10 −14
Original line number Diff line number Diff line
@@ -121,8 +121,6 @@ public class WindowTokenClient extends Binder {
                newDisplayId, true /* shouldReportConfigChange */).recycleOnUse());
    }

    // TODO(b/192048581): rewrite this method based on WindowContext and WindowProviderService
    //  are inherited from WindowProvider.
    /**
     * Called when {@link Configuration} updates from the server side receive.
     *
@@ -169,7 +167,7 @@ public class WindowTokenClient extends Binder {
        CompatibilityInfo.applyOverrideIfNeeded(newConfig);
        final boolean displayChanged;
        final boolean shouldUpdateResources;
        final int diff;
        final int publicDiff;
        final Configuration currentConfig;

        synchronized (mConfiguration) {
@@ -177,7 +175,7 @@ public class WindowTokenClient extends Binder {
            shouldUpdateResources = shouldUpdateResources(this, mConfiguration,
                    newConfig, newConfig /* overrideConfig */, displayChanged,
                    null /* configChanged */);
            diff = mConfiguration.diffPublicOnly(newConfig);
            publicDiff = mConfiguration.diffPublicOnly(newConfig);
            currentConfig = mShouldDumpConfigForIme ? new Configuration(mConfiguration) : null;
            if (shouldUpdateResources) {
                mConfiguration.setTo(newConfig);
@@ -200,17 +198,15 @@ public class WindowTokenClient extends Binder {
            // TODO(ag/9789103): update resource manager logic to track non-activity tokens
            mResourcesManager.updateResourcesForActivity(this, newConfig, newDisplayId);

            if (shouldReportConfigChange && context instanceof WindowContext) {
                final WindowContext windowContext = (WindowContext) context;
                windowContext.dispatchConfigurationChanged(newConfig);
            if (shouldReportConfigChange && context instanceof ConfigurationDispatcher dispatcher) {
                // Updating resources implies some fields of configuration are updated despite they
                // are public or not.
                if (dispatcher.shouldReportPrivateChanges() || publicDiff != 0) {
                    dispatcher.dispatchConfigurationChanged(newConfig);
                }

            if (shouldReportConfigChange && diff != 0
                    && context instanceof WindowProviderService) {
                final WindowProviderService windowProviderService = (WindowProviderService) context;
                windowProviderService.onConfigurationChanged(newConfig);
            }
            freeTextLayoutCachesIfNeeded(diff);

            freeTextLayoutCachesIfNeeded(publicDiff);
            if (mShouldDumpConfigForIme) {
                if (!shouldReportConfigChange) {
                    Log.d(TAG, "Only apply configuration update to Resources because "
@@ -219,7 +215,7 @@ public class WindowTokenClient extends Binder {
                            + ", config=" + context.getResources().getConfiguration()
                            + ", display ID=" + context.getDisplayId() + "\n"
                            + Debug.getCallers(5));
                } else if (diff == 0) {
                } else if (publicDiff == 0) {
                    Log.d(TAG, "Configuration not dispatch to IME because configuration has no "
                            + " public difference with updated config. "
                            + " Current config=" + context.getResources().getConfiguration()
Loading