1 /*
2  * Copyright (C) 2018 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 package com.android.settings.location;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 
20 import static org.mockito.ArgumentMatchers.any;
21 import static org.mockito.ArgumentMatchers.anyInt;
22 import static org.mockito.Mockito.doNothing;
23 import static org.mockito.Mockito.never;
24 import static org.mockito.Mockito.spy;
25 import static org.mockito.Mockito.verify;
26 import static org.mockito.Mockito.when;
27 
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.pm.ActivityInfo;
31 import android.content.pm.ApplicationInfo;
32 import android.content.pm.PackageManager;
33 import android.content.pm.PackageManager.NameNotFoundException;
34 import android.content.pm.ResolveInfo;
35 import android.content.res.Resources;
36 import android.location.LocationManager;
37 import android.os.Bundle;
38 
39 import androidx.preference.Preference;
40 import androidx.preference.PreferenceCategory;
41 
42 import org.junit.Before;
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 import org.mockito.ArgumentCaptor;
46 import org.mockito.Mock;
47 import org.mockito.MockitoAnnotations;
48 import org.robolectric.RobolectricTestRunner;
49 import org.robolectric.RuntimeEnvironment;
50 
51 import java.util.ArrayList;
52 import java.util.List;
53 
54 @RunWith(RobolectricTestRunner.class)
55 public class LocationFooterPreferenceControllerTest {
56 
57     @Mock
58     private PreferenceCategory mPreferenceCategory;
59     @Mock
60     private PackageManager mPackageManager;
61     @Mock
62     private Resources mResources;
63     private LocationFooterPreferenceController mController;
64     private static final int TEST_RES_ID = 1234;
65     private static final String TEST_TEXT = "text";
66 
67     @Before
setUp()68     public void setUp() throws NameNotFoundException {
69         MockitoAnnotations.initMocks(this);
70         Context context = spy(RuntimeEnvironment.application);
71         when(context.getPackageManager()).thenReturn(mPackageManager);
72         when(mPreferenceCategory.getContext()).thenReturn(context);
73         mController = spy(new LocationFooterPreferenceController(context, "key"));
74         when(mPackageManager.getResourcesForApplication(any(ApplicationInfo.class)))
75                 .thenReturn(mResources);
76         when(mResources.getString(TEST_RES_ID)).thenReturn(TEST_TEXT);
77         doNothing().when(mPreferenceCategory).removeAll();
78     }
79 
80     @Test
isAvailable_hasValidFooter_returnsTrue()81     public void isAvailable_hasValidFooter_returnsTrue() {
82         final List<ResolveInfo> testResolveInfos = new ArrayList<>();
83         testResolveInfos.add(
84                 getTestResolveInfo(/*isSystemApp*/ true, /*hasRequiredMetadata*/ true));
85         when(mPackageManager.queryBroadcastReceivers(any(Intent.class), anyInt()))
86                 .thenReturn(testResolveInfos);
87 
88         assertThat(mController.isAvailable()).isTrue();
89     }
90 
91     @Test
isAvailable_noSystemApp_returnsFalse()92     public void isAvailable_noSystemApp_returnsFalse() {
93         final List<ResolveInfo> testResolveInfos = new ArrayList<>();
94         testResolveInfos.add(
95                 getTestResolveInfo(/*isSystemApp*/ false, /*hasRequiredMetadata*/ true));
96         when(mPackageManager.queryBroadcastReceivers(any(Intent.class), anyInt()))
97                 .thenReturn(testResolveInfos);
98         assertThat(mController.isAvailable()).isFalse();
99     }
100 
101     @Test
isAvailable_noRequiredMetadata_returnsFalse()102     public void isAvailable_noRequiredMetadata_returnsFalse() {
103         final List<ResolveInfo> testResolveInfos = new ArrayList<>();
104         testResolveInfos.add(
105                 getTestResolveInfo(/*isSystemApp*/ true, /*hasRequiredMetadata*/ false));
106         when(mPackageManager.queryBroadcastReceivers(any(Intent.class), anyInt()))
107                 .thenReturn(testResolveInfos);
108         assertThat(mController.isAvailable()).isFalse();
109     }
110 
111     @Test
updateState_addPreferences()112     public void updateState_addPreferences() {
113         final List<ResolveInfo> testResolveInfos = new ArrayList<>();
114         testResolveInfos.add(
115                 getTestResolveInfo(/*isSystemApp*/ true, /*hasRequiredMetadata*/ true));
116         when(mPackageManager.queryBroadcastReceivers(any(Intent.class), anyInt()))
117                 .thenReturn(testResolveInfos);
118         mController.updateState(mPreferenceCategory);
119         ArgumentCaptor<Preference> pref = ArgumentCaptor.forClass(Preference.class);
120         verify(mPreferenceCategory).addPreference(pref.capture());
121         assertThat(pref.getValue().getTitle()).isEqualTo(TEST_TEXT);
122     }
123 
124     @Test
updateState_notSystemApp_ignore()125     public void updateState_notSystemApp_ignore() {
126         final List<ResolveInfo> testResolveInfos = new ArrayList<>();
127         testResolveInfos.add(
128                 getTestResolveInfo(/*isSystemApp*/ false, /*hasRequiredMetadata*/ true));
129         when(mPackageManager.queryBroadcastReceivers(any(Intent.class), anyInt()))
130                 .thenReturn(testResolveInfos);
131         mController.updateState(mPreferenceCategory);
132         verify(mPreferenceCategory, never()).addPreference(any(Preference.class));
133     }
134 
135     /**
136      * Returns a ResolveInfo object for testing
137      * @param isSystemApp If true, the application is a system app.
138      * @param hasRequiredMetaData If true, the broadcast receiver has a valid value for
139      *                            {@link LocationManager#METADATA_SETTINGS_FOOTER_STRING}
140      */
getTestResolveInfo(boolean isSystemApp, boolean hasRequiredMetaData)141     private ResolveInfo getTestResolveInfo(boolean isSystemApp, boolean hasRequiredMetaData) {
142         ResolveInfo testResolveInfo = new ResolveInfo();
143         ApplicationInfo testAppInfo = new ApplicationInfo();
144         if (isSystemApp) {
145             testAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
146         }
147         ActivityInfo testActivityInfo = new ActivityInfo();
148         testActivityInfo.name = "TestActivityName";
149         testActivityInfo.packageName = "TestPackageName";
150         testActivityInfo.applicationInfo = testAppInfo;
151         if (hasRequiredMetaData) {
152             testActivityInfo.metaData = new Bundle();
153             testActivityInfo.metaData.putInt(
154                     LocationManager.METADATA_SETTINGS_FOOTER_STRING, TEST_RES_ID);
155         }
156         testResolveInfo.activityInfo = testActivityInfo;
157         return testResolveInfo;
158     }
159 }
160