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

Commit 335ec4dd authored by Michael Wright's avatar Michael Wright Committed by Android (Google) Code Review
Browse files

Merge "Read the high refresh rate blacklist from DeviceConfig."

parents 4e89e6ff f40ed275
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -344,6 +344,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 90hz.
         *
         * @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
@@ -4225,4 +4225,8 @@
    the default implementation of ACTION_FACTORY_RESET does not work, so it is needed to re-route
    this intent to this package. This is being used in MasterClearReceiver.java. -->
    <string name="config_factoryResetPackage" translatable="false"></string>

    <!-- 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>
+1 −0
Original line number Diff line number Diff line
@@ -3828,4 +3828,5 @@
  <java-symbol type="integer" name="config_notificationStripRemoteViewSizeBytes" />

  <java-symbol type="string" name="config_factoryResetPackage" />
  <java-symbol type="array" name="config_highRefreshRateBlacklist" />
</resources>
+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 addOnPropertiesChangedListener(@NonNull String namespace,
                    @NonNull Executor executor,
                    @NonNull DeviceConfig.OnPropertiesChangedListener listener) {
                DeviceConfig.addOnPropertiesChangedListener(namespace, executor, listener);
            }
        });
    }

    @VisibleForTesting
    HighRefreshRateBlacklist(SystemPropertyGetter propertyGetter) {
    HighRefreshRateBlacklist(Resources r, DeviceConfigInterface deviceConfig) {
        mDefaultBlacklist = r.getStringArray(R.array.config_highRefreshRateBlacklist);
        deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                BackgroundThread.getExecutor(), new OnPropertiesChangedListener());
        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 addOnPropertiesChangedListener(@NonNull String namespace, @NonNull Executor executor,
                @NonNull DeviceConfig.OnPropertiesChangedListener listener);
    }

    private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener {
        public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
            updateBlacklist(
                    properties.getString(KEY_HIGH_REFRESH_RATE_BLACKLIST, null /*default*/));
        }
    }
}
+16 −1
Original line number Diff line number Diff line
@@ -856,7 +856,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.
@@ -1143,6 +1143,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));
@@ -5897,6 +5899,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");
@@ -6297,6 +6305,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)) {
@@ -6352,6 +6363,10 @@ public class WindowManagerService extends IWindowManager.Stub
                pw.println(separator);
            }
            dumpTraceStatus(pw);
            if (dumpAll) {
                pw.println(separator);
            }
            dumpHighRefreshRateBlacklist(pw);
        }
    }

Loading