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

Commit 000c605f authored by Michael Wright's avatar Michael Wright Committed by android-build-merger
Browse files

Merge "Read the high refresh rate blacklist from DeviceConfig." into qt-r1-dev

am: 6173ba74

Change-Id: I443831f56e417efe3a124cb0a09ae25b1946bc3a
parents f5ce2124 6173ba74
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -336,6 +336,15 @@ public final class DeviceConfig {
        @TestApi
        String KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE =
                "system_gestures_excluded_by_pre_q_sticky_immersive";

        /**
         * Key for controlling which packages are explicitly blocked from running at refresh rates
         * higher than 60hz.
         *
         * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
         * @hide
         */
        String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
    }

    private static final Object sLock = new Object();
+4 −0
Original line number Diff line number Diff line
@@ -4208,4 +4208,8 @@

    <!-- Sharesheet: define a max number of targets per application for new shortcuts-based direct share introduced in Q -->
    <integer name="config_maxShortcutTargetsPerApp">3</integer>

    <!-- The list of packages to automatically opt out of refresh rates higher than 60hz because
         of known compatibility issues. -->
    <string-array name="config_highRefreshRateBlacklist"></string-array>
</resources>
+2 −0
Original line number Diff line number Diff line
@@ -3822,6 +3822,8 @@
  <java-symbol type="string" name="config_defaultSupervisionProfileOwnerComponent" />
  <java-symbol type="bool" name="config_inflateSignalStrength" />

  <java-symbol type="array" name="config_highRefreshRateBlacklist" />

  <java-symbol type="drawable" name="android_logotype" />
  <java-symbol type="layout" name="platlogo_layout" />

+71 −29
Original line number Diff line number Diff line
@@ -16,60 +16,102 @@

package com.android.server.wm;

import static android.provider.DeviceConfig.WindowManager.KEY_HIGH_REFRESH_RATE_BLACKLIST;

import android.annotation.NonNull;
import android.os.SystemProperties;
import android.annotation.Nullable;
import android.content.res.Resources;
import android.provider.DeviceConfig;
import android.util.ArraySet;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;

import java.io.PrintWriter;
import java.util.concurrent.Executor;

/**
 * A Blacklist for packages that should force the display out of high refresh rate.
 */
class HighRefreshRateBlacklist {

    private static final String SYSPROP_KEY = "ro.window_manager.high_refresh_rate_blacklist";
    private static final String SYSPROP_KEY_LENGTH_SUFFIX = "_length";
    private static final String SYSPROP_KEY_ENTRY_SUFFIX = "_entry";
    private static final int MAX_ENTRIES = 50;

    private ArraySet<String> mBlacklistedPackages = new ArraySet<>();
    private final ArraySet<String> mBlacklistedPackages = new ArraySet<>();
    @NonNull
    private final String[] mDefaultBlacklist;
    private final Object mLock = new Object();

    static HighRefreshRateBlacklist create() {
        return new HighRefreshRateBlacklist(new SystemPropertyGetter() {
    static HighRefreshRateBlacklist create(@NonNull Resources r) {
        return new HighRefreshRateBlacklist(r, new DeviceConfigInterface() {
            @Override
            public int getInt(String key, int def) {
                return SystemProperties.getInt(key, def);
            public @Nullable String getProperty(@NonNull String namespace, @NonNull String name) {
                return DeviceConfig.getProperty(namespace, name);
            }

            @Override
            public String get(String key) {
                return SystemProperties.get(key);
            public void addOnPropertyChangedListener(@NonNull String namespace,
                    @NonNull Executor executor,
                    @NonNull DeviceConfig.OnPropertyChangedListener listener) {
                DeviceConfig.addOnPropertyChangedListener(namespace, executor, listener);
            }
        });
    }

    @VisibleForTesting
    HighRefreshRateBlacklist(SystemPropertyGetter propertyGetter) {
    HighRefreshRateBlacklist(Resources r, DeviceConfigInterface deviceConfig) {
        mDefaultBlacklist = r.getStringArray(R.array.config_highRefreshRateBlacklist);
        deviceConfig.addOnPropertyChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                BackgroundThread.getExecutor(), new OnPropertyChangedListener());
        final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                KEY_HIGH_REFRESH_RATE_BLACKLIST);
        updateBlacklist(property);
    }

        // Read and populate the blacklist
        final int length = Math.min(
                propertyGetter.getInt(SYSPROP_KEY + SYSPROP_KEY_LENGTH_SUFFIX, 0),
                MAX_ENTRIES);
        for (int i = 1; i <= length; i++) {
            final String packageName = propertyGetter.get(
                    SYSPROP_KEY + SYSPROP_KEY_ENTRY_SUFFIX + i);
            if (!packageName.isEmpty()) {
                mBlacklistedPackages.add(packageName);
    private void updateBlacklist(@Nullable String property) {
        synchronized (mLock) {
            mBlacklistedPackages.clear();
            if (property != null) {
                String[] packages = property.split(",");
                for (String pkg : packages) {
                    String pkgName = pkg.trim();
                    if (!pkgName.isEmpty()) {
                        mBlacklistedPackages.add(pkgName);
                    }
                }
            } else {
                // If there's no config, or the config has been deleted, fallback to the device's
                // default blacklist
                for (String pkg : mDefaultBlacklist) {
                    mBlacklistedPackages.add(pkg);
                }
            }
        }
    }

    boolean isBlacklisted(String packageName) {
        synchronized (mLock) {
            return mBlacklistedPackages.contains(packageName);
        }
    }
    void dump(PrintWriter pw) {
        pw.println("High Refresh Rate Blacklist");
        pw.println("  Packages:");
        synchronized (mLock) {
            for (String pkg : mBlacklistedPackages) {
                pw.println("    " + pkg);
            }
        }
    }

    interface SystemPropertyGetter {
        int getInt(String key, int def);
        @NonNull String get(String key);
    interface DeviceConfigInterface {
        @Nullable String getProperty(@NonNull String namespace, @NonNull String name);
        void addOnPropertyChangedListener(@NonNull String namespace, @NonNull Executor executor,
                @NonNull DeviceConfig.OnPropertyChangedListener listener);
    }

    private class OnPropertyChangedListener implements DeviceConfig.OnPropertyChangedListener {
        public void onPropertyChanged(@NonNull String namespace, @NonNull String name,
                @Nullable String value) {
            updateBlacklist(value);
        }
    }
}
+16 −1
Original line number Diff line number Diff line
@@ -854,7 +854,7 @@ public class WindowManagerService extends IWindowManager.Stub

    final Configuration mTempConfiguration = new Configuration();

    final HighRefreshRateBlacklist mHighRefreshRateBlacklist = HighRefreshRateBlacklist.create();
    final HighRefreshRateBlacklist mHighRefreshRateBlacklist;

    // If true, only the core apps and services are being launched because the device
    // is in a special boot mode, such as being encrypted or waiting for a decryption password.
@@ -1141,6 +1141,8 @@ public class WindowManagerService extends IWindowManager.Stub
                this, mInputManager, mActivityTaskManager, mH.getLooper());
        mDragDropController = new DragDropController(this, mH.getLooper());

        mHighRefreshRateBlacklist = HighRefreshRateBlacklist.create(context.getResources());

        mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
                DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                        KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
@@ -5922,6 +5924,12 @@ public class WindowManagerService extends IWindowManager.Stub
        mRoot.dumpTokens(pw, dumpAll);
    }


    private void dumpHighRefreshRateBlacklist(PrintWriter pw) {
        pw.println("WINDOW MANAGER HIGH REFRESH RATE BLACKLIST (dumpsys window refresh)");
        mHighRefreshRateBlacklist.dump(pw);
    }

    private void dumpTraceStatus(PrintWriter pw) {
        pw.println("WINDOW MANAGER TRACE (dumpsys window trace)");
        pw.print(mWindowTracing.getStatus() + "\n");
@@ -6321,6 +6329,9 @@ public class WindowManagerService extends IWindowManager.Stub
            } else if ("trace".equals(cmd)) {
                dumpTraceStatus(pw);
                return;
            } else if ("refresh".equals(cmd)) {
                dumpHighRefreshRateBlacklist(pw);
                return;
            } else {
                // Dumping a single name?
                if (!dumpWindows(pw, cmd, args, opti, dumpAll)) {
@@ -6376,6 +6387,10 @@ public class WindowManagerService extends IWindowManager.Stub
                pw.println(separator);
            }
            dumpTraceStatus(pw);
            if (dumpAll) {
                pw.println(separator);
            }
            dumpHighRefreshRateBlacklist(pw);
        }
    }

Loading