diff options
4 files changed, 83 insertions, 2 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java index 7baef2b2dc97..bde46a1bc375 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java @@ -361,6 +361,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> outResult.mRootView = rootView; final boolean fontScaleChanged = mWindowDecorConfig != null && mWindowDecorConfig.fontScale != mTaskInfo.configuration.fontScale; + final boolean localeListChanged = mWindowDecorConfig != null + && !mWindowDecorConfig.getLocales() + .equals(mTaskInfo.getConfiguration().getLocales()); final int oldDensityDpi = mWindowDecorConfig != null ? mWindowDecorConfig.densityDpi : DENSITY_DPI_UNDEFINED; final int oldNightMode = mWindowDecorConfig != null @@ -376,7 +379,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> || oldLayoutResId != mLayoutResId || oldNightMode != newNightMode || mDecorWindowContext == null - || fontScaleChanged) { + || fontScaleChanged + || localeListChanged) { releaseViews(wct); if (!obtainDisplayOrRegisterListener()) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoader.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoader.kt index 801048adda4d..957898fd0088 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoader.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoader.kt @@ -21,6 +21,7 @@ import android.content.Context import android.content.pm.ActivityInfo import android.content.pm.PackageManager import android.graphics.Bitmap +import android.os.LocaleList import android.os.UserHandle import androidx.tracing.Trace import com.android.internal.annotations.VisibleForTesting @@ -80,6 +81,13 @@ class WindowDecorTaskResourceLoader( */ private val existingTasks = mutableSetOf<Int>() + /** + * A map of task -> localeList to keep track of the language of app name that's currently + * cached in |taskToResourceCache|. + */ + @VisibleForTesting + val localeListOnCache = ConcurrentHashMap<Int, LocaleList>() + init { shellInit.addInitCallback(this::onInit, this) } @@ -99,11 +107,14 @@ class WindowDecorTaskResourceLoader( fun getName(taskInfo: RunningTaskInfo): CharSequence { checkWindowDecorExists(taskInfo) val cachedResources = taskToResourceCache[taskInfo.taskId] - if (cachedResources != null) { + val localeListActiveOnCacheTime = localeListOnCache[taskInfo.taskId] + if (cachedResources != null && + taskInfo.getConfiguration().getLocales().equals(localeListActiveOnCacheTime)) { return cachedResources.appName } val resources = loadAppResources(taskInfo) taskToResourceCache[taskInfo.taskId] = resources + localeListOnCache[taskInfo.taskId] = taskInfo.getConfiguration().getLocales() return resources.appName } @@ -117,6 +128,7 @@ class WindowDecorTaskResourceLoader( } val resources = loadAppResources(taskInfo) taskToResourceCache[taskInfo.taskId] = resources + localeListOnCache[taskInfo.taskId] = taskInfo.getConfiguration().getLocales() return resources.appIcon } @@ -130,6 +142,7 @@ class WindowDecorTaskResourceLoader( } val resources = loadAppResources(taskInfo) taskToResourceCache[taskInfo.taskId] = resources + localeListOnCache[taskInfo.taskId] = taskInfo.getConfiguration().getLocales() return resources.veilIcon } @@ -142,6 +155,7 @@ class WindowDecorTaskResourceLoader( fun onWindowDecorClosed(taskInfo: RunningTaskInfo) { existingTasks.remove(taskInfo.taskId) taskToResourceCache.remove(taskInfo.taskId) + localeListOnCache.remove(taskInfo.taskId) } private fun checkWindowDecorExists(taskInfo: RunningTaskInfo) { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java index a2927fa3527b..9a2e2fad50be 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java @@ -60,6 +60,7 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; import android.os.Handler; +import android.os.LocaleList; import android.testing.AndroidTestingRunner; import android.util.DisplayMetrics; import android.view.AttachedSurfaceControl; @@ -97,6 +98,7 @@ import org.mockito.Mockito; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.function.Supplier; /** @@ -475,6 +477,50 @@ public class WindowDecorationTests extends ShellTestCase { } @Test + public void testReinflateViewsOnLocaleListChange() { + final Display defaultDisplay = mock(Display.class); + doReturn(defaultDisplay).when(mMockDisplayController) + .getDisplay(Display.DEFAULT_DISPLAY); + + final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder() + .setVisible(true) + .setDisplayId(Display.DEFAULT_DISPLAY) + .build(); + taskInfo.configuration.setLocales(new LocaleList(Locale.FRANCE, Locale.US)); + final TestWindowDecoration windowDecor = spy(createWindowDecoration(taskInfo)); + windowDecor.relayout(taskInfo, true /* hasGlobalFocus */, Region.obtain()); + clearInvocations(windowDecor); + + final ActivityManager.RunningTaskInfo taskInfo2 = new TestRunningTaskInfoBuilder() + .setVisible(true) + .setDisplayId(Display.DEFAULT_DISPLAY) + .build(); + taskInfo2.configuration.setLocales(new LocaleList(Locale.US, Locale.FRANCE)); + windowDecor.relayout(taskInfo2, true /* hasGlobalFocus */, Region.obtain()); + // WindowDecoration#releaseViews should be called since the locale list has changed. + verify(windowDecor, times(1)).releaseViews(any()); + } + + @Test + public void testViewNotReinflatedWhenLocaleListNotChanged() { + final Display defaultDisplay = mock(Display.class); + doReturn(defaultDisplay).when(mMockDisplayController) + .getDisplay(Display.DEFAULT_DISPLAY); + + final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder() + .setVisible(true) + .setDisplayId(Display.DEFAULT_DISPLAY) + .build(); + taskInfo.configuration.setLocales(new LocaleList(Locale.FRANCE, Locale.US)); + final TestWindowDecoration windowDecor = spy(createWindowDecoration(taskInfo)); + windowDecor.relayout(taskInfo, true /* hasGlobalFocus */, Region.obtain()); + clearInvocations(windowDecor); + windowDecor.relayout(taskInfo, true /* hasGlobalFocus */, Region.obtain()); + // WindowDecoration#releaseViews should not be called since nothing has changed. + verify(windowDecor, never()).releaseViews(any()); + } + + @Test public void testLayoutResultCalculation_fullWidthCaption() { final Display defaultDisplay = mock(Display.class); doReturn(defaultDisplay).when(mMockDisplayController) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoaderTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoaderTest.kt index c61e0eb3b5af..c8ccac35d4c4 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoaderTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoaderTest.kt @@ -23,6 +23,7 @@ import android.content.pm.ActivityInfo import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.graphics.drawable.Drawable +import android.os.LocaleList import android.os.UserHandle import android.testing.AndroidTestingRunner import android.testing.TestableContext @@ -39,6 +40,7 @@ import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.sysui.UserChangeListener import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader.AppResources import com.google.common.truth.Truth.assertThat +import java.util.Locale import org.junit.Assert.assertThrows import org.junit.Before import org.junit.Test @@ -116,8 +118,10 @@ class WindowDecorTaskResourceLoaderTest : ShellTestCase() { @Test fun testGetName_cached_returnsFromCache() { val task = createTaskInfo(context.userId) + task.configuration.setLocales(LocaleList(Locale.US)) loader.onWindowDecorCreated(task) loader.taskToResourceCache[task.taskId] = AppResources("App Name", mock(), mock()) + loader.localeListOnCache[task.taskId] = LocaleList(Locale.US) loader.getName(task) @@ -130,6 +134,19 @@ class WindowDecorTaskResourceLoaderTest : ShellTestCase() { } @Test + fun testGetName_cached_localesChanged_loadsResourceAndCaches() { + val task = createTaskInfo(context.userId) + loader.onWindowDecorCreated(task) + loader.taskToResourceCache[task.taskId] = AppResources("App Name", mock(), mock()) + loader.localeListOnCache[task.taskId] = LocaleList(Locale.US, Locale.FRANCE) + task.configuration.setLocales(LocaleList(Locale.FRANCE, Locale.US)) + doReturn("App Name but in French").whenever(mockPackageManager).getApplicationLabel(any()) + + assertThat(loader.getName(task)).isEqualTo("App Name but in French") + assertThat(loader.taskToResourceCache[task.taskId]?.appName).isEqualTo("App Name but in French") + } + + @Test fun testGetHeaderIcon_notCached_loadsResourceAndCaches() { val task = createTaskInfo(context.userId) loader.onWindowDecorCreated(task) |