1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static android.hardware.display.DisplayManager.DeviceConfig.KEY_HIGH_REFRESH_RATE_BLACKLIST; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.content.res.Resources; 24 import android.provider.DeviceConfig; 25 import android.provider.DeviceConfigInterface; 26 import android.util.ArraySet; 27 28 import com.android.internal.R; 29 import com.android.internal.annotations.VisibleForTesting; 30 import com.android.internal.os.BackgroundThread; 31 32 import java.io.PrintWriter; 33 34 /** 35 * A Denylist for packages that should force the display out of high refresh rate. 36 */ 37 class HighRefreshRateDenylist { 38 39 private final ArraySet<String> mDenylistedPackages = new ArraySet<>(); 40 @NonNull 41 private final String[] mDefaultDenylist; 42 private final Object mLock = new Object(); 43 create(@onNull Resources r)44 static HighRefreshRateDenylist create(@NonNull Resources r) { 45 return new HighRefreshRateDenylist(r, DeviceConfigInterface.REAL); 46 } 47 48 @VisibleForTesting HighRefreshRateDenylist(Resources r, DeviceConfigInterface deviceConfig)49 HighRefreshRateDenylist(Resources r, DeviceConfigInterface deviceConfig) { 50 mDefaultDenylist = r.getStringArray(R.array.config_highRefreshRateBlacklist); 51 deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, 52 BackgroundThread.getExecutor(), new OnPropertiesChangedListener()); 53 final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, 54 KEY_HIGH_REFRESH_RATE_BLACKLIST); 55 updateDenylist(property); 56 } 57 updateDenylist(@ullable String property)58 private void updateDenylist(@Nullable String property) { 59 synchronized (mLock) { 60 mDenylistedPackages.clear(); 61 if (property != null) { 62 String[] packages = property.split(","); 63 for (String pkg : packages) { 64 String pkgName = pkg.trim(); 65 if (!pkgName.isEmpty()) { 66 mDenylistedPackages.add(pkgName); 67 } 68 } 69 } else { 70 // If there's no config, or the config has been deleted, fallback to the device's 71 // default denylist 72 for (String pkg : mDefaultDenylist) { 73 mDenylistedPackages.add(pkg); 74 } 75 } 76 } 77 } 78 isDenylisted(String packageName)79 boolean isDenylisted(String packageName) { 80 synchronized (mLock) { 81 return mDenylistedPackages.contains(packageName); 82 } 83 } dump(PrintWriter pw)84 void dump(PrintWriter pw) { 85 pw.println("High Refresh Rate Denylist"); 86 pw.println(" Packages:"); 87 synchronized (mLock) { 88 for (String pkg : mDenylistedPackages) { 89 pw.println(" " + pkg); 90 } 91 } 92 } 93 94 private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener { onPropertiesChanged(@onNull DeviceConfig.Properties properties)95 public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) { 96 if (properties.getKeyset().contains(KEY_HIGH_REFRESH_RATE_BLACKLIST)) { 97 updateDenylist( 98 properties.getString(KEY_HIGH_REFRESH_RATE_BLACKLIST, null /*default*/)); 99 } 100 } 101 } 102 } 103 104