1/*
2 * Copyright (C) 2014 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
17package com.android.server;
18
19import static junit.framework.Assert.assertEquals;
20import static junit.framework.Assert.assertNotNull;
21import static junit.framework.Assert.assertNull;
22import static junit.framework.Assert.assertTrue;
23
24import static org.junit.Assert.assertFalse;
25import static org.mockito.ArgumentMatchers.anyString;
26import static org.mockito.Matchers.any;
27import static org.mockito.Matchers.anyInt;
28import static org.mockito.Matchers.eq;
29import static org.mockito.Mockito.never;
30import static org.mockito.Mockito.verify;
31import static org.mockito.Mockito.when;
32
33import android.Manifest.permission;
34import android.app.AppOpsManager;
35import android.content.ComponentName;
36import android.content.Context;
37import android.content.Intent;
38import android.content.pm.ActivityInfo;
39import android.content.pm.ApplicationInfo;
40import android.content.pm.PackageManager;
41import android.content.pm.ResolveInfo;
42import android.content.pm.ServiceInfo;
43import android.content.res.Resources;
44import android.net.NetworkScoreManager;
45import android.net.NetworkScorerAppData;
46import android.os.Bundle;
47import android.provider.Settings;
48import android.support.test.runner.AndroidJUnit4;
49
50import com.android.internal.R;
51
52import org.junit.Before;
53import org.junit.Test;
54import org.junit.runner.RunWith;
55import org.mockito.ArgumentMatcher;
56import org.mockito.Mock;
57import org.mockito.Mockito;
58import org.mockito.MockitoAnnotations;
59
60import java.util.ArrayList;
61import java.util.List;
62
63@RunWith(AndroidJUnit4.class)
64public class NetworkScorerAppManagerTest {
65    private static final int PACKAGE_UID = 924;
66    private static String MOCK_SERVICE_LABEL = "Mock Service";
67    private static String MOCK_OVERRIDEN_SERVICE_LABEL = "Mock Service Label Override";
68    private static String MOCK_NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID =
69            "Mock Network Available Notification Channel Id";
70    private static final ComponentName RECO_COMPONENT = new ComponentName("package1", "class1");
71
72    @Mock private Context mMockContext;
73    @Mock private PackageManager mMockPm;
74    @Mock private Resources mResources;
75    @Mock private NetworkScorerAppManager.SettingsFacade mSettingsFacade;
76    @Mock private AppOpsManager mAppOpsManager;
77    private NetworkScorerAppManager mNetworkScorerAppManager;
78    private List<ResolveInfo> mAvailableServices;
79
80    @Before
81    public void setUp() throws Exception {
82        MockitoAnnotations.initMocks(this);
83        mAvailableServices = new ArrayList<>();
84        when(mMockContext.getPackageManager()).thenReturn(mMockPm);
85        when(mMockPm.queryIntentServices(Mockito.argThat(
86                intent -> NetworkScoreManager.ACTION_RECOMMEND_NETWORKS.equals(intent.getAction())),
87                eq(PackageManager.GET_META_DATA))).thenReturn(mAvailableServices);
88        when(mMockContext.getResources()).thenReturn(mResources);
89        when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
90
91        mockLocationModeOn();
92        mockLocationPermissionGranted(PACKAGE_UID, RECO_COMPONENT.getPackageName());
93
94        mNetworkScorerAppManager = new NetworkScorerAppManager(mMockContext, mSettingsFacade);
95    }
96
97    @Test
98    public void testGetActiveScorer_providerAvailable() throws Exception {
99        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
100        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
101        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */);
102
103        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
104        assertNotNull(activeScorer);
105        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
106        assertEquals(PACKAGE_UID, activeScorer.packageUid);
107        assertEquals(MOCK_SERVICE_LABEL, activeScorer.getRecommendationServiceLabel());
108    }
109
110    @Test
111    public void testGetActiveScorer_providerAvailable_serviceLabelOverride() throws Exception {
112        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
113        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
114        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
115                null /* enableUseOpenWifiPackageActivityPackage*/, true /* serviceLabelOverride */);
116
117        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
118        assertNotNull(activeScorer);
119        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
120        assertEquals(PACKAGE_UID, activeScorer.packageUid);
121        assertEquals(MOCK_OVERRIDEN_SERVICE_LABEL, activeScorer.getRecommendationServiceLabel());
122    }
123
124    @Test
125    public void testGetActiveScorer_scoreNetworksPermissionMissing() throws Exception {
126        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
127        mockScoreNetworksDenied(RECO_COMPONENT.getPackageName());
128        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */);
129
130        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
131        assertNull(activeScorer);
132    }
133
134    @Test
135    public void testGetActiveScorer_locationPermissionMissing() throws Exception {
136        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
137        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
138        mockLocationPermissionDenied(PACKAGE_UID, RECO_COMPONENT.getPackageName());
139        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */);
140
141        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
142        assertNull(activeScorer);
143    }
144
145    @Test
146    public void testGetActiveScorer_locationModeOff() throws Exception {
147        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
148        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
149        mockLocationPermissionGranted(PACKAGE_UID, RECO_COMPONENT.getPackageName());
150        mockLocationModeOff();
151        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */);
152
153        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
154        assertNull(activeScorer);
155    }
156
157    @Test
158    public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotSet()
159            throws Exception {
160        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
161        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
162        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
163                null /* enableUseOpenWifiPackageActivityPackage*/);
164
165        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
166        assertNotNull(activeScorer);
167        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
168        assertEquals(PACKAGE_UID, activeScorer.packageUid);
169        assertNull(activeScorer.getEnableUseOpenWifiActivity());
170    }
171
172    @Test
173    public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotResolved()
174            throws Exception {
175        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
176        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
177        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
178                "package2" /* enableUseOpenWifiPackageActivityPackage*/);
179
180        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
181        assertNotNull(activeScorer);
182        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
183        assertEquals(PACKAGE_UID, activeScorer.packageUid);
184        assertNull(activeScorer.getEnableUseOpenWifiActivity());
185    }
186
187    @Test
188    public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityResolved()
189            throws Exception {
190        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
191        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
192        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
193        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
194                enableUseOpenWifiComponent.getPackageName());
195        mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
196
197        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
198        assertNotNull(activeScorer);
199        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
200        assertEquals(PACKAGE_UID, activeScorer.packageUid);
201        assertEquals(enableUseOpenWifiComponent, activeScorer.getEnableUseOpenWifiActivity());
202        assertNull(activeScorer.getNetworkAvailableNotificationChannelId());
203    }
204
205    @Test
206    public void testGetActiveScorer_providerAvailable_networkAvailableNotificationChannelIdSet() {
207        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
208        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
209        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
210                null /* enableUseOpenWifiActivityPackage */, false /* serviceLabelOverride */,
211                true /* setNotificationChannelId */);
212
213        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
214        assertNotNull(activeScorer);
215        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
216        assertEquals(PACKAGE_UID, activeScorer.packageUid);
217        assertEquals(MOCK_NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID,
218                activeScorer.getNetworkAvailableNotificationChannelId());
219    }
220
221    @Test
222    public void testGetActiveScorer_packageSettingIsNull()
223            throws Exception {
224        // NETWORK_RECOMMENDATIONS_PACKAGE is null
225
226        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
227        assertNull(activeScorer);
228    }
229
230    @Test
231    public void testGetActiveScorer_packageSettingIsInvalid() throws Exception {
232        setDefaultNetworkRecommendationPackage(RECO_COMPONENT.getPackageName());
233        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
234        // NETWORK_RECOMMENDATIONS_PACKAGE is set to a package that isn't a recommender.
235
236        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
237        assertNull(activeScorer);
238    }
239
240    @Test
241    public void testSetActiveScorer_noChange() throws Exception {
242        String packageName = "package";
243        setNetworkRecoPackageSetting(packageName);
244
245        assertTrue(mNetworkScorerAppManager.setActiveScorer(packageName));
246        verify(mSettingsFacade, never()).putString(any(), any(), any());
247    }
248
249    @Test
250    public void testSetActiveScorer_nullPackage_currentIsSet() throws Exception {
251        setNetworkRecoPackageSetting("package");
252
253        assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
254        verify(mSettingsFacade).putString(mMockContext,
255                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, null);
256        verify(mSettingsFacade).putInt(mMockContext,
257                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
258                NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
259    }
260
261    @Test
262    public void testSetActiveScorer_nullPackage_currentIsNull() throws Exception {
263        setNetworkRecoPackageSetting(null);
264
265        assertTrue(mNetworkScorerAppManager.setActiveScorer(null));
266        verify(mSettingsFacade, never()).putString(any(), any(), any());
267    }
268
269    @Test
270    public void testSetActiveScorer_validPackage() throws Exception {
271        String newPackage = "newPackage";
272        int newAppUid = 621;
273        final ComponentName recoComponent = new ComponentName(newPackage, "class1");
274        mockScoreNetworksGranted(recoComponent.getPackageName());
275        mockRecommendationServiceAvailable(recoComponent, newAppUid, null);
276        mockLocationPermissionGranted(newAppUid, recoComponent.getPackageName());
277
278        assertTrue(mNetworkScorerAppManager.setActiveScorer(newPackage));
279        verify(mSettingsFacade).putString(mMockContext,
280                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, newPackage);
281        verify(mSettingsFacade).putInt(mMockContext,
282                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
283                NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
284    }
285
286    @Test
287    public void testSetActiveScorer_invalidPackage() throws Exception {
288        String packageName = "package";
289        String newPackage = "newPackage";
290        setNetworkRecoPackageSetting(packageName);
291        // newPackage doesn't resolve to a valid recommender
292
293        assertFalse(mNetworkScorerAppManager.setActiveScorer(newPackage));
294        verify(mSettingsFacade, never()).putString(any(), any(), any());
295    }
296
297    @Test
298    public void testUpdateState_recommendationsForcedOff() throws Exception {
299        setRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
300
301        mNetworkScorerAppManager.updateState();
302
303        verify(mSettingsFacade, never()).getString(any(),
304                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE));
305        verify(mSettingsFacade, never()).putInt(any(),
306                eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt());
307    }
308
309    @Test
310    public void testUpdateState_currentPackageValid() throws Exception {
311        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
312        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
313        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID , null);
314
315        mNetworkScorerAppManager.updateState();
316
317        verify(mSettingsFacade, never()).putString(any(),
318                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
319        verify(mSettingsFacade).putInt(mMockContext,
320                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
321                NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
322    }
323
324    @Test
325    public void testUpdateState_currentPackageNotValid_validDefault() throws Exception {
326        final String defaultPackage = "defaultPackage";
327        final int defaultAppUid = 621;
328        final ComponentName recoComponent = new ComponentName(defaultPackage, "class1");
329        setDefaultNetworkRecommendationPackage(defaultPackage);
330        mockScoreNetworksGranted(recoComponent.getPackageName());
331        mockRecommendationServiceAvailable(recoComponent, defaultAppUid, null);
332        mockLocationPermissionGranted(defaultAppUid, defaultPackage);
333
334        mNetworkScorerAppManager.updateState();
335
336        verify(mSettingsFacade).putString(mMockContext,
337                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
338        verify(mSettingsFacade).putInt(mMockContext,
339                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
340                NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
341    }
342
343    @Test
344    public void testUpdateState_currentPackageNotValid_invalidDefault() throws Exception {
345        String defaultPackage = "defaultPackage";
346        setDefaultNetworkRecommendationPackage(defaultPackage);
347        setNetworkRecoPackageSetting("currentPackage");
348
349        mNetworkScorerAppManager.updateState();
350
351        verify(mSettingsFacade).putInt(mMockContext,
352                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
353                NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
354    }
355
356    @Test
357    public void testUpdateState_currentPackageNull_defaultNull() throws Exception {
358        setDefaultNetworkRecommendationPackage(null);
359        setNetworkRecoPackageSetting(null);
360
361        mNetworkScorerAppManager.updateState();
362
363        verify(mSettingsFacade, never()).putString(any(),
364                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString());
365        verify(mSettingsFacade).putInt(mMockContext,
366                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
367                NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
368    }
369
370    @Test
371    public void testUpdateState_currentPackageEmpty_defaultEmpty() throws Exception {
372        setDefaultNetworkRecommendationPackage("");
373        setNetworkRecoPackageSetting("");
374
375        mNetworkScorerAppManager.updateState();
376
377        verify(mSettingsFacade, never()).putString(any(),
378                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString());
379        verify(mSettingsFacade).putInt(mMockContext,
380                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
381                NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
382    }
383
384    @Test
385    public void testUpdateState_currentPackageNotValid_sameAsDefault() throws Exception {
386        String defaultPackage = "defaultPackage";
387        setDefaultNetworkRecommendationPackage(defaultPackage);
388        setNetworkRecoPackageSetting(defaultPackage);
389
390        mNetworkScorerAppManager.updateState();
391
392        verify(mSettingsFacade).putInt(mMockContext,
393                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
394                NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
395    }
396
397    @Test
398    public void testMigrateNetworkScorerAppSettingIfNeeded_networkScorerAppIsNull()
399            throws Exception {
400        when(mSettingsFacade.getString(mMockContext,
401                Settings.Global.NETWORK_SCORER_APP)).thenReturn(null);
402
403        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
404
405        verify(mSettingsFacade, never()).putString(eq(mMockContext),
406                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
407    }
408
409    @Test
410    public void testMigrateNetworkScorerAppSettingIfNeeded_networkScorerAppIsEmpty()
411            throws Exception {
412        when(mSettingsFacade.getString(mMockContext,
413                Settings.Global.NETWORK_SCORER_APP)).thenReturn("");
414
415        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
416
417        verify(mSettingsFacade, never()).putString(eq(mMockContext),
418                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
419    }
420
421    @Test
422    public void testMigrateNetworkScorerAppSettingIfNeeded_networkScorerIsNotActive()
423            throws Exception {
424        when(mSettingsFacade.getString(mMockContext,
425                Settings.Global.NETWORK_SCORER_APP)).thenReturn("com.foo.package");
426        // Make getActiveScorer() return null.
427        setRecommendationsEnabledSetting(NetworkScoreManager.RECOMMENDATIONS_ENABLED_FORCED_OFF);
428
429        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
430
431        verify(mSettingsFacade, never()).putString(eq(mMockContext),
432                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
433    }
434
435    @Test
436    public void testMigrateNetworkScorerAppSettingIfNeeded_useOpenWifiSettingIsNotEmpty()
437            throws Exception {
438        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
439        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
440        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
441        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
442                enableUseOpenWifiComponent.getPackageName());
443        mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
444        when(mSettingsFacade.getString(mMockContext,
445                Settings.Global.NETWORK_SCORER_APP))
446                .thenReturn(enableUseOpenWifiComponent.getPackageName());
447        // The setting has a value so the migration shouldn't touch it.
448        when(mSettingsFacade.getString(mMockContext,
449                Settings.Global.USE_OPEN_WIFI_PACKAGE))
450                .thenReturn(enableUseOpenWifiComponent.getPackageName());
451
452        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
453
454        verify(mSettingsFacade, never()).putString(eq(mMockContext),
455                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
456        verify(mSettingsFacade).putString(eq(mMockContext),
457                eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
458    }
459
460    @Test
461    public void testMigrateNetworkScorerAppSettingIfNeeded_useOpenWifiActivityNotAvail()
462            throws Exception {
463        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
464        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
465        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
466        // The active component doesn't have an open wifi activity so the migration shouldn't
467        // set USE_OPEN_WIFI_PACKAGE.
468        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
469                null /*useOpenWifiActivityPackage*/);
470        when(mSettingsFacade.getString(mMockContext,
471                Settings.Global.NETWORK_SCORER_APP))
472                .thenReturn(enableUseOpenWifiComponent.getPackageName());
473        when(mSettingsFacade.getString(mMockContext,
474                Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
475
476        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
477
478        verify(mSettingsFacade, never()).putString(eq(mMockContext),
479                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
480        verify(mSettingsFacade).putString(eq(mMockContext),
481                eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
482    }
483
484    @Test
485    public void testMigrateNetworkScorerAppSettingIfNeeded_packageMismatch_activity()
486            throws Exception {
487        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
488        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
489        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
490        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
491                enableUseOpenWifiComponent.getPackageName());
492        mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
493        // The older network scorer app setting doesn't match the new use open wifi activity package
494        // so the migration shouldn't set USE_OPEN_WIFI_PACKAGE.
495        when(mSettingsFacade.getString(mMockContext,
496                Settings.Global.NETWORK_SCORER_APP))
497                .thenReturn(enableUseOpenWifiComponent.getPackageName() + ".diff");
498        when(mSettingsFacade.getString(mMockContext,
499                Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
500
501        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
502
503        verify(mSettingsFacade, never()).putString(eq(mMockContext),
504                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
505        verify(mSettingsFacade).putString(eq(mMockContext),
506                eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
507    }
508
509    @Test
510    public void testMigrateNetworkScorerAppSettingIfNeeded_packageMismatch_service()
511            throws Exception {
512        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
513        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
514        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
515        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
516                enableUseOpenWifiComponent.getPackageName());
517        mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
518        // The older network scorer app setting doesn't match the active package so the migration
519        // shouldn't set USE_OPEN_WIFI_PACKAGE.
520        when(mSettingsFacade.getString(mMockContext,
521                Settings.Global.NETWORK_SCORER_APP))
522                .thenReturn(RECO_COMPONENT.getPackageName() + ".diff");
523        when(mSettingsFacade.getString(mMockContext,
524                Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
525
526        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
527
528        verify(mSettingsFacade, never()).putString(eq(mMockContext),
529                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE), anyString());
530        verify(mSettingsFacade).putString(eq(mMockContext),
531                eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
532    }
533
534    @Test
535    public void testMigrateNetworkScorerAppSettingIfNeeded_packageMatch_activity()
536            throws Exception {
537        final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
538        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
539        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
540        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
541                enableUseOpenWifiComponent.getPackageName());
542        mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
543        // Old setting matches the new activity package, migration should happen.
544        when(mSettingsFacade.getString(mMockContext,
545                Settings.Global.NETWORK_SCORER_APP))
546                .thenReturn(enableUseOpenWifiComponent.getPackageName());
547        when(mSettingsFacade.getString(mMockContext,
548                Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
549
550        mNetworkScorerAppManager.migrateNetworkScorerAppSettingIfNeeded();
551
552        verify(mSettingsFacade).putString(eq(mMockContext),
553                eq(Settings.Global.USE_OPEN_WIFI_PACKAGE),
554                eq(enableUseOpenWifiComponent.getPackageName()));
555        verify(mSettingsFacade).putString(eq(mMockContext),
556                eq(Settings.Global.NETWORK_SCORER_APP), eq(null));
557    }
558
559    private void setRecommendationsEnabledSetting(int value) {
560        when(mSettingsFacade.getInt(eq(mMockContext),
561                eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt())).thenReturn(value);
562    }
563
564    private void setNetworkRecoPackageSetting(String packageName) {
565        when(mSettingsFacade.getString(mMockContext,
566                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE)).thenReturn(packageName);
567    }
568
569    private void setDefaultNetworkRecommendationPackage(String name) {
570        when(mResources.getString(R.string.config_defaultNetworkRecommendationProviderPackage))
571                .thenReturn(name);
572    }
573
574    private void mockScoreNetworksGranted(String packageName) {
575        when(mMockPm.checkPermission(permission.SCORE_NETWORKS, packageName))
576                .thenReturn(PackageManager.PERMISSION_GRANTED);
577    }
578
579    private void mockScoreNetworksDenied(String packageName) {
580        when(mMockPm.checkPermission(permission.SCORE_NETWORKS, packageName))
581                .thenReturn(PackageManager.PERMISSION_DENIED);
582    }
583
584    private void mockLocationModeOn() {
585        mockLocationModeValue(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
586    }
587
588    private void mockLocationModeOff() {
589        mockLocationModeValue(Settings.Secure.LOCATION_MODE_OFF);
590    }
591
592    private void mockLocationModeValue(int returnVal) {
593        when(mSettingsFacade.getSecureInt(eq(mMockContext),
594                eq(Settings.Secure.LOCATION_MODE), anyInt())).thenReturn(returnVal);
595    }
596
597    private void mockLocationPermissionGranted(int uid, String packageName) {
598        when(mMockPm.checkPermission(permission.ACCESS_COARSE_LOCATION, packageName))
599                .thenReturn(PackageManager.PERMISSION_GRANTED);
600        when(mAppOpsManager.noteOp(AppOpsManager.OP_COARSE_LOCATION, uid, packageName))
601                .thenReturn(AppOpsManager.MODE_ALLOWED);
602    }
603
604    private void mockLocationPermissionDenied(int uid, String packageName) {
605        when(mMockPm.checkPermission(permission.ACCESS_COARSE_LOCATION, packageName))
606                .thenReturn(PackageManager.PERMISSION_DENIED);
607        when(mAppOpsManager.noteOp(AppOpsManager.OP_COARSE_LOCATION, uid, packageName))
608                .thenReturn(AppOpsManager.MODE_IGNORED);
609    }
610
611    private void mockRecommendationServiceAvailable(final ComponentName compName, int packageUid) {
612        mockRecommendationServiceAvailable(compName, packageUid, null, false);
613    }
614
615    private void mockRecommendationServiceAvailable(final ComponentName compName, int packageUid,
616            String enableUseOpenWifiActivityPackage) {
617        mockRecommendationServiceAvailable(
618                compName, packageUid, enableUseOpenWifiActivityPackage, false);
619    }
620
621    private void mockRecommendationServiceAvailable(final ComponentName compName, int packageUid,
622            String enableUseOpenWifiActivityPackage, boolean serviceLabelOverride) {
623        mockRecommendationServiceAvailable(compName, packageUid, enableUseOpenWifiActivityPackage,
624                serviceLabelOverride, false);
625    }
626
627    private void mockRecommendationServiceAvailable(final ComponentName compName, int packageUid,
628            String enableUseOpenWifiActivityPackage, boolean serviceLabelOverride,
629            boolean setNotificationChannel) {
630        final ResolveInfo serviceInfo = new ResolveInfo();
631        serviceInfo.serviceInfo = new ServiceInfo();
632        serviceInfo.serviceInfo.name = compName.getClassName();
633        serviceInfo.serviceInfo.packageName = compName.getPackageName();
634        serviceInfo.serviceInfo.applicationInfo = new ApplicationInfo();
635        serviceInfo.serviceInfo.applicationInfo.uid = packageUid;
636        if (enableUseOpenWifiActivityPackage != null) {
637            serviceInfo.serviceInfo.metaData = new Bundle();
638            serviceInfo.serviceInfo.metaData.putString(
639                    NetworkScoreManager.USE_OPEN_WIFI_PACKAGE_META_DATA,
640                    enableUseOpenWifiActivityPackage);
641        }
642        if (serviceLabelOverride) {
643            if (serviceInfo.serviceInfo.metaData == null) {
644                serviceInfo.serviceInfo.metaData = new Bundle();
645            }
646            serviceInfo.serviceInfo.metaData.putString(
647                    NetworkScoreManager.RECOMMENDATION_SERVICE_LABEL_META_DATA,
648                    MOCK_OVERRIDEN_SERVICE_LABEL);
649        } else {
650            serviceInfo.serviceInfo.nonLocalizedLabel = MOCK_SERVICE_LABEL;
651        }
652        if (setNotificationChannel) {
653            if (serviceInfo.serviceInfo.metaData == null) {
654                serviceInfo.serviceInfo.metaData = new Bundle();
655            }
656            serviceInfo.serviceInfo.metaData.putString(
657                    NetworkScoreManager.NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID_META_DATA,
658                    MOCK_NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID);
659        }
660
661        final int flags = PackageManager.GET_META_DATA;
662        when(mMockPm.resolveService(
663                Mockito.argThat(intent -> NetworkScoreManager.ACTION_RECOMMEND_NETWORKS
664                        .equals(intent.getAction())
665                        && compName.getPackageName().equals(intent.getPackage())),
666                Mockito.eq(flags))).thenReturn(serviceInfo);
667
668        mAvailableServices.add(serviceInfo);
669    }
670
671    private void mockEnableUseOpenWifiActivity(final ComponentName useOpenWifiComp) {
672        final ResolveInfo resolveActivityInfo = new ResolveInfo();
673        resolveActivityInfo.activityInfo = new ActivityInfo();
674        resolveActivityInfo.activityInfo.name = useOpenWifiComp.getClassName();
675        resolveActivityInfo.activityInfo.packageName = useOpenWifiComp.getPackageName();
676
677        final int flags = 0;
678        when(mMockPm.resolveActivity(
679                Mockito.argThat(intent ->
680                        NetworkScoreManager.ACTION_CUSTOM_ENABLE.equals(intent.getAction())
681                                && useOpenWifiComp.getPackageName().equals(intent.getPackage())),
682                Mockito.eq(flags))).thenReturn(resolveActivityInfo);
683    }
684}
685