Merge "NetworkRecommendationProviders require the location permission." into oc-mr1-dev
am: 589ba65d91

Change-Id: I971c3a922340ee2d73722eea5e293d928b6f9a54
diff --git a/core/java/android/net/NetworkRecommendationProvider.java b/core/java/android/net/NetworkRecommendationProvider.java
index fdb4ba0..a70c97b 100644
--- a/core/java/android/net/NetworkRecommendationProvider.java
+++ b/core/java/android/net/NetworkRecommendationProvider.java
@@ -35,6 +35,7 @@
  * A network recommendation provider is any application which:
  * <ul>
  * <li>Is granted the {@link permission#SCORE_NETWORKS} permission.
+ * <li>Is granted the {@link permission#ACCESS_COARSE_LOCATION} permission.
  * <li>Includes a Service for the {@link NetworkScoreManager#ACTION_RECOMMEND_NETWORKS} intent
  *     which is protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE} permission.
  * </ul>
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 7e0c9ce..060af0d 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -38,7 +38,8 @@
  *
  * <p>A network scorer is any application which:
  * <ul>
- * <li>Declares the {@link permission#SCORE_NETWORKS} permission.
+ * <li>Is granted the {@link permission#SCORE_NETWORKS} permission.
+ * <li>Is granted the {@link permission#ACCESS_COARSE_LOCATION} permission.
  * <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action
  *     protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE}
  *     permission.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 06aa9a3..4b64e3f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1391,6 +1391,7 @@
     <!-- The package name of the default network recommendation app.
          A network recommendation provider must:
              * Be granted the SCORE_NETWORKS permission.
+             * Be granted the ACCESS_COARSE_LOCATION permission.
              * Include a Service for the android.net.scoring.RECOMMEND_NETWORKS action
                protected by the BIND_NETWORK_RECOMMENDATION_SERVICE permission.
 
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
index fdc0bba..d60df83 100644
--- a/services/core/java/com/android/server/NetworkScoreService.java
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -27,6 +27,7 @@
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
+import android.location.LocationManager;
 import android.net.INetworkRecommendationProvider;
 import android.net.INetworkScoreCache;
 import android.net.INetworkScoreService;
@@ -113,6 +114,16 @@
         }
     };
 
+    private BroadcastReceiver mLocationModeReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            final String action = intent.getAction();
+            if (LocationManager.MODE_CHANGED_ACTION.equals(action)) {
+                refreshBinding();
+            }
+        }
+    };
+
     /**
      * Clears scores when the active scorer package is no longer valid and
      * manages the service connection.
@@ -241,6 +252,10 @@
                 mUserIntentReceiver, UserHandle.SYSTEM, filter, null /* broadcastPermission*/,
                 null /* scheduler */);
         mHandler = new ServiceHandler(looper);
+        IntentFilter locationModeFilter = new IntentFilter(LocationManager.MODE_CHANGED_ACTION);
+        mContext.registerReceiverAsUser(
+                mLocationModeReceiver, UserHandle.SYSTEM, locationModeFilter,
+                null /* broadcastPermission*/, mHandler);
         mContentObserver = new DispatchingContentObserver(context, mHandler);
         mServiceConnProducer = serviceConnProducer;
     }
diff --git a/services/core/java/com/android/server/NetworkScorerAppManager.java b/services/core/java/com/android/server/NetworkScorerAppManager.java
index 42777bf..bfd4247 100644
--- a/services/core/java/com/android/server/NetworkScorerAppManager.java
+++ b/services/core/java/com/android/server/NetworkScorerAppManager.java
@@ -18,6 +18,7 @@
 
 import android.Manifest.permission;
 import android.annotation.Nullable;
+import android.app.AppOpsManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -79,7 +80,7 @@
         List<NetworkScorerAppData> appDataList = new ArrayList<>();
         for (int i = 0; i < resolveInfos.size(); i++) {
             final ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo;
-            if (hasPermissions(serviceInfo.packageName)) {
+            if (hasPermissions(serviceInfo.applicationInfo.uid, serviceInfo.packageName)) {
                 if (VERBOSE) {
                     Log.v(TAG, serviceInfo.packageName + " is a valid scorer/recommender.");
                 }
@@ -197,12 +198,33 @@
         return null;
     }
 
-    private boolean hasPermissions(String packageName) {
+    private boolean hasPermissions(final int uid, final String packageName) {
+        return hasScoreNetworksPermission(packageName)
+                && canAccessLocation(uid, packageName);
+    }
+
+    private boolean hasScoreNetworksPermission(String packageName) {
         final PackageManager pm = mContext.getPackageManager();
         return pm.checkPermission(permission.SCORE_NETWORKS, packageName)
                 == PackageManager.PERMISSION_GRANTED;
     }
 
+    private boolean canAccessLocation(int uid, String packageName) {
+        final PackageManager pm = mContext.getPackageManager();
+        final AppOpsManager appOpsManager =
+                (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+        return isLocationModeEnabled()
+                && pm.checkPermission(permission.ACCESS_COARSE_LOCATION, packageName)
+                == PackageManager.PERMISSION_GRANTED
+                && appOpsManager.noteOp(AppOpsManager.OP_COARSE_LOCATION, uid, packageName)
+                == AppOpsManager.MODE_ALLOWED;
+    }
+
+    private boolean isLocationModeEnabled() {
+        return mSettingsFacade.getSecureInt(mContext, Settings.Secure.LOCATION_MODE,
+                Settings.Secure.LOCATION_MODE_OFF) != Settings.Secure.LOCATION_MODE_OFF;
+    }
+
     /**
      * Set the specified package as the default scorer application.
      *
@@ -270,23 +292,20 @@
             return;
         }
 
-        // the active scorer isn't valid, revert to the default if it's different
+        int newEnabledSetting = NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF;
+        // the active scorer isn't valid, revert to the default if it's different and valid
         final String defaultPackageName = getDefaultPackageSetting();
-        if (!TextUtils.equals(currentPackageName, defaultPackageName)) {
-            setNetworkRecommendationsPackage(defaultPackageName);
+        if (!TextUtils.equals(currentPackageName, defaultPackageName)
+                && getScorer(defaultPackageName) != null) {
             if (DEBUG) {
-                Log.d(TAG, "Defaulted the network recommendations app to: " + defaultPackageName);
+                Log.d(TAG, "Defaulting the network recommendations app to: "
+                        + defaultPackageName);
             }
-            if (getScorer(defaultPackageName) != null) { // the default is valid
-                if (DEBUG) Log.d(TAG, defaultPackageName + " is now the active scorer.");
-                setNetworkRecommendationsEnabledSetting(
-                        NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON);
-            } else { // the default isn't valid either, we're disabled at this point
-                if (DEBUG) Log.d(TAG, defaultPackageName + " is not an active scorer.");
-                setNetworkRecommendationsEnabledSetting(
-                        NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
-            }
+            setNetworkRecommendationsPackage(defaultPackageName);
+            newEnabledSetting = NetworkScoreManager.RECOMMENDATIONS_ENABLED_ON;
         }
+
+        setNetworkRecommendationsEnabledSetting(newEnabledSetting);
     }
 
     /**
@@ -352,6 +371,9 @@
     private void setNetworkRecommendationsPackage(String packageName) {
         mSettingsFacade.putString(mContext,
                 Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, packageName);
+        if (VERBOSE) {
+            Log.d(TAG, Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE + " set to " + packageName);
+        }
     }
 
     private int getNetworkRecommendationsEnabledSetting() {
@@ -361,6 +383,9 @@
     private void setNetworkRecommendationsEnabledSetting(int value) {
         mSettingsFacade.putInt(mContext,
                 Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED, value);
+        if (VERBOSE) {
+            Log.d(TAG, Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED + " set to " + value);
+        }
     }
 
     /**
@@ -382,5 +407,9 @@
         public int getInt(Context context, String name, int defaultValue) {
             return Settings.Global.getInt(context.getContentResolver(), name, defaultValue);
         }
+
+        public int getSecureInt(Context context, String name, int defaultValue) {
+            return Settings.Secure.getInt(context.getContentResolver(), name, defaultValue);
+        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
index ceb92de..82ff0d8 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScorerAppManagerTest.java
@@ -31,6 +31,7 @@
 import static org.mockito.Mockito.when;
 
 import android.Manifest.permission;
+import android.app.AppOpsManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -61,15 +62,18 @@
 
 @RunWith(AndroidJUnit4.class)
 public class NetworkScorerAppManagerTest {
+    private static final int PACKAGE_UID = 924;
     private static String MOCK_SERVICE_LABEL = "Mock Service";
     private static String MOCK_OVERRIDEN_SERVICE_LABEL = "Mock Service Label Override";
     private static String MOCK_NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID =
             "Mock Network Available Notification Channel Id";
+    private static final ComponentName RECO_COMPONENT = new ComponentName("package1", "class1");
 
     @Mock private Context mMockContext;
     @Mock private PackageManager mMockPm;
     @Mock private Resources mResources;
     @Mock private NetworkScorerAppManager.SettingsFacade mSettingsFacade;
+    @Mock private AppOpsManager mAppOpsManager;
     private NetworkScorerAppManager mNetworkScorerAppManager;
     private List<ResolveInfo> mAvailableServices;
 
@@ -86,45 +90,69 @@
             }
         }), eq(PackageManager.GET_META_DATA))).thenReturn(mAvailableServices);
         when(mMockContext.getResources()).thenReturn(mResources);
+        when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
+
+        mockLocationModeOn();
+        mockLocationPermissionGranted(PACKAGE_UID, RECO_COMPONENT.getPackageName());
 
         mNetworkScorerAppManager = new NetworkScorerAppManager(mMockContext, mSettingsFacade);
     }
 
     @Test
     public void testGetActiveScorer_providerAvailable() throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */);
 
         final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
         assertNotNull(activeScorer);
-        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
-        assertEquals(924, activeScorer.packageUid);
+        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
+        assertEquals(PACKAGE_UID, activeScorer.packageUid);
         assertEquals(MOCK_SERVICE_LABEL, activeScorer.getRecommendationServiceLabel());
     }
 
     @Test
     public void testGetActiveScorer_providerAvailable_serviceLabelOverride() throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
                 null /* enableUseOpenWifiPackageActivityPackage*/, true /* serviceLabelOverride */);
 
         final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
         assertNotNull(activeScorer);
-        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
-        assertEquals(924, activeScorer.packageUid);
+        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
+        assertEquals(PACKAGE_UID, activeScorer.packageUid);
         assertEquals(MOCK_OVERRIDEN_SERVICE_LABEL, activeScorer.getRecommendationServiceLabel());
     }
 
     @Test
-    public void testGetActiveScorer_permissionMissing() throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksDenied(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */);
+    public void testGetActiveScorer_scoreNetworksPermissionMissing() throws Exception {
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksDenied(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */);
+
+        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+        assertNull(activeScorer);
+    }
+
+    @Test
+    public void testGetActiveScorer_locationPermissionMissing() throws Exception {
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockLocationPermissionDenied(PACKAGE_UID, RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */);
+
+        final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
+        assertNull(activeScorer);
+    }
+
+    @Test
+    public void testGetActiveScorer_locationModeOff() throws Exception {
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockLocationPermissionGranted(PACKAGE_UID, RECO_COMPONENT.getPackageName());
+        mockLocationModeOff();
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */);
 
         final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
         assertNull(activeScorer);
@@ -133,67 +161,63 @@
     @Test
     public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotSet()
             throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
                 null /* enableUseOpenWifiPackageActivityPackage*/);
 
         final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
         assertNotNull(activeScorer);
-        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
-        assertEquals(924, activeScorer.packageUid);
+        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
+        assertEquals(PACKAGE_UID, activeScorer.packageUid);
         assertNull(activeScorer.getEnableUseOpenWifiActivity());
     }
 
     @Test
     public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityNotResolved()
             throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
                 "package2" /* enableUseOpenWifiPackageActivityPackage*/);
 
         final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
         assertNotNull(activeScorer);
-        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
-        assertEquals(924, activeScorer.packageUid);
+        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
+        assertEquals(PACKAGE_UID, activeScorer.packageUid);
         assertNull(activeScorer.getEnableUseOpenWifiActivity());
     }
 
     @Test
     public void testGetActiveScorer_providerAvailable_enableUseOpenWifiActivityResolved()
             throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
         final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
                 enableUseOpenWifiComponent.getPackageName());
         mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
 
         final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
         assertNotNull(activeScorer);
-        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
-        assertEquals(924, activeScorer.packageUid);
+        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
+        assertEquals(PACKAGE_UID, activeScorer.packageUid);
         assertEquals(enableUseOpenWifiComponent, activeScorer.getEnableUseOpenWifiActivity());
         assertNull(activeScorer.getNetworkAvailableNotificationChannelId());
     }
 
     @Test
     public void testGetActiveScorer_providerAvailable_networkAvailableNotificationChannelIdSet() {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
                 null /* enableUseOpenWifiActivityPackage */, false /* serviceLabelOverride */,
                 true /* setNotificationChannelId */);
 
         final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
         assertNotNull(activeScorer);
-        assertEquals(recoComponent, activeScorer.getRecommendationServiceComponent());
-        assertEquals(924, activeScorer.packageUid);
+        assertEquals(RECO_COMPONENT, activeScorer.getRecommendationServiceComponent());
+        assertEquals(PACKAGE_UID, activeScorer.packageUid);
         assertEquals(MOCK_NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID,
                 activeScorer.getNetworkAvailableNotificationChannelId());
     }
@@ -209,9 +233,8 @@
 
     @Test
     public void testGetActiveScorer_packageSettingIsInvalid() throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
-        setDefaultNetworkRecommendationPackage(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
+        setDefaultNetworkRecommendationPackage(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
         // NETWORK_RECOMMENDATIONS_PACKAGE is set to a package that isn't a recommender.
 
         final NetworkScorerAppData activeScorer = mNetworkScorerAppManager.getActiveScorer();
@@ -249,12 +272,12 @@
 
     @Test
     public void testSetActiveScorer_validPackage() throws Exception {
-        String packageName = "package";
         String newPackage = "newPackage";
-        setNetworkRecoPackageSetting(packageName);
+        int newAppUid = 621;
         final ComponentName recoComponent = new ComponentName(newPackage, "class1");
         mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+        mockRecommendationServiceAvailable(recoComponent, newAppUid, null);
+        mockLocationPermissionGranted(newAppUid, recoComponent.getPackageName());
 
         assertTrue(mNetworkScorerAppManager.setActiveScorer(newPackage));
         verify(mSettingsFacade).putString(mMockContext,
@@ -289,11 +312,9 @@
 
     @Test
     public void testUpdateState_currentPackageValid() throws Exception {
-        String packageName = "package";
-        setNetworkRecoPackageSetting(packageName);
-        final ComponentName recoComponent = new ComponentName(packageName, "class1");
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID , null);
 
         mNetworkScorerAppManager.updateState();
 
@@ -306,11 +327,13 @@
 
     @Test
     public void testUpdateState_currentPackageNotValid_validDefault() throws Exception {
-        String defaultPackage = "defaultPackage";
-        setDefaultNetworkRecommendationPackage(defaultPackage);
+        final String defaultPackage = "defaultPackage";
+        final int defaultAppUid = 621;
         final ComponentName recoComponent = new ComponentName(defaultPackage, "class1");
+        setDefaultNetworkRecommendationPackage(defaultPackage);
         mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */, null);
+        mockRecommendationServiceAvailable(recoComponent, defaultAppUid, null);
+        mockLocationPermissionGranted(defaultAppUid, defaultPackage);
 
         mNetworkScorerAppManager.updateState();
 
@@ -329,8 +352,6 @@
 
         mNetworkScorerAppManager.updateState();
 
-        verify(mSettingsFacade).putString(mMockContext,
-                Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE, defaultPackage);
         verify(mSettingsFacade).putInt(mMockContext,
                 Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
                 NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
@@ -345,8 +366,9 @@
 
         verify(mSettingsFacade, never()).putString(any(),
                 eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString());
-        verify(mSettingsFacade, never()).putInt(any(),
-                eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt());
+        verify(mSettingsFacade).putInt(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+                NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
     }
 
     @Test
@@ -358,8 +380,9 @@
 
         verify(mSettingsFacade, never()).putString(any(),
                 eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), anyString());
-        verify(mSettingsFacade, never()).putInt(any(),
-                eq(Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED), anyInt());
+        verify(mSettingsFacade).putInt(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+                NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
     }
 
     @Test
@@ -370,8 +393,9 @@
 
         mNetworkScorerAppManager.updateState();
 
-        verify(mSettingsFacade, never()).putString(any(),
-                eq(Settings.Global.NETWORK_RECOMMENDATIONS_PACKAGE), any());
+        verify(mSettingsFacade).putInt(mMockContext,
+                Settings.Global.NETWORK_RECOMMENDATIONS_ENABLED,
+                NetworkScoreManager.RECOMMENDATIONS_ENABLED_OFF);
     }
 
     @Test
@@ -415,11 +439,10 @@
     @Test
     public void testMigrateNetworkScorerAppSettingIfNeeded_useOpenWifiSettingIsNotEmpty()
             throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
         final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
                 enableUseOpenWifiComponent.getPackageName());
         mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
         when(mSettingsFacade.getString(mMockContext,
@@ -441,13 +464,12 @@
     @Test
     public void testMigrateNetworkScorerAppSettingIfNeeded_useOpenWifiActivityNotAvail()
             throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
         final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
         // The active component doesn't have an open wifi activity so the migration shouldn't
         // set USE_OPEN_WIFI_PACKAGE.
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
                 null /*useOpenWifiActivityPackage*/);
         when(mSettingsFacade.getString(mMockContext,
                 Settings.Global.NETWORK_SCORER_APP))
@@ -466,11 +488,10 @@
     @Test
     public void testMigrateNetworkScorerAppSettingIfNeeded_packageMismatch_activity()
             throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
         final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
                 enableUseOpenWifiComponent.getPackageName());
         mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
         // The older network scorer app setting doesn't match the new use open wifi activity package
@@ -492,18 +513,17 @@
     @Test
     public void testMigrateNetworkScorerAppSettingIfNeeded_packageMismatch_service()
             throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
         final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
                 enableUseOpenWifiComponent.getPackageName());
         mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
         // The older network scorer app setting doesn't match the active package so the migration
         // shouldn't set USE_OPEN_WIFI_PACKAGE.
         when(mSettingsFacade.getString(mMockContext,
                 Settings.Global.NETWORK_SCORER_APP))
-                .thenReturn(recoComponent.getPackageName() + ".diff");
+                .thenReturn(RECO_COMPONENT.getPackageName() + ".diff");
         when(mSettingsFacade.getString(mMockContext,
                 Settings.Global.USE_OPEN_WIFI_PACKAGE)).thenReturn(null);
 
@@ -518,11 +538,10 @@
     @Test
     public void testMigrateNetworkScorerAppSettingIfNeeded_packageMatch_activity()
             throws Exception {
-        final ComponentName recoComponent = new ComponentName("package1", "class1");
         final ComponentName enableUseOpenWifiComponent = new ComponentName("package2", "class2");
-        setNetworkRecoPackageSetting(recoComponent.getPackageName());
-        mockScoreNetworksGranted(recoComponent.getPackageName());
-        mockRecommendationServiceAvailable(recoComponent, 924 /* packageUid */,
+        setNetworkRecoPackageSetting(RECO_COMPONENT.getPackageName());
+        mockScoreNetworksGranted(RECO_COMPONENT.getPackageName());
+        mockRecommendationServiceAvailable(RECO_COMPONENT, PACKAGE_UID /* packageUid */,
                 enableUseOpenWifiComponent.getPackageName());
         mockEnableUseOpenWifiActivity(enableUseOpenWifiComponent);
         // Old setting matches the new activity package, migration should happen.
@@ -566,6 +585,33 @@
                 .thenReturn(PackageManager.PERMISSION_DENIED);
     }
 
+    private void mockLocationModeOn() {
+        mockLocationModeValue(Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
+    }
+
+    private void mockLocationModeOff() {
+        mockLocationModeValue(Settings.Secure.LOCATION_MODE_OFF);
+    }
+
+    private void mockLocationModeValue(int returnVal) {
+        when(mSettingsFacade.getSecureInt(eq(mMockContext),
+                eq(Settings.Secure.LOCATION_MODE), anyInt())).thenReturn(returnVal);
+    }
+
+    private void mockLocationPermissionGranted(int uid, String packageName) {
+        when(mMockPm.checkPermission(permission.ACCESS_COARSE_LOCATION, packageName))
+                .thenReturn(PackageManager.PERMISSION_GRANTED);
+        when(mAppOpsManager.noteOp(AppOpsManager.OP_COARSE_LOCATION, uid, packageName))
+                .thenReturn(AppOpsManager.MODE_ALLOWED);
+    }
+
+    private void mockLocationPermissionDenied(int uid, String packageName) {
+        when(mMockPm.checkPermission(permission.ACCESS_COARSE_LOCATION, packageName))
+                .thenReturn(PackageManager.PERMISSION_DENIED);
+        when(mAppOpsManager.noteOp(AppOpsManager.OP_COARSE_LOCATION, uid, packageName))
+                .thenReturn(AppOpsManager.MODE_IGNORED);
+    }
+
     private void mockRecommendationServiceAvailable(final ComponentName compName, int packageUid) {
         mockRecommendationServiceAvailable(compName, packageUid, null, false);
     }