Merge "Implement force app refresh rate policy in window manager" into r-keystone-qcom-dev
diff --git a/services/core/java/com/android/server/wm/ForceRefreshRatePackagelist.java b/services/core/java/com/android/server/wm/ForceRefreshRatePackagelist.java
new file mode 100755
index 0000000..e3377c8
--- /dev/null
+++ b/services/core/java/com/android/server/wm/ForceRefreshRatePackagelist.java
@@ -0,0 +1,130 @@
+/*

+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.

+ *

+ * Not a contribution.

+*/

+

+/*

+ * Copyright (C) 2019 The Android Open Source Project

+ *

+ * Licensed under the Apache License, Version 2.0 (the "License");

+ * you may not use this file except in compliance with the License.

+ * You may obtain a copy of the License at

+ *

+ *      http://www.apache.org/licenses/LICENSE-2.0

+ *

+ * Unless required by applicable law or agreed to in writing, software

+ * distributed under the License is distributed on an "AS IS" BASIS,

+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ * See the License for the specific language governing permissions and

+ * limitations under the License.

+ */

+

+package com.android.server.wm;

+

+import android.annotation.NonNull;

+import android.annotation.Nullable;

+import android.provider.DeviceConfig;

+import android.text.TextUtils;

+import android.util.ArrayMap;

+import android.util.Log;

+import android.view.Display;

+import android.view.DisplayInfo;

+

+import com.android.internal.os.BackgroundThread;

+import com.android.server.wm.utils.DeviceConfigInterface;

+

+

+/**

+ * A list for packages that should force the display out of high refresh rate.

+ */

+class ForceRefreshRatePackageList {

+

+    private static final String TAG = ForceRefreshRatePackageList.class.getSimpleName();

+    private static final String KEY_FORCE_REFRESH_RATE_LIST = "force_refresh_rate_list";

+    private static final float REFRESH_RATE_EPSILON  = 0.01f;

+

+    private final ArrayMap<String, Float> mForcedPackageList = new ArrayMap<>();

+    private final Object mLock = new Object();

+    private DisplayInfo mDisplayInfo;

+    private DeviceConfigInterface mDeviceConfig;

+    private OnPropertiesChangedListener mListener = new OnPropertiesChangedListener();

+

+    private static volatile ForceRefreshRatePackageList mInstance;

+

+    static ForceRefreshRatePackageList getInstance(WindowManagerService wmService) {

+        if (mInstance == null) {

+            synchronized (ForceRefreshRatePackageList.class) {

+                if (mInstance == null) {

+                    mInstance = new ForceRefreshRatePackageList(wmService);

+                }

+            }

+        }

+        return mInstance;

+    }

+

+    private ForceRefreshRatePackageList(WindowManagerService wmService) {

+        mDisplayInfo = wmService.getDefaultDisplayContentLocked().getDisplayInfo();

+        mDeviceConfig = DeviceConfigInterface.REAL;

+        mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,

+                BackgroundThread.getExecutor(), mListener);

+        final String property = mDeviceConfig.getProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,

+                KEY_FORCE_REFRESH_RATE_LIST);

+        updateForcedPackagelist(property);

+    }

+

+    private void updateForcedPackagelist(@Nullable String property) {

+        synchronized (mLock) {

+            mForcedPackageList.clear();

+            if (!TextUtils.isEmpty(property)) {

+                String[] pairs = property.split(";");

+                for (String pair : pairs) {

+                    String[] keyValue = pair.split(",");

+                    if (keyValue != null && keyValue.length == 2) {

+                        if (!TextUtils.isEmpty(keyValue[0].trim())

+                                && !TextUtils.isEmpty(keyValue[1].trim())) {

+                            try {

+                                String packageName = keyValue[0].trim();

+                                Float refreshRate = new Float(keyValue[1].trim());

+                                mForcedPackageList.put(packageName, refreshRate);

+                            } catch (NumberFormatException e) {

+                                Log.e(TAG, "Invalid refresh rate input! input: " + keyValue);

+                            }

+                        }

+                    }

+                }

+            }

+        }

+    }

+

+    int getForceRefreshRateId(String packageName) {

+        synchronized (mLock) {

+            if(mForcedPackageList.containsKey(packageName)) {

+                float refreshRate = mForcedPackageList.get(packageName).floatValue();

+                return findModeByRefreshRate(refreshRate);

+            }else {

+                return 0;

+            }

+        }

+    }

+

+    int findModeByRefreshRate(float refreshRate) {

+        Display.Mode[] modes = mDisplayInfo.supportedModes;

+        for (int i = 0; i < modes.length; i++) {

+            if (Math.abs(modes[i].getRefreshRate() - refreshRate) < REFRESH_RATE_EPSILON) {

+                return modes[i].getModeId();

+            }

+        }

+        return 0;

+    }

+

+    private class OnPropertiesChangedListener implements DeviceConfig.OnPropertiesChangedListener {

+        public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {

+            if (properties.getKeyset().contains(KEY_FORCE_REFRESH_RATE_LIST)) {

+                updateForcedPackagelist(

+                        properties.getString(KEY_FORCE_REFRESH_RATE_LIST, null /*default*/));

+            }

+        }

+    }

+}

+

diff --git a/services/core/java/com/android/server/wm/RefreshRatePolicy.java b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
old mode 100644
new mode 100755
index 2cb7d5a..7544e73
--- a/services/core/java/com/android/server/wm/RefreshRatePolicy.java
+++ b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
@@ -95,6 +95,13 @@
             return 0;
         }
 
+        // If app is forced to specified refresh rate, return the specified refresh rate
+        ForceRefreshRatePackageList forceList = ForceRefreshRatePackageList.getInstance(mWmService);
+        int forceRefreshRateId = forceList.getForceRefreshRateId(w.getOwningPackage());
+        if(forceRefreshRateId > 0) {
+            return forceRefreshRateId;
+        }
+
         // If app requests a certain refresh rate or mode, don't override it.
         if (w.mAttrs.preferredRefreshRate != 0 || w.mAttrs.preferredDisplayModeId != 0) {
             return w.mAttrs.preferredDisplayModeId;