DisplayCutout: Cache rotations of DisplayCutout
Caches the result of the DisplayCutout computation for all rotations.
With the fix to 72444324, the rotated DisplayCutout is recomputed a
lot more frequently for all rotations.
Bug: 72444324
Test: atest RotationCacheTest
Change-Id: Id413cf35fc2a6e77f738f0e3b42971e0387fd7bb
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 473eeda..13357b8 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -154,6 +154,7 @@
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.view.IInputMethodClient;
import com.android.server.policy.WindowManagerPolicy;
+import com.android.server.wm.utils.RotationCache;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -215,7 +216,8 @@
int mInitialDisplayDensity = 0;
DisplayCutout mInitialDisplayCutout;
- DisplayCutout mDisplayCutoutOverride;
+ private final RotationCache<DisplayCutout, DisplayCutout> mDisplayCutoutCache
+ = new RotationCache<>(this::calculateDisplayCutoutForRotationUncached);
/**
* Overridden display size. Initialized with {@link #mInitialDisplayWidth}
@@ -1198,7 +1200,11 @@
}
DisplayCutout calculateDisplayCutoutForRotation(int rotation) {
- final DisplayCutout cutout = mInitialDisplayCutout;
+ return mDisplayCutoutCache.getOrCompute(mInitialDisplayCutout, rotation);
+ }
+
+ private DisplayCutout calculateDisplayCutoutForRotationUncached(
+ DisplayCutout cutout, int rotation) {
if (cutout == null || cutout == DisplayCutout.NO_CUTOUT) {
return cutout;
}
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 423be63..5c8fadb 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -174,7 +174,7 @@
final int position = DockedDividerUtils.calculatePositionForBounds(mTmpRect, dockSide,
getContentWidth());
- DisplayCutout displayCutout = mDisplayContent.calculateDisplayCutoutForRotation(
+ final DisplayCutout displayCutout = mDisplayContent.calculateDisplayCutoutForRotation(
rotation);
// Since we only care about feasible states, snap to the closest snap target, like it
diff --git a/services/core/java/com/android/server/wm/utils/RotationCache.java b/services/core/java/com/android/server/wm/utils/RotationCache.java
new file mode 100644
index 0000000..7a06cbc
--- /dev/null
+++ b/services/core/java/com/android/server/wm/utils/RotationCache.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2018 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.utils;
+
+import android.util.SparseArray;
+
+import java.util.Arrays;
+
+/**
+ * Caches the result of a rotation-dependent computation.
+ *
+ * The cache is discarded once the identity of the other parameter changes.
+ *
+ * @param <T> type of the parameter to the computation
+ * @param <R> type of the result of the computation
+ */
+public class RotationCache<T,R> {
+
+ private final RotationDependentComputation<T,R> mComputation;
+ private final SparseArray<R> mCache = new SparseArray<>(4);
+ private T mCachedFor;
+
+ public RotationCache(RotationDependentComputation<T, R> computation) {
+ mComputation = computation;
+ }
+
+ /**
+ * Looks up the result of the computation, or calculates it if needed.
+ *
+ * @param t a parameter to the rotation-dependent computation.
+ * @param rotation the rotation for which to perform the rotation-dependent computation.
+ * @return the result of the rotation-dependent computation.
+ */
+ public R getOrCompute(T t, int rotation) {
+ if (t != mCachedFor) {
+ mCache.clear();
+ mCachedFor = t;
+ }
+ final int idx = mCache.indexOfKey(rotation);
+ if (idx >= 0) {
+ return mCache.valueAt(idx);
+ }
+ final R result = mComputation.compute(t, rotation);
+ mCache.put(rotation, result);
+ return result;
+ }
+
+ /**
+ * A computation that takes a generic input and is dependent on the rotation. The result can
+ * be cached by {@link RotationCache}.
+ */
+ @FunctionalInterface
+ public interface RotationDependentComputation<T, R> {
+ R compute(T t, int rotation);
+ }
+}