Loading src/com/android/documentsui/BaseActivity.java +7 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.android.documentsui.base.SharedMinimal.DEBUG; import static com.android.documentsui.base.State.MODE_GRID; import android.content.Intent; import android.content.om.OverlayManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; Loading Loading @@ -73,6 +74,7 @@ import com.android.documentsui.roots.ProvidersCache; import com.android.documentsui.sidebar.RootsFragment; import com.android.documentsui.sorting.SortController; import com.android.documentsui.sorting.SortModel; import com.android.documentsui.theme.ThemeOverlayManager; import com.google.android.material.appbar.AppBarLayout; Loading Loading @@ -101,6 +103,8 @@ public abstract class BaseActivity protected NavigationViewManager mNavigator; protected SortController mSortController; protected ThemeOverlayManager mThemeOverlayManager; private final List<EventListener> mEventListeners = new ArrayList<>(); private final String mTag; Loading Loading @@ -132,6 +136,9 @@ public abstract class BaseActivity // Record the time when onCreate is invoked for metric. mStartTime = new Date().getTime(); mThemeOverlayManager = new ThemeOverlayManager(getSystemService(OverlayManager.class), getPackageName()); mThemeOverlayManager.applyOverlays(true); // ToDo Create tool to check resource version before applyStyle for the theme // If version code is not match, we should reset overlay package to default, // in case Activity continueusly encounter resource not found exception Loading src/com/android/documentsui/theme/ThemeOverlayManager.java 0 → 100644 +82 −0 Original line number Diff line number Diff line /* * 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.documentsui.theme; import android.annotation.TargetApi; import android.content.om.OverlayInfo; import android.content.om.OverlayManager; import android.os.Build; import android.os.UserHandle; import android.util.Log; import java.util.List; /** * ThemeOverlayManager manage runtime resource overlay packages of DocumentsUI */ public class ThemeOverlayManager { private static final String TAG = ThemeOverlayManager.class.getSimpleName(); private static final boolean DEBUG = false; private OverlayManager mOverlayManager; private String mTargetPackageId; private UserHandle mUserHandle; @TargetApi(Build.VERSION_CODES.M) public ThemeOverlayManager(OverlayManager overlayManager, String targetPackageId) { mOverlayManager = overlayManager; mTargetPackageId = targetPackageId; mUserHandle = UserHandle.of(UserHandle.myUserId()); } /** * Apply runtime overlay package * * @param enabled whether or not enable overlay package */ public void applyOverlays(boolean enabled) { setOverlaysEnabled(getOverlayInfo(), enabled); } private List<OverlayInfo> getOverlayInfo() { if (mOverlayManager != null) { return mOverlayManager.getOverlayInfosForTarget(mTargetPackageId, mUserHandle); } return null; } private void setOverlaysEnabled(List<OverlayInfo> overlayInfos, boolean enabled) { if (mOverlayManager != null && overlayInfos != null) { for (OverlayInfo info : overlayInfos) { if (info.isEnabled() != enabled) { setEnabled(info.getPackageName(), mUserHandle, enabled); } else { Log.w(TAG, "Overlay package:" + info.getPackageName() + ", already enabled, UserHandle:"); } } } } private void setEnabled(String pkg, UserHandle userHandle, boolean enabled) { if (DEBUG) { Log.d(TAG, String.format("setEnabled: %s %s %b", pkg, userHandle, enabled)); } mOverlayManager.setEnabled(pkg, enabled, userHandle); } } tests/unit/com/android/documentsui/theme/ThemeOverlayManagerTest.java 0 → 100644 +169 −0 Original line number Diff line number Diff line /* * 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.documentsui.theme; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.om.OverlayInfo; import android.content.om.OverlayManager; import android.os.UserHandle; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.google.common.collect.Lists; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.List; @SmallTest @RunWith(AndroidJUnit4.class) public class ThemeOverlayManagerTest { private static final String TEST_DISABLED_PREFIX = "com.example."; private static final String TEST_ENABLED_PREFIX = "com.example.enabled."; private static final String TEST_OVERLAY_PACKAGE = "test.overlay"; private static final String TEST_TARGET_PACKAGE = "test.target"; @Mock OverlayManager mOverlayManager; ThemeOverlayManager mThemeOverlayManager; UserHandle mUserHandle; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mUserHandle = UserHandle.of(UserHandle.myUserId()); when(mOverlayManager.getOverlayInfosForTarget(getEnabledTargetPackageId(), mUserHandle)).thenReturn(Lists.newArrayList( createOverlayInfo(getOverlayPackageId(), getEnabledTargetPackageId(), true))); when(mOverlayManager.getOverlayInfosForTarget(getDisabledTargetPackageId(), mUserHandle)).thenReturn(Lists.newArrayList( createOverlayInfo(getOverlayPackageId(), getDisabledTargetPackageId(), false))); } @Test public void testOverlayPackagesForDocumentsUI_shouldBeNonStatic() { final String docsuiPkgId = InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName(); final OverlayManager manager = InstrumentationRegistry.getInstrumentation().getTargetContext().getSystemService( OverlayManager.class); final List<OverlayInfo> infos = manager.getOverlayInfosForTarget(docsuiPkgId, mUserHandle); for (OverlayInfo info : infos) { assertThat(info.isStatic).isFalse(); } } @Test public void testApplyOverlays_shouldSetEnabled() { final boolean enabled = true; mThemeOverlayManager = new ThemeOverlayManager(mOverlayManager, getDisabledTargetPackageId()); mThemeOverlayManager.applyOverlays(enabled); verify(mOverlayManager, times(1)).setEnabled(getOverlayPackageId(), enabled, mUserHandle); } @Test public void testApplyOverlays_shouldGetOverlayInfo() { final boolean enabled = true; mThemeOverlayManager = new ThemeOverlayManager(mOverlayManager, getEnabledTargetPackageId()); mThemeOverlayManager.applyOverlays(enabled); verify(mOverlayManager, times(1)).getOverlayInfosForTarget(getEnabledTargetPackageId(), mUserHandle); } @Test public void testApplyOverlays_shouldCheckEnabled_beforeSetEnabled() { final boolean enabled = true; mThemeOverlayManager = new ThemeOverlayManager(mOverlayManager, getEnabledTargetPackageId()); mThemeOverlayManager.applyOverlays(enabled); verify(mOverlayManager, never()).setEnabled(getOverlayPackageId(), enabled, mUserHandle); } @Test public void testDefaultDisabled_applyOverlays_shouldEnabled() { final boolean enabled = true; assertThat(mOverlayManager.getOverlayInfosForTarget(getDisabledTargetPackageId(), mUserHandle).get(0).isEnabled()).isEqualTo(!enabled); mThemeOverlayManager = new ThemeOverlayManager(mOverlayManager, getDisabledTargetPackageId()); mThemeOverlayManager.applyOverlays(enabled); verify(mOverlayManager, times(1)).setEnabled(getOverlayPackageId(), enabled, mUserHandle); } @Test public void testDefaultEnabled_applyOverlays_shouldDisabled() { final boolean enabled = false; assertThat(mOverlayManager.getOverlayInfosForTarget(getEnabledTargetPackageId(), mUserHandle).get(0).isEnabled()).isEqualTo(!enabled); mThemeOverlayManager = new ThemeOverlayManager(mOverlayManager, getEnabledTargetPackageId()); mThemeOverlayManager.applyOverlays(enabled); verify(mOverlayManager, times(1)).setEnabled(getOverlayPackageId(), enabled, mUserHandle); } private static OverlayInfo createOverlayInfo(String packageName, String targetPackageName, boolean enabled) { return new OverlayInfo(packageName, targetPackageName, null, null, "", enabled ? OverlayInfo.STATE_ENABLED : OverlayInfo.STATE_DISABLED, 0, 0, false); } private static String getDisabledTargetPackageId() { return TEST_DISABLED_PREFIX + TEST_TARGET_PACKAGE; } private static String getEnabledTargetPackageId() { return TEST_ENABLED_PREFIX + TEST_TARGET_PACKAGE; } private static String getOverlayPackageId() { return TEST_DISABLED_PREFIX + TEST_OVERLAY_PACKAGE; } } Loading
src/com/android/documentsui/BaseActivity.java +7 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static com.android.documentsui.base.SharedMinimal.DEBUG; import static com.android.documentsui.base.State.MODE_GRID; import android.content.Intent; import android.content.om.OverlayManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ProviderInfo; Loading Loading @@ -73,6 +74,7 @@ import com.android.documentsui.roots.ProvidersCache; import com.android.documentsui.sidebar.RootsFragment; import com.android.documentsui.sorting.SortController; import com.android.documentsui.sorting.SortModel; import com.android.documentsui.theme.ThemeOverlayManager; import com.google.android.material.appbar.AppBarLayout; Loading Loading @@ -101,6 +103,8 @@ public abstract class BaseActivity protected NavigationViewManager mNavigator; protected SortController mSortController; protected ThemeOverlayManager mThemeOverlayManager; private final List<EventListener> mEventListeners = new ArrayList<>(); private final String mTag; Loading Loading @@ -132,6 +136,9 @@ public abstract class BaseActivity // Record the time when onCreate is invoked for metric. mStartTime = new Date().getTime(); mThemeOverlayManager = new ThemeOverlayManager(getSystemService(OverlayManager.class), getPackageName()); mThemeOverlayManager.applyOverlays(true); // ToDo Create tool to check resource version before applyStyle for the theme // If version code is not match, we should reset overlay package to default, // in case Activity continueusly encounter resource not found exception Loading
src/com/android/documentsui/theme/ThemeOverlayManager.java 0 → 100644 +82 −0 Original line number Diff line number Diff line /* * 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.documentsui.theme; import android.annotation.TargetApi; import android.content.om.OverlayInfo; import android.content.om.OverlayManager; import android.os.Build; import android.os.UserHandle; import android.util.Log; import java.util.List; /** * ThemeOverlayManager manage runtime resource overlay packages of DocumentsUI */ public class ThemeOverlayManager { private static final String TAG = ThemeOverlayManager.class.getSimpleName(); private static final boolean DEBUG = false; private OverlayManager mOverlayManager; private String mTargetPackageId; private UserHandle mUserHandle; @TargetApi(Build.VERSION_CODES.M) public ThemeOverlayManager(OverlayManager overlayManager, String targetPackageId) { mOverlayManager = overlayManager; mTargetPackageId = targetPackageId; mUserHandle = UserHandle.of(UserHandle.myUserId()); } /** * Apply runtime overlay package * * @param enabled whether or not enable overlay package */ public void applyOverlays(boolean enabled) { setOverlaysEnabled(getOverlayInfo(), enabled); } private List<OverlayInfo> getOverlayInfo() { if (mOverlayManager != null) { return mOverlayManager.getOverlayInfosForTarget(mTargetPackageId, mUserHandle); } return null; } private void setOverlaysEnabled(List<OverlayInfo> overlayInfos, boolean enabled) { if (mOverlayManager != null && overlayInfos != null) { for (OverlayInfo info : overlayInfos) { if (info.isEnabled() != enabled) { setEnabled(info.getPackageName(), mUserHandle, enabled); } else { Log.w(TAG, "Overlay package:" + info.getPackageName() + ", already enabled, UserHandle:"); } } } } private void setEnabled(String pkg, UserHandle userHandle, boolean enabled) { if (DEBUG) { Log.d(TAG, String.format("setEnabled: %s %s %b", pkg, userHandle, enabled)); } mOverlayManager.setEnabled(pkg, enabled, userHandle); } }
tests/unit/com/android/documentsui/theme/ThemeOverlayManagerTest.java 0 → 100644 +169 −0 Original line number Diff line number Diff line /* * 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.documentsui.theme; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.om.OverlayInfo; import android.content.om.OverlayManager; import android.os.UserHandle; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import com.google.common.collect.Lists; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.List; @SmallTest @RunWith(AndroidJUnit4.class) public class ThemeOverlayManagerTest { private static final String TEST_DISABLED_PREFIX = "com.example."; private static final String TEST_ENABLED_PREFIX = "com.example.enabled."; private static final String TEST_OVERLAY_PACKAGE = "test.overlay"; private static final String TEST_TARGET_PACKAGE = "test.target"; @Mock OverlayManager mOverlayManager; ThemeOverlayManager mThemeOverlayManager; UserHandle mUserHandle; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mUserHandle = UserHandle.of(UserHandle.myUserId()); when(mOverlayManager.getOverlayInfosForTarget(getEnabledTargetPackageId(), mUserHandle)).thenReturn(Lists.newArrayList( createOverlayInfo(getOverlayPackageId(), getEnabledTargetPackageId(), true))); when(mOverlayManager.getOverlayInfosForTarget(getDisabledTargetPackageId(), mUserHandle)).thenReturn(Lists.newArrayList( createOverlayInfo(getOverlayPackageId(), getDisabledTargetPackageId(), false))); } @Test public void testOverlayPackagesForDocumentsUI_shouldBeNonStatic() { final String docsuiPkgId = InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageName(); final OverlayManager manager = InstrumentationRegistry.getInstrumentation().getTargetContext().getSystemService( OverlayManager.class); final List<OverlayInfo> infos = manager.getOverlayInfosForTarget(docsuiPkgId, mUserHandle); for (OverlayInfo info : infos) { assertThat(info.isStatic).isFalse(); } } @Test public void testApplyOverlays_shouldSetEnabled() { final boolean enabled = true; mThemeOverlayManager = new ThemeOverlayManager(mOverlayManager, getDisabledTargetPackageId()); mThemeOverlayManager.applyOverlays(enabled); verify(mOverlayManager, times(1)).setEnabled(getOverlayPackageId(), enabled, mUserHandle); } @Test public void testApplyOverlays_shouldGetOverlayInfo() { final boolean enabled = true; mThemeOverlayManager = new ThemeOverlayManager(mOverlayManager, getEnabledTargetPackageId()); mThemeOverlayManager.applyOverlays(enabled); verify(mOverlayManager, times(1)).getOverlayInfosForTarget(getEnabledTargetPackageId(), mUserHandle); } @Test public void testApplyOverlays_shouldCheckEnabled_beforeSetEnabled() { final boolean enabled = true; mThemeOverlayManager = new ThemeOverlayManager(mOverlayManager, getEnabledTargetPackageId()); mThemeOverlayManager.applyOverlays(enabled); verify(mOverlayManager, never()).setEnabled(getOverlayPackageId(), enabled, mUserHandle); } @Test public void testDefaultDisabled_applyOverlays_shouldEnabled() { final boolean enabled = true; assertThat(mOverlayManager.getOverlayInfosForTarget(getDisabledTargetPackageId(), mUserHandle).get(0).isEnabled()).isEqualTo(!enabled); mThemeOverlayManager = new ThemeOverlayManager(mOverlayManager, getDisabledTargetPackageId()); mThemeOverlayManager.applyOverlays(enabled); verify(mOverlayManager, times(1)).setEnabled(getOverlayPackageId(), enabled, mUserHandle); } @Test public void testDefaultEnabled_applyOverlays_shouldDisabled() { final boolean enabled = false; assertThat(mOverlayManager.getOverlayInfosForTarget(getEnabledTargetPackageId(), mUserHandle).get(0).isEnabled()).isEqualTo(!enabled); mThemeOverlayManager = new ThemeOverlayManager(mOverlayManager, getEnabledTargetPackageId()); mThemeOverlayManager.applyOverlays(enabled); verify(mOverlayManager, times(1)).setEnabled(getOverlayPackageId(), enabled, mUserHandle); } private static OverlayInfo createOverlayInfo(String packageName, String targetPackageName, boolean enabled) { return new OverlayInfo(packageName, targetPackageName, null, null, "", enabled ? OverlayInfo.STATE_ENABLED : OverlayInfo.STATE_DISABLED, 0, 0, false); } private static String getDisabledTargetPackageId() { return TEST_DISABLED_PREFIX + TEST_TARGET_PACKAGE; } private static String getEnabledTargetPackageId() { return TEST_ENABLED_PREFIX + TEST_TARGET_PACKAGE; } private static String getOverlayPackageId() { return TEST_DISABLED_PREFIX + TEST_OVERLAY_PACKAGE; } }