diff options
| author | 2023-12-12 22:02:59 -0600 | |
|---|---|---|
| committer | 2023-12-15 21:45:39 +0800 | |
| commit | a10d9b94c15302d4ff0a472a1391fd8c0fcf822b (patch) | |
| tree | d7c13ab4f71beb2160fba575cad95625a2bd203d | |
| parent | c7faccbdbdae750779b2cf5bc70de3c8a95e2a94 (diff) | |
Simplify legacy screen compat mode a bit
The entry of changing legacy screen compat mode is almost a dead code.
The current usage is only from command:
adb shell am screen-compat [on|off] $packageName
But because the manifest attributes are still valid:
android:smallScreens/normalScreens/largeScreens
It might be better to preserve the behavior for now.
By caching the legacy compat state in server side and reusing
restartProcessIfVisible for compatibility info change, this can
reduce unnecessary Configuration comparison on every frame from
Display#getDisplayAdjustments(). Also the fields can be removed:
ViewRootImpl#mLastInCompatMode
WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW
ActivityRecord#forceNewConfig
Bug: 163976519
Test: atest CompatModePackagesTests
Test: adb install --bypass-low-target-sdk-block test.apk
which declares minSdkVersion="1"
The appearance is not changed and touch can still work.
Test: App (without always/never-compat) can be relaunched and
scaled when using command:
adb shell am screen-compat [on|off] $packageName
Change-Id: I661ddaee15014201aa1109671cfd6619df91ea4a
10 files changed, 65 insertions, 91 deletions
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 5cbb42e0e346..764881ef5437 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -530,8 +530,6 @@ public final class ViewRootImpl implements ViewParent, // Set to true to stop input during an Activity Transition. boolean mPausedForTransition = false; - boolean mLastInCompatMode = false; - SurfaceHolder.Callback2 mSurfaceHolderCallback; BaseSurfaceHolder mSurfaceHolder; boolean mIsCreating; @@ -1362,11 +1360,6 @@ public final class ViewRootImpl implements ViewParent, } if (DEBUG_LAYOUT) Log.d(mTag, "WindowLayout in setView:" + attrs); - if (!compatibilityInfo.supportsScreen()) { - attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; - mLastInCompatMode = true; - } - mSoftInputMode = attrs.softInputMode; mWindowAttributesChanged = true; mAttachInfo.mRootView = view; @@ -1900,10 +1893,6 @@ public final class ViewRootImpl implements ViewParent, // Keep track of the actual window flags supplied by the client. mClientWindowLayoutFlags = attrs.flags; - // Preserve compatible window flag if exists. - final int compatibleWindowFlag = mWindowAttributes.privateFlags - & WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; - // Preserve system UI visibility. final int systemUiVisibility = mWindowAttributes.systemUiVisibility; final int subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility; @@ -1935,8 +1924,7 @@ public final class ViewRootImpl implements ViewParent, mWindowAttributes.subtreeSystemUiVisibility = subtreeSystemUiVisibility; mWindowAttributes.insetsFlags.appearance = appearance; mWindowAttributes.insetsFlags.behavior = behavior; - mWindowAttributes.privateFlags |= compatibleWindowFlag - | appearanceAndBehaviorPrivateFlags; + mWindowAttributes.privateFlags |= appearanceAndBehaviorPrivateFlags; if (mWindowAttributes.preservePreviousSurfaceInsets) { // Restore old surface insets. @@ -3137,21 +3125,6 @@ public final class ViewRootImpl implements ViewParent, final boolean shouldOptimizeMeasure = shouldOptimizeMeasure(lp); WindowManager.LayoutParams params = null; - CompatibilityInfo compatibilityInfo = - mDisplay.getDisplayAdjustments().getCompatibilityInfo(); - if (compatibilityInfo.supportsScreen() == mLastInCompatMode) { - params = lp; - mFullRedrawNeeded = true; - mLayoutRequested = true; - if (mLastInCompatMode) { - params.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; - mLastInCompatMode = false; - } else { - params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; - mLastInCompatMode = true; - } - } - Rect frame = mWinFrame; if (mFirst) { mFullRedrawNeeded = true; diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index c7e180732fd4..5fc1ae5c3914 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -3137,13 +3137,6 @@ public interface WindowManager extends ViewManager { @UnsupportedAppUsage public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 1 << 6; - /** Window flag: special flag to limit the size of the window to be - * original size ([320x480] x density). Used to create window for applications - * running under compatibility mode. - * - * {@hide} */ - public static final int PRIVATE_FLAG_COMPATIBLE_WINDOW = 1 << 7; - /** Window flag: a special option intended for system dialogs. When * this flag is set, the window will demand focus unconditionally when * it is created. @@ -3339,7 +3332,6 @@ public interface WindowManager extends ViewManager { SYSTEM_FLAG_SHOW_FOR_ALL_USERS, PRIVATE_FLAG_UNRESTRICTED_GESTURE_EXCLUSION, PRIVATE_FLAG_NO_MOVE_ANIMATION, - PRIVATE_FLAG_COMPATIBLE_WINDOW, PRIVATE_FLAG_SYSTEM_ERROR, PRIVATE_FLAG_OPTIMIZE_MEASURE, PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS, @@ -3393,10 +3385,6 @@ public interface WindowManager extends ViewManager { equals = PRIVATE_FLAG_NO_MOVE_ANIMATION, name = "NO_MOVE_ANIMATION"), @ViewDebug.FlagToString( - mask = PRIVATE_FLAG_COMPATIBLE_WINDOW, - equals = PRIVATE_FLAG_COMPATIBLE_WINDOW, - name = "COMPATIBLE_WINDOW"), - @ViewDebug.FlagToString( mask = PRIVATE_FLAG_SYSTEM_ERROR, equals = PRIVATE_FLAG_SYSTEM_ERROR, name = "SYSTEM_ERROR"), diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java index ae21c4bf5450..f58aeac918b5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java @@ -277,11 +277,6 @@ public class SplashscreenContentDrawer { params.token = appToken; params.packageName = activityInfo.packageName; params.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS; - - if (!context.getResources().getCompatibilityInfo().supportsScreen()) { - params.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; - } - params.setTitle("Splash Screen " + title); return params; } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 04ac9fbf178d..00069fc0c8a2 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -563,7 +563,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A boolean idle; // has the activity gone idle? boolean hasBeenLaunched;// has this activity ever been launched? boolean immersive; // immersive mode (don't interrupt if possible) - boolean forceNewConfig; // force re-create with new config next time boolean supportsEnterPipOnTaskSwitch; // This flag is set by the system to indicate that the // activity can enter picture in picture while pausing (only when switching to another task) // The PiP params used when deferring the entering of picture-in-picture. @@ -9592,7 +9591,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // configurations because there are cases (like moving a task to the root pinned task) where // the combine configurations are equal, but would otherwise differ in the override config mTmpConfig.setTo(mLastReportedConfiguration.getMergedConfiguration()); - if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) { + if (getConfiguration().equals(mTmpConfig) && !displayChanged) { ProtoLog.v(WM_DEBUG_CONFIGURATION, "Configuration & display " + "unchanged in %s", this); return true; @@ -9619,7 +9618,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A return true; } - if (changes == 0 && !forceNewConfig) { + if (changes == 0) { ProtoLog.v(WM_DEBUG_CONFIGURATION, "Configuration no differences in %s", this); // There are no significant differences, so we won't relaunch but should still deliver @@ -9641,7 +9640,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // pick that up next time it starts. if (!attachedToProcess()) { ProtoLog.v(WM_DEBUG_CONFIGURATION, "Configuration doesn't matter not running %s", this); - forceNewConfig = false; return true; } @@ -9651,11 +9649,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A Integer.toHexString(changes), Integer.toHexString(info.getRealConfigChanged()), mLastReportedConfiguration); - if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) { + if (shouldRelaunchLocked(changes, mTmpConfig)) { // Aha, the activity isn't handling the change, so DIE DIE DIE. configChangeFlags |= changes; startFreezingScreenLocked(globalChanges); - forceNewConfig = false; // Do not preserve window if it is freezing screen because the original window won't be // able to update drawn state that causes freeze timeout. preserveWindow &= isResizeOnlyChange(changes) && !mFreezingScreen; @@ -9875,7 +9872,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A try { ProtoLog.i(WM_DEBUG_STATES, "Moving to %s Relaunching %s callers=%s" , (andResume ? "RESUMED" : "PAUSED"), this, Debug.getCallers(6)); - forceNewConfig = false; final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(token, pendingResults, pendingNewIntents, configChangeFlags, new MergedConfiguration(getProcessGlobalConfiguration(), diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java index e59601c69cd8..10efb9491bed 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java @@ -906,7 +906,6 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } mService.getPackageManagerInternalLocked().notifyPackageUse( r.intent.getComponent().getPackageName(), NOTIFY_PACKAGE_USE_ACTIVITY); - r.forceNewConfig = false; mService.getAppWarningsLocked().onStartActivity(r); // Because we could be starting an Activity in the system process this may not go diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java index 73bcc8d94252..1a8927ecf564 100644 --- a/services/core/java/com/android/server/wm/CompatModePackages.java +++ b/services/core/java/com/android/server/wm/CompatModePackages.java @@ -19,7 +19,6 @@ package com.android.server.wm; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; -import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS; import static com.android.server.wm.CompatScaleProvider.COMPAT_SCALE_MODE_SYSTEM_FIRST; import static com.android.server.wm.CompatScaleProvider.COMPAT_SCALE_MODE_SYSTEM_LAST; @@ -47,6 +46,7 @@ import android.util.AtomicFile; import android.util.DisplayMetrics; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseBooleanArray; import android.util.Xml; import com.android.internal.protolog.common.ProtoLog; @@ -60,6 +60,7 @@ import org.xmlpull.v1.XmlPullParserException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -347,6 +348,7 @@ public final class CompatModePackages { private GameManagerInternal mGameManager; private final AtomicFile mFile; private final HashMap<String, Integer> mPackages = new HashMap<>(); + private final SparseBooleanArray mLegacyScreenCompatPackages = new SparseBooleanArray(); private final CompatHandler mHandler; private final SparseArray<CompatScaleProvider> mProviders = new SparseArray<>(); @@ -427,6 +429,7 @@ public final class CompatModePackages { mPackages.remove(packageName); scheduleWrite(); } + mLegacyScreenCompatPackages.delete(packageName.hashCode()); } public void handlePackageAddedLocked(String packageName, boolean updated) { @@ -458,6 +461,17 @@ public final class CompatModePackages { mHandler.sendMessageDelayed(msg, 10000); } + /** + * Returns {@code true} if the windows belonging to the package should be scaled with + * {@link DisplayContent#mCompatibleScreenScale}. + */ + boolean useLegacyScreenCompatMode(String packageName) { + if (mLegacyScreenCompatPackages.size() == 0) { + return false; + } + return mLegacyScreenCompatPackages.get(packageName.hashCode()); + } + public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) { final boolean forceCompat = getPackageCompatModeEnabledLocked(ai); final CompatScale compatScale = getCompatScaleFromProvider(ai.packageName, ai.uid); @@ -466,8 +480,18 @@ public final class CompatModePackages { : getCompatScale(ai.packageName, ai.uid, /* checkProvider= */ false); final float densityScale = compatScale != null ? compatScale.mDensityScaleFactor : appScale; final Configuration config = mService.getGlobalConfiguration(); - return new CompatibilityInfo(ai, config.screenLayout, config.smallestScreenWidthDp, - forceCompat, appScale, densityScale); + final CompatibilityInfo info = new CompatibilityInfo(ai, config.screenLayout, + config.smallestScreenWidthDp, forceCompat, appScale, densityScale); + // Ignore invalid info which may be a placeholder of isolated process. + if (ai.flags != 0 && ai.sourceDir != null) { + if (!info.supportsScreen() && !"android".equals(ai.packageName)) { + Slog.i(TAG, "Use legacy screen compat mode: " + ai.packageName); + mLegacyScreenCompatPackages.put(ai.packageName.hashCode(), true); + } else if (mLegacyScreenCompatPackages.size() > 0) { + mLegacyScreenCompatPackages.delete(ai.packageName.hashCode()); + } + } + return info; } float getCompatScale(String packageName, int uid) { @@ -718,14 +742,23 @@ public final class CompatModePackages { scheduleWrite(); - final Task rootTask = mService.getTopDisplayFocusedRootTask(); - ActivityRecord starting = rootTask.restartPackage(packageName); - + final ArrayList<WindowProcessController> restartedApps = new ArrayList<>(); + mService.mRootWindowContainer.forAllWindows(w -> { + final ActivityRecord ar = w.mActivityRecord; + if (ar != null) { + if (ar.packageName.equals(packageName) && !restartedApps.contains(ar.app)) { + ar.restartProcessIfVisible(); + restartedApps.add(ar.app); + } + } else if (w.getProcess().mInfo.packageName.equals(packageName)) { + w.updateGlobalScale(); + } + }, true /* traverseTopToBottom */); // Tell all processes that loaded this package about the change. SparseArray<WindowProcessController> pidMap = mService.mProcessMap.getPidMap(); for (int i = pidMap.size() - 1; i >= 0; i--) { final WindowProcessController app = pidMap.valueAt(i); - if (!app.containsPackage(packageName)) { + if (!app.containsPackage(packageName) || restartedApps.contains(app)) { continue; } try { @@ -737,14 +770,6 @@ public final class CompatModePackages { } catch (Exception e) { } } - - if (starting != null) { - starting.ensureActivityConfiguration(0 /* globalChanges */, - false /* preserveWindow */); - // And we need to make sure at this point that all other activities - // are made visible with the correct configuration. - rootTask.ensureActivitiesVisible(starting, 0, !PRESERVE_WINDOWS); - } } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 03d6c2cab828..f24128b80b49 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -512,7 +512,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ private final DisplayMetrics mCompatDisplayMetrics = new DisplayMetrics(); - /** The desired scaling factor for compatible apps. */ + /** + * The desired scaling factor for compatible apps. It limits the size of the window to be + * original size ([320x480] x density). Used to scale window for applications running under + * legacy compatibility mode. + */ float mCompatibleScreenScale; /** @see #getCurrentOverrideConfigurationChanges */ diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 671acfc697e4..dbfcc22c6903 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -34,7 +34,6 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS; import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME; -import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY; import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY; @@ -5917,22 +5916,6 @@ class Task extends TaskFragment { return activities; } - ActivityRecord restartPackage(String packageName) { - ActivityRecord starting = topRunningActivity(); - - // All activities that came from the package must be - // restarted as if there was a config change. - forAllActivities(r -> { - if (!r.info.packageName.equals(packageName)) return; - r.forceNewConfig = true; - if (starting != null && r == starting && r.isVisibleRequested()) { - r.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT); - } - }); - - return starting; - } - Task reuseOrCreateTask(ActivityInfo info, Intent intent, boolean toTop) { return reuseOrCreateTask(info, intent, null /*voiceSession*/, null /*voiceInteractor*/, toTop, null /*activity*/, null /*source*/, null /*options*/); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 4e9d23c88db4..ddbaf08cec3f 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -52,7 +52,6 @@ import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON; import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.MATCH_PARENT; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NOT_MAGNIFIABLE; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY; @@ -1270,13 +1269,14 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP * @see ActivityRecord#hasSizeCompatBounds() */ boolean hasCompatScale() { - if ((mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0) { - return true; - } if (mAttrs.type == TYPE_APPLICATION_STARTING) { // Exclude starting window because it is not displayed by the application. return false; } + if (mWmService.mAtmService.mCompatModePackages.useLegacyScreenCompatMode( + mSession.mProcess.mInfo.packageName)) { + return true; + } return mActivityRecord != null && mActivityRecord.hasSizeCompatBounds() || mOverrideScale != 1f; } diff --git a/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java b/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java index 1f7b65e8b701..c18726350d81 100644 --- a/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/CompatModePackagesTests.java @@ -20,10 +20,13 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; import android.app.GameManagerInternal; +import android.content.pm.ApplicationInfo; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; @@ -90,6 +93,14 @@ public class CompatModePackagesTests extends SystemServiceTestsBase { public void testGetCompatScale_noGameManager() { assertEquals(mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID), 1f, 0.01f); - } + final ApplicationInfo info = new ApplicationInfo(); + // Any non-zero value without FLAG_SUPPORTS_*_SCREENS. + info.flags = ApplicationInfo.FLAG_HAS_CODE; + info.packageName = info.sourceDir = "legacy.app"; + mAtm.mCompatModePackages.compatibilityInfoForPackageLocked(info); + assertTrue(mAtm.mCompatModePackages.useLegacyScreenCompatMode(info.packageName)); + mAtm.mCompatModePackages.handlePackageUninstalledLocked(info.packageName); + assertFalse(mAtm.mCompatModePackages.useLegacyScreenCompatMode(info.packageName)); + } } |