1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.display;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.ArgumentMatchers.anyInt;
23 import static org.mockito.ArgumentMatchers.anyString;
24 import static org.mockito.Mockito.doReturn;
25 import static org.mockito.Mockito.mock;
26 import static org.mockito.Mockito.spy;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.when;
29 
30 import android.app.admin.DevicePolicyManager;
31 import android.content.Context;
32 import android.content.om.IOverlayManager;
33 import android.content.om.OverlayInfo;
34 import android.content.pm.ApplicationInfo;
35 import android.content.pm.PackageInfo;
36 import android.content.pm.PackageManager;
37 import android.content.pm.PackageManager.NameNotFoundException;
38 
39 import androidx.preference.ListPreference;
40 
41 import com.android.settings.R;
42 import com.android.settings.testutils.FakeFeatureFactory;
43 
44 import org.junit.Before;
45 import org.junit.Test;
46 import org.junit.runner.RunWith;
47 import org.mockito.Answers;
48 import org.mockito.Mock;
49 import org.mockito.MockitoAnnotations;
50 import org.robolectric.RobolectricTestRunner;
51 import org.robolectric.RuntimeEnvironment;
52 
53 import java.util.Arrays;
54 
55 @RunWith(RobolectricTestRunner.class)
56 public class ThemePreferenceControllerTest {
57 
58     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
59     private Context mContext;
60     @Mock
61     private PackageManager mPackageManager;
62     @Mock
63     private ApplicationInfo mApplicationInfo;
64     @Mock
65     private ListPreference mPreference;
66     @Mock
67     private IOverlayManager mOverlayManager;
68 
69     private ThemePreferenceController mController;
70 
71     @Before
setUp()72     public void setUp() throws NameNotFoundException {
73         MockitoAnnotations.initMocks(this);
74         FakeFeatureFactory.setupForTest();
75         doReturn(mock(DevicePolicyManager.class)).when(mContext)
76                 .getSystemService(Context.DEVICE_POLICY_SERVICE);
77         when(mPackageManager.getApplicationInfo(any(), anyInt())).thenReturn(mApplicationInfo);
78         when(mContext.getPackageManager()).thenReturn(mPackageManager);
79         when(mContext.getString(R.string.default_theme))
80                 .thenReturn(RuntimeEnvironment.application.getString(R.string.default_theme));
81 
82         when(mContext.getSystemService(Context.OVERLAY_SERVICE)).thenReturn(mOverlayManager);
83         mController = spy(new ThemePreferenceController(mContext, mOverlayManager));
84     }
85 
86     @Test
testAvailable_false()87     public void testAvailable_false() throws Exception {
88         when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(
89                 new PackageInfo());
90         when(mOverlayManager.getOverlayInfosForTarget(any(), anyInt()))
91                 .thenReturn(Arrays.asList(new OverlayInfo("", "", "", "", "", 0, 0, 0, false)));
92         assertThat(mController.isAvailable()).isFalse();
93     }
94 
95     @Test
testAvailable_true()96     public void testAvailable_true() throws Exception {
97         when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(
98                 new PackageInfo());
99         when(mOverlayManager.getOverlayInfosForTarget(any(), anyInt()))
100                 .thenReturn(Arrays.asList(
101                         new OverlayInfo("", "", "", OverlayInfo.CATEGORY_THEME, "", 0, 0, 0, true),
102                         new OverlayInfo("", "", "", OverlayInfo.CATEGORY_THEME, "", 0, 0, 0,
103                                 true)));
104         assertThat(mController.isAvailable()).isTrue();
105     }
106 
107     @Test
updateState_themeSet_shouldSetPreferenceValue()108     public void updateState_themeSet_shouldSetPreferenceValue() throws NameNotFoundException {
109         final String pkg1 = "pkg1.theme1";
110         final String pkg2 = "pkg2.theme2";
111         final String themeLabel1 = "Theme1";
112         final String themeLabel2 = "Theme2";
113         final String[] themes = {pkg1, pkg2};
114         doReturn("pkg1.theme1").when(mController).getCurrentTheme();
115         doReturn(themes).when(mController).getAvailableThemes(false /* currentThemeOnly */);
116         when(mPackageManager.getApplicationInfo(anyString(), anyInt()).loadLabel(mPackageManager))
117                 .thenReturn(themeLabel1)
118                 .thenReturn(themeLabel2);
119 
120         mController.updateState(mPreference);
121 
122         verify(mPreference).setSummary(themeLabel1);
123         verify(mPreference).setValue(pkg1);
124     }
125 
126     @Test
updateState_themeNull_shouldSetDefaultSummary()127     public void updateState_themeNull_shouldSetDefaultSummary() throws NameNotFoundException {
128         final String pkg1 = "pkg1.theme1";
129         final String pkg2 = "pkg2.theme2";
130         final String themeLabel1 = "Theme1";
131         final String themeLabel2 = "Theme2";
132         final String[] themes = {pkg1, pkg2};
133         doReturn(null).when(mController).getCurrentTheme();
134         doReturn(themes).when(mController).getAvailableThemes(false /* currentThemeOnly */);
135         when(mPackageManager.getApplicationInfo(anyString(), anyInt()).loadLabel(mPackageManager))
136                 .thenReturn(themeLabel1)
137                 .thenReturn(themeLabel2);
138 
139         mController.updateState(mPreference);
140 
141         verify(mPreference)
142                 .setSummary(RuntimeEnvironment.application.getString(R.string.default_theme));
143         verify(mPreference).setValue(null);
144     }
145 
146     @Test
getCurrentTheme_withEnabledState()147     public void getCurrentTheme_withEnabledState() throws Exception {
148         OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android", "",
149                 OverlayInfo.CATEGORY_THEME, "", OverlayInfo.STATE_ENABLED, 0, 0, true);
150         OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android", "",
151                 OverlayInfo.CATEGORY_THEME, "", 0, 0, 0, true);
152         when(mOverlayManager.getOverlayInfosForTarget(any(), anyInt())).thenReturn(
153                 Arrays.asList(info1, info2));
154         when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(
155                 new PackageInfo());
156 
157         assertThat(mController.getCurrentTheme()).isEqualTo(info1.packageName);
158     }
159 
160     @Test
testGetCurrentTheme_withoutEnabledState()161     public void testGetCurrentTheme_withoutEnabledState() throws Exception {
162         OverlayInfo info1 = new OverlayInfo("com.android.Theme1", "android", "",
163                 OverlayInfo.CATEGORY_THEME, "", OverlayInfo.STATE_DISABLED, 0, 0, true);
164         OverlayInfo info2 = new OverlayInfo("com.android.Theme2", "android", "",
165                 OverlayInfo.CATEGORY_THEME, "", 0, 0, 0, true);
166         when(mOverlayManager.getOverlayInfosForTarget(any(), anyInt())).thenReturn(
167                 Arrays.asList(info1, info2));
168         when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(
169                 new PackageInfo());
170 
171         assertThat(mController.getCurrentTheme()).isNull();
172     }
173 }
174