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