Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 699174f5 authored by Bartosz Chominski's avatar Bartosz Chominski
Browse files

On locale change update app name in window caption

Store the localeList that was active in system settings at the moment
of caching app resources.
Relayout window decor on locale change.

Fix: 352649989
Flag: com.android.window.flags.enable_desktop_windowing_mode
Test: manual and unit tests
Change-Id: I73bd89f913e155a73019e072ae60a313fd52ac30
parent 449beb9f
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -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()) {
+15 −1
Original line number Diff line number Diff line
@@ -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) {
+46 −0
Original line number Diff line number Diff line
@@ -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;

/**
@@ -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);
+17 −0
Original line number Diff line number Diff line
@@ -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)

@@ -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)