Loading services/core/java/com/android/server/wm/DisplayContent.java +8 −2 Original line number Diff line number Diff line Loading @@ -154,6 +154,7 @@ import com.android.internal.annotations.VisibleForTesting; 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; Loading Loading @@ -215,7 +216,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo int mInitialDisplayDensity = 0; DisplayCutout mInitialDisplayCutout; DisplayCutout mDisplayCutoutOverride; private final RotationCache<DisplayCutout, DisplayCutout> mDisplayCutoutCache = new RotationCache<>(this::calculateDisplayCutoutForRotationUncached); /** * Overridden display size. Initialized with {@link #mInitialDisplayWidth} Loading Loading @@ -1198,7 +1200,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } 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; } Loading services/core/java/com/android/server/wm/DockedStackDividerController.java +1 −1 Original line number Diff line number Diff line Loading @@ -174,7 +174,7 @@ public class DockedStackDividerController { 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 Loading services/core/java/com/android/server/wm/utils/RotationCache.java 0 → 100644 +70 −0 Original line number Diff line number Diff line /* * 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); } } services/tests/servicestests/src/com/android/server/wm/utils/RotationCacheTest.java 0 → 100644 +103 −0 Original line number Diff line number Diff line /* * 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 static android.util.Pair.create; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.util.Pair; import com.android.server.wm.utils.RotationCache.RotationDependentComputation; import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit public class RotationCacheTest { private RotationCache<Object, Pair<Object, Integer>> mCache; private boolean mComputationCalled; @Before public void setUp() throws Exception { mComputationCalled = false; mCache = new RotationCache<>((o, rot) -> { mComputationCalled = true; return create(o, rot); }); } @Test public void getOrCompute_computes() throws Exception { assertThat(mCache.getOrCompute("hello", 0), equalTo(create("hello", 0))); assertThat(mCache.getOrCompute("hello", 1), equalTo(create("hello", 1))); assertThat(mCache.getOrCompute("hello", 2), equalTo(create("hello", 2))); assertThat(mCache.getOrCompute("hello", 3), equalTo(create("hello", 3))); } @Test public void getOrCompute_sameParam_sameRot_hitsCache() throws Exception { assertNotNull(mCache.getOrCompute("hello", 1)); mComputationCalled = false; assertThat(mCache.getOrCompute("hello", 1), equalTo(create("hello", 1))); assertThat(mComputationCalled, is(false)); } @Test public void getOrCompute_sameParam_hitsCache_forAllRots() throws Exception { assertNotNull(mCache.getOrCompute("hello", 3)); assertNotNull(mCache.getOrCompute("hello", 2)); assertNotNull(mCache.getOrCompute("hello", 1)); assertNotNull(mCache.getOrCompute("hello", 0)); mComputationCalled = false; assertThat(mCache.getOrCompute("hello", 1), equalTo(create("hello", 1))); assertThat(mCache.getOrCompute("hello", 0), equalTo(create("hello", 0))); assertThat(mCache.getOrCompute("hello", 2), equalTo(create("hello", 2))); assertThat(mCache.getOrCompute("hello", 3), equalTo(create("hello", 3))); assertThat(mComputationCalled, is(false)); } @Test public void getOrCompute_changingParam_recomputes() throws Exception { assertNotNull(mCache.getOrCompute("hello", 1)); assertThat(mCache.getOrCompute("world", 1), equalTo(create("world", 1))); } @Test public void getOrCompute_changingParam_clearsCacheForDifferentRots() throws Exception { assertNotNull(mCache.getOrCompute("hello", 1)); assertNotNull(mCache.getOrCompute("world", 2)); mComputationCalled = false; assertThat(mCache.getOrCompute("hello", 1), equalTo(create("hello", 1))); assertThat(mComputationCalled, is(true)); } } No newline at end of file Loading
services/core/java/com/android/server/wm/DisplayContent.java +8 −2 Original line number Diff line number Diff line Loading @@ -154,6 +154,7 @@ import com.android.internal.annotations.VisibleForTesting; 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; Loading Loading @@ -215,7 +216,8 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo int mInitialDisplayDensity = 0; DisplayCutout mInitialDisplayCutout; DisplayCutout mDisplayCutoutOverride; private final RotationCache<DisplayCutout, DisplayCutout> mDisplayCutoutCache = new RotationCache<>(this::calculateDisplayCutoutForRotationUncached); /** * Overridden display size. Initialized with {@link #mInitialDisplayWidth} Loading Loading @@ -1198,7 +1200,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } 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; } Loading
services/core/java/com/android/server/wm/DockedStackDividerController.java +1 −1 Original line number Diff line number Diff line Loading @@ -174,7 +174,7 @@ public class DockedStackDividerController { 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 Loading
services/core/java/com/android/server/wm/utils/RotationCache.java 0 → 100644 +70 −0 Original line number Diff line number Diff line /* * 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); } }
services/tests/servicestests/src/com/android/server/wm/utils/RotationCacheTest.java 0 → 100644 +103 −0 Original line number Diff line number Diff line /* * 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 static android.util.Pair.create; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import android.platform.test.annotations.Presubmit; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.util.Pair; import com.android.server.wm.utils.RotationCache.RotationDependentComputation; import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit public class RotationCacheTest { private RotationCache<Object, Pair<Object, Integer>> mCache; private boolean mComputationCalled; @Before public void setUp() throws Exception { mComputationCalled = false; mCache = new RotationCache<>((o, rot) -> { mComputationCalled = true; return create(o, rot); }); } @Test public void getOrCompute_computes() throws Exception { assertThat(mCache.getOrCompute("hello", 0), equalTo(create("hello", 0))); assertThat(mCache.getOrCompute("hello", 1), equalTo(create("hello", 1))); assertThat(mCache.getOrCompute("hello", 2), equalTo(create("hello", 2))); assertThat(mCache.getOrCompute("hello", 3), equalTo(create("hello", 3))); } @Test public void getOrCompute_sameParam_sameRot_hitsCache() throws Exception { assertNotNull(mCache.getOrCompute("hello", 1)); mComputationCalled = false; assertThat(mCache.getOrCompute("hello", 1), equalTo(create("hello", 1))); assertThat(mComputationCalled, is(false)); } @Test public void getOrCompute_sameParam_hitsCache_forAllRots() throws Exception { assertNotNull(mCache.getOrCompute("hello", 3)); assertNotNull(mCache.getOrCompute("hello", 2)); assertNotNull(mCache.getOrCompute("hello", 1)); assertNotNull(mCache.getOrCompute("hello", 0)); mComputationCalled = false; assertThat(mCache.getOrCompute("hello", 1), equalTo(create("hello", 1))); assertThat(mCache.getOrCompute("hello", 0), equalTo(create("hello", 0))); assertThat(mCache.getOrCompute("hello", 2), equalTo(create("hello", 2))); assertThat(mCache.getOrCompute("hello", 3), equalTo(create("hello", 3))); assertThat(mComputationCalled, is(false)); } @Test public void getOrCompute_changingParam_recomputes() throws Exception { assertNotNull(mCache.getOrCompute("hello", 1)); assertThat(mCache.getOrCompute("world", 1), equalTo(create("world", 1))); } @Test public void getOrCompute_changingParam_clearsCacheForDifferentRots() throws Exception { assertNotNull(mCache.getOrCompute("hello", 1)); assertNotNull(mCache.getOrCompute("world", 2)); mComputationCalled = false; assertThat(mCache.getOrCompute("hello", 1), equalTo(create("hello", 1))); assertThat(mComputationCalled, is(true)); } } No newline at end of file