blob: e6dc4db34f91ea8f98ff49f56fa375477056c388 [file] [log] [blame]
/*
* Copyright (C) 2019 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.systemui.theme;
import static com.android.systemui.theme.ThemeOverlayApplier.ANDROID_PACKAGE;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ACCENT_COLOR;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_FONT;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ICON_ANDROID;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ICON_LAUNCHER;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ICON_SETTINGS;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ICON_SYSUI;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_ICON_THEME_PICKER;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_SHAPE;
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_CATEGORY_SYSTEM_PALETTE;
import static com.android.systemui.theme.ThemeOverlayApplier.SETTINGS_PACKAGE;
import static com.android.systemui.theme.ThemeOverlayApplier.SYSTEM_USER_CATEGORIES;
import static com.android.systemui.theme.ThemeOverlayApplier.SYSUI_PACKAGE;
import static com.android.systemui.theme.ThemeOverlayApplier.THEME_CATEGORIES;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.om.FabricatedOverlay;
import android.content.om.OverlayIdentifier;
import android.content.om.OverlayInfo;
import android.content.om.OverlayManager;
import android.content.om.OverlayManagerTransaction;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.google.android.collect.Maps;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.MoreExecutors;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class ThemeOverlayApplierTest extends SysuiTestCase {
private static final String TEST_DISABLED_PREFIX = "com.example.";
private static final String TEST_ENABLED_PREFIX = "com.example.enabled.";
private static final Map<String, OverlayIdentifier> ALL_CATEGORIES_MAP = Maps.newArrayMap();
static {
for (String category : THEME_CATEGORIES) {
ALL_CATEGORIES_MAP.put(category,
new OverlayIdentifier(TEST_DISABLED_PREFIX + category));
}
}
private static final String THEMEPICKER_PACKAGE = "com.android.wallpaper";
private static final String LAUNCHER_PACKAGE = "com.android.launcher3";
private static final UserHandle TEST_USER = UserHandle.of(5);
private static final UserHandle TEST_USER_MANAGED_PROFILE = UserHandle.of(6);
private static final Set<UserHandle> TEST_USER_HANDLES =
Sets.newHashSet(TEST_USER_MANAGED_PROFILE);
@Mock
OverlayManager mOverlayManager;
@Mock
DumpManager mDumpManager;
@Mock
OverlayManagerTransaction.Builder mTransactionBuilder;
@Mock
Runnable mOnOverlaysApplied;
private ThemeOverlayApplier mManager;
private boolean mGetOverlayInfoEnabled = true;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
mManager = new ThemeOverlayApplier(mOverlayManager,
MoreExecutors.directExecutor(), MoreExecutors.directExecutor(),
LAUNCHER_PACKAGE, THEMEPICKER_PACKAGE, mDumpManager) {
@Override
protected OverlayManagerTransaction.Builder getTransactionBuilder() {
return mTransactionBuilder;
}
};
when(mOverlayManager.getOverlayInfosForTarget(ANDROID_PACKAGE, UserHandle.SYSTEM))
.thenReturn(Lists.newArrayList(
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_ACCENT_COLOR,
ANDROID_PACKAGE, OVERLAY_CATEGORY_ACCENT_COLOR, false),
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_SYSTEM_PALETTE,
ANDROID_PACKAGE, OVERLAY_CATEGORY_SYSTEM_PALETTE, false),
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_FONT,
ANDROID_PACKAGE, OVERLAY_CATEGORY_FONT, false),
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_SHAPE,
ANDROID_PACKAGE, OVERLAY_CATEGORY_SHAPE, false),
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_ICON_ANDROID,
ANDROID_PACKAGE, OVERLAY_CATEGORY_ICON_ANDROID, false),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ACCENT_COLOR,
ANDROID_PACKAGE, OVERLAY_CATEGORY_ACCENT_COLOR, true),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_SYSTEM_PALETTE,
ANDROID_PACKAGE, OVERLAY_CATEGORY_SYSTEM_PALETTE, true),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_FONT,
ANDROID_PACKAGE, OVERLAY_CATEGORY_FONT, true),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_SHAPE,
ANDROID_PACKAGE, OVERLAY_CATEGORY_SHAPE, true),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_ANDROID,
ANDROID_PACKAGE, OVERLAY_CATEGORY_ICON_ANDROID, true)));
when(mOverlayManager.getOverlayInfosForTarget(SYSUI_PACKAGE, UserHandle.SYSTEM))
.thenReturn(Lists.newArrayList(
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_ICON_SYSUI,
SYSUI_PACKAGE, OVERLAY_CATEGORY_ICON_SYSUI, false),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_SYSUI,
SYSUI_PACKAGE, OVERLAY_CATEGORY_ICON_SYSUI, true)));
when(mOverlayManager.getOverlayInfosForTarget(SETTINGS_PACKAGE, UserHandle.SYSTEM))
.thenReturn(Lists.newArrayList(
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_ICON_SETTINGS,
SETTINGS_PACKAGE, OVERLAY_CATEGORY_ICON_SETTINGS, false),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_SETTINGS,
SETTINGS_PACKAGE, OVERLAY_CATEGORY_ICON_SETTINGS, true)));
when(mOverlayManager.getOverlayInfosForTarget(LAUNCHER_PACKAGE, UserHandle.SYSTEM))
.thenReturn(Lists.newArrayList(
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_ICON_LAUNCHER,
LAUNCHER_PACKAGE, OVERLAY_CATEGORY_ICON_LAUNCHER, false),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_LAUNCHER,
LAUNCHER_PACKAGE, OVERLAY_CATEGORY_ICON_LAUNCHER, true)));
when(mOverlayManager.getOverlayInfosForTarget(THEMEPICKER_PACKAGE, UserHandle.SYSTEM))
.thenReturn(Lists.newArrayList(
createOverlayInfo(TEST_DISABLED_PREFIX + OVERLAY_CATEGORY_ICON_THEME_PICKER,
THEMEPICKER_PACKAGE, OVERLAY_CATEGORY_ICON_THEME_PICKER, false),
createOverlayInfo(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_THEME_PICKER,
THEMEPICKER_PACKAGE, OVERLAY_CATEGORY_ICON_THEME_PICKER, true)));
OverlayInfo launcherTargetInfo = new OverlayInfo("packageName", LAUNCHER_PACKAGE,
null, null, "/", 0, 0, 0, false);
when(mOverlayManager.getOverlayInfo(any(OverlayIdentifier.class), any()))
.thenAnswer(answer -> {
if (mGetOverlayInfoEnabled) {
return launcherTargetInfo;
}
return null;
});
clearInvocations(mOverlayManager);
verify(mDumpManager).registerDumpable(any(), any());
}
@Test
public void allCategoriesSpecified_allEnabledExclusively() {
mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(),
TEST_USER_HANDLES, mOnOverlaysApplied);
verify(mOverlayManager).commit(any());
for (OverlayIdentifier overlayPackage : ALL_CATEGORIES_MAP.values()) {
verify(mTransactionBuilder).setEnabled(eq(overlayPackage), eq(true),
eq(TEST_USER.getIdentifier()));
}
}
@Test
public void allCategoriesSpecified_sysuiCategoriesAlsoAppliedToSysuiUser() {
mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(),
TEST_USER_HANDLES, mOnOverlaysApplied);
for (Map.Entry<String, OverlayIdentifier> entry : ALL_CATEGORIES_MAP.entrySet()) {
if (SYSTEM_USER_CATEGORIES.contains(entry.getKey())) {
verify(mTransactionBuilder).setEnabled(eq(entry.getValue()), eq(true),
eq(UserHandle.SYSTEM.getIdentifier()));
} else {
verify(mTransactionBuilder, never()).setEnabled(
eq(entry.getValue()), eq(true), eq(UserHandle.SYSTEM.getIdentifier()));
}
}
}
@Test
public void allCategoriesSpecified_enabledForAllUserHandles() {
Set<UserHandle> userHandles = Sets.newHashSet(TEST_USER_HANDLES);
mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(),
userHandles, mOnOverlaysApplied);
verify(mOnOverlaysApplied).run();
for (OverlayIdentifier overlayPackage : ALL_CATEGORIES_MAP.values()) {
verify(mTransactionBuilder).setEnabled(eq(overlayPackage), eq(true),
eq(TEST_USER.getIdentifier()));
// Not enabled for work profile because the target package is LAUNCHER_PACKAGE
verify(mTransactionBuilder, never()).setEnabled(eq(overlayPackage), eq(true),
eq(TEST_USER_MANAGED_PROFILE.getIdentifier()));
}
}
@Test
public void enablesOverlays_onlyIfItExistsForUser() {
mGetOverlayInfoEnabled = false;
Set<UserHandle> userHandles = Sets.newHashSet(TEST_USER_HANDLES);
mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, null, TEST_USER.getIdentifier(),
userHandles, mOnOverlaysApplied);
for (OverlayIdentifier overlayPackage : ALL_CATEGORIES_MAP.values()) {
verify(mTransactionBuilder, never()).setEnabled(eq(overlayPackage), eq(true),
eq(TEST_USER.getIdentifier()));
}
}
@Test
public void applyCurrentUserOverlays_createsPendingOverlays() {
FabricatedOverlay[] pendingCreation = new FabricatedOverlay[]{
mock(FabricatedOverlay.class)
};
mManager.applyCurrentUserOverlays(ALL_CATEGORIES_MAP, pendingCreation,
TEST_USER.getIdentifier(), TEST_USER_HANDLES, mOnOverlaysApplied);
for (FabricatedOverlay overlay : pendingCreation) {
verify(mTransactionBuilder).registerFabricatedOverlay(eq(overlay));
}
}
@Test
public void someCategoriesSpecified_specifiedEnabled_unspecifiedDisabled() {
Map<String, OverlayIdentifier> categoryToPackage = new HashMap<>(ALL_CATEGORIES_MAP);
categoryToPackage.remove(OVERLAY_CATEGORY_ICON_SETTINGS);
categoryToPackage.remove(OVERLAY_CATEGORY_ICON_ANDROID);
mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER.getIdentifier(),
TEST_USER_HANDLES, mOnOverlaysApplied);
for (OverlayIdentifier overlayPackage : categoryToPackage.values()) {
verify(mTransactionBuilder).setEnabled(eq(overlayPackage), eq(true),
eq(TEST_USER.getIdentifier()));
}
verify(mTransactionBuilder).setEnabled(
eq(new OverlayIdentifier(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_SETTINGS)),
eq(false), eq(TEST_USER.getIdentifier()));
verify(mTransactionBuilder).setEnabled(
eq(new OverlayIdentifier(TEST_ENABLED_PREFIX + OVERLAY_CATEGORY_ICON_ANDROID)),
eq(false), eq(TEST_USER.getIdentifier()));
}
@Test
public void zeroCategoriesSpecified_allDisabled() {
mManager.applyCurrentUserOverlays(Maps.newArrayMap(), null, TEST_USER.getIdentifier(),
TEST_USER_HANDLES, mOnOverlaysApplied);
for (String category : THEME_CATEGORIES) {
verify(mTransactionBuilder).setEnabled(
eq(new OverlayIdentifier(TEST_ENABLED_PREFIX + category)), eq(false),
eq(TEST_USER.getIdentifier()));
}
}
@Test
public void nonThemeCategorySpecified_ignored() {
Map<String, OverlayIdentifier> categoryToPackage = new HashMap<>(ALL_CATEGORIES_MAP);
categoryToPackage.put("blah.category", new OverlayIdentifier("com.example.blah.category"));
mManager.applyCurrentUserOverlays(categoryToPackage, null, TEST_USER.getIdentifier(),
TEST_USER_HANDLES, mOnOverlaysApplied);
verify(mTransactionBuilder, never()).setEnabled(
eq(new OverlayIdentifier("com.example.blah.category")), eq(false),
eq(TEST_USER.getIdentifier()));
verify(mTransactionBuilder, never()).setEnabled(
eq(new OverlayIdentifier("com.example.blah.category")), eq(true),
eq(TEST_USER.getIdentifier()));
}
private static OverlayInfo createOverlayInfo(String packageName, String targetPackageName,
String category, boolean enabled) {
return new OverlayInfo(packageName, null, targetPackageName, null, category, "",
enabled ? OverlayInfo.STATE_ENABLED : OverlayInfo.STATE_DISABLED, 0, 0, false,
false);
}
}