Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +5 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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()) { Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoader.kt +15 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) } Loading @@ -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 } Loading @@ -117,6 +128,7 @@ class WindowDecorTaskResourceLoader( } val resources = loadAppResources(taskInfo) taskToResourceCache[taskInfo.taskId] = resources localeListOnCache[taskInfo.taskId] = taskInfo.getConfiguration().getLocales() return resources.appIcon } Loading @@ -130,6 +142,7 @@ class WindowDecorTaskResourceLoader( } val resources = loadAppResources(taskInfo) taskToResourceCache[taskInfo.taskId] = resources localeListOnCache[taskInfo.taskId] = taskInfo.getConfiguration().getLocales() return resources.veilIcon } Loading @@ -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) { Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java +46 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; /** Loading Loading @@ -474,6 +476,50 @@ public class WindowDecorationTests extends ShellTestCase { verify(mMockSurfaceControlViewHostFactory).create(any(), eq(defaultDisplay), any()); } @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); Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoaderTest.kt +17 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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) Loading @@ -129,6 +133,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) Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +5 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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()) { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoader.kt +15 −1 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) } Loading @@ -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 } Loading @@ -117,6 +128,7 @@ class WindowDecorTaskResourceLoader( } val resources = loadAppResources(taskInfo) taskToResourceCache[taskInfo.taskId] = resources localeListOnCache[taskInfo.taskId] = taskInfo.getConfiguration().getLocales() return resources.appIcon } Loading @@ -130,6 +142,7 @@ class WindowDecorTaskResourceLoader( } val resources = loadAppResources(taskInfo) taskToResourceCache[taskInfo.taskId] = resources localeListOnCache[taskInfo.taskId] = taskInfo.getConfiguration().getLocales() return resources.veilIcon } Loading @@ -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) { Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java +46 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; /** Loading Loading @@ -474,6 +476,50 @@ public class WindowDecorationTests extends ShellTestCase { verify(mMockSurfaceControlViewHostFactory).create(any(), eq(defaultDisplay), any()); } @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); Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/common/WindowDecorTaskResourceLoaderTest.kt +17 −0 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -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) Loading @@ -129,6 +133,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) Loading