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

Commit 79b96064 authored by Yunfan Chen's avatar Yunfan Chen
Browse files

Let IME be aware of display override configuration updates

This patch contains three parts:
- Register a listener to corresponding ActivityDisplay to let IME get
  updated display override configuration.
- Isolate IME display override configuration update from general global
  default display configuration update.
- Fix a possible NPE in getProcessGlobalConfiguratoin().

With the patch, IME will keep to get correct process global
configuration of the display it's registered to.

Bug: 113253755
Bug: 116870598
Test: See repro steps in b/111364446#comment10.
Test: go/wm-smoke
Change-Id: I7fb58ed23e58e4696a2fe336806c4bf323891074
parent e08bef25
Loading
Loading
Loading
Loading
+32 −31
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.server.am;
import static android.Manifest.permission.BIND_VOICE_INTERACTION;
import static android.Manifest.permission.CHANGE_CONFIGURATION;
import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
import static android.Manifest.permission.FILTER_EVENTS;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
import static android.Manifest.permission.READ_FRAME_BUFFER;
@@ -28,9 +27,9 @@ import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.Manifest.permission.STOP_APP_SWITCHES;
import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
import static android.app.ActivityManagerInternal.ALLOW_FULL_ONLY;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
@@ -71,6 +70,10 @@ import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
import static android.view.WindowManager.TRANSIT_TASK_OPEN;
import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;

import static com.android.server.am.ActivityManagerService.ANR_TRACE_DIR;
import static com.android.server.am.ActivityManagerService.MY_PID;
import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
import static com.android.server.am.ActivityManagerService.dumpStackTraces;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.CONFIG_WILL_CHANGE;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.CONTROLLER;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.CURRENT_TRACKER;
@@ -81,12 +84,21 @@ import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.HEA
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.HOME_PROC;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.LAUNCHING_ACTIVITY;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.PREVIOUS_PROC_VISIBLE_TIME_MS;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto
        .PREVIOUS_PROC_VISIBLE_TIME_MS;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.SCREEN_COMPAT_PACKAGES;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.MODE;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage.PACKAGE;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage
        .MODE;
import static com.android.server.am.ActivityManagerServiceDumpProcessesProto.ScreenCompatPackage
        .PACKAGE;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_ALL;
import static com.android.server.am.ActivityManagerService.ANR_TRACE_DIR;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_IMMERSIVE;
@@ -104,19 +116,8 @@ import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_SWITC
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityManagerService.MY_PID;
import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
import static com.android.server.am.ActivityManagerService.dumpStackTraces;
import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import static com.android.server.am.ActivityTaskManagerService.H.REPORT_TIME_TRACKER_MSG;
import static com.android.server.am.ActivityTaskManagerService.UiHandler.DISMISS_DIALOG_UI_MSG;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
@@ -4761,7 +4762,8 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
        }

        for (int i = mPidMap.size() - 1; i >= 0; i--) {
            WindowProcessController app = mPidMap.get(mPidMap.keyAt(i));
            final int pid = mPidMap.keyAt(i);
            final WindowProcessController app = mPidMap.get(pid);
            if (DEBUG_CONFIGURATION) {
                Slog.v(TAG_CONFIGURATION, "Update process config of "
                        + app.mName + " to new config " + configCopy);
@@ -6015,7 +6017,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
         * @param displayId The ID of the display showing the IME.
         */
        @Override
        public void onImeWindowSetOnDisplay(int pid, int displayId) {
        public void onImeWindowSetOnDisplay(final int pid, final int displayId) {
            if (pid == MY_PID || pid < 0) {
                if (DEBUG_CONFIGURATION) {
                    Slog.w(TAG,
@@ -6025,29 +6027,28 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
            }
            mH.post(() -> {
                synchronized (mGlobalLock) {
                    // Check if display is initialized in AM.
                    if (!mStackSupervisor.isDisplayAdded(displayId)) {
                        // Call come when display is not yet added or has already been removed.
                    final ActivityDisplay activityDisplay =
                            mStackSupervisor.getActivityDisplay(displayId);
                    if (activityDisplay == null) {
                        // Call might come when display is not yet added or has been removed.
                        if (DEBUG_CONFIGURATION) {
                            Slog.w(TAG, "Trying to update display configuration for non-existing "
                                    + "displayId=" + displayId);
                        }
                        return;
                    }
                    final WindowProcessController imeProcess = mPidMap.get(pid);
                    if (imeProcess == null) {
                    final WindowProcessController process = mPidMap.get(pid);
                    if (process == null) {
                        if (DEBUG_CONFIGURATION) {
                            Slog.w(TAG, "Trying to update display configuration for invalid pid: "
                                            + pid);
                            Slog.w(TAG, "Trying to update display configuration for invalid "
                                    + "process, pid=" + pid);
                        }
                        return;
                    }
                    // Fetch the current override configuration of the display and set it to the
                    // process global configuration.
                    imeProcess.onConfigurationChanged(
                            mStackSupervisor.getDisplayOverrideConfiguration(displayId));
                    process.registerDisplayConfigurationListenerLocked(activityDisplay);
                }
            });

        }

        @Override
+40 −9
Original line number Diff line number Diff line
@@ -17,20 +17,22 @@
package com.android.server.am;

import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT;
import static android.view.Display.INVALID_DISPLAY;

import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
import static com.android.server.am.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityTaskManagerDebugConfig.DEBUG_RELEASE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
import static com.android.server.am.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.am.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.am.ActivityTaskManagerService
        .INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MS;
import static com.android.server.am.ActivityTaskManagerService.KEY_DISPATCHING_TIMEOUT_MS;
import static com.android.server.am.ActivityTaskManagerService.RELAUNCH_REASON_NONE;

@@ -47,11 +49,12 @@ import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;

import android.util.proto.ProtoOutputStream;

import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.wm.ConfigurationContainer;
import com.android.server.wm.ConfigurationContainerListener;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -67,7 +70,8 @@ import java.util.ArrayList;
 * window manager so the window manager lock is held and appropriate permissions are checked before
 * calls are allowed to proceed.
 */
public class WindowProcessController extends ConfigurationContainer<ConfigurationContainer> {
public class WindowProcessController extends ConfigurationContainer<ConfigurationContainer>
        implements ConfigurationContainerListener {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowProcessController" : TAG_ATM;
    private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
    private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
@@ -147,6 +151,8 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio

    // Last configuration that was reported to the process.
    private final Configuration mLastReportedConfiguration;
    // Registered display id as a listener to override config change
    private int mDisplayId;

    WindowProcessController(ActivityTaskManagerService atm, ApplicationInfo info, String name,
            int uid, int userId, Object owner, WindowProcessListener listener,
@@ -159,6 +165,7 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
        mListener = listener;
        mAtm = atm;
        mLastReportedConfiguration = new Configuration();
        mDisplayId = INVALID_DISPLAY;
        if (config != null) {
            onConfigurationChanged(config);
        }
@@ -704,6 +711,30 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
        mListener.appDied();
    }

    void registerDisplayConfigurationListenerLocked(ActivityDisplay activityDisplay) {
        if (activityDisplay == null) {
            return;
        }
        // A process can only register to one display to listener to the override configuration
        // change. Unregister existing listener if it has one before register the new one.
        unregisterDisplayConfigurationListenerLocked();
        mDisplayId = activityDisplay.mDisplayId;
        activityDisplay.registerConfigurationChangeListener(this);
    }

    private void unregisterDisplayConfigurationListenerLocked() {
        if (mDisplayId == INVALID_DISPLAY) {
            return;
        }
        final ActivityDisplay activityDisplay =
                mAtm.mStackSupervisor.getActivityDisplay(mDisplayId);
        if (activityDisplay != null) {
            mAtm.mStackSupervisor.getActivityDisplay(
                    mDisplayId).unregisterConfigurationChangeListener(this);
        }
        mDisplayId = INVALID_DISPLAY;
    }

    @Override
    public void onConfigurationChanged(Configuration newGlobalConfig) {
        super.onConfigurationChanged(newGlobalConfig);
+1 −1
Original line number Diff line number Diff line
@@ -2256,7 +2256,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    private Configuration getProcessGlobalConfiguration() {
        // For child windows we want to use the pid for the parent window in case the the child
        // window was added from another process.
        final int pid = isChildWindow() ? getParentWindow().mSession.mPid : mSession.mPid;
        final int pid = getParentWindow() != null ? getParentWindow().mSession.mPid : mSession.mPid;
        mTempConfiguration.setTo(mService.mProcessConfigurations.get(
                pid, mService.mRoot.getConfiguration()));
        return mTempConfiguration;