diff --git a/res/values/strings.xml b/res/values/strings.xml
index 36790575d3c..099a29039ef 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3039,6 +3039,8 @@
Device only
Location off
+
+ App-level permissions
Recent location requests
diff --git a/res/xml/location_settings.xml b/res/xml/location_settings.xml
index 1abf9be7043..ecce221790e 100644
--- a/res/xml/location_settings.xml
+++ b/res/xml/location_settings.xml
@@ -34,6 +34,11 @@
android:enabled="false"
android:selectable="true" />
+
+
+
diff --git a/src/com/android/settings/location/AppLocationPermissionPreferenceController.java b/src/com/android/settings/location/AppLocationPermissionPreferenceController.java
new file mode 100644
index 00000000000..d91b47b9cb6
--- /dev/null
+++ b/src/com/android/settings/location/AppLocationPermissionPreferenceController.java
@@ -0,0 +1,39 @@
+package com.android.settings.location;
+
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.core.PreferenceController;
+
+public class AppLocationPermissionPreferenceController extends PreferenceController {
+
+ private static final String KEY_APP_LEVEL_PERMISSIONS = "app_level_permissions";
+ private Preference mPreference;
+
+ public AppLocationPermissionPreferenceController(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ if (isAvailable()) {
+ mPreference = screen.findPreference(KEY_APP_LEVEL_PERMISSIONS);
+ }
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_APP_LEVEL_PERMISSIONS;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ android.provider.Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED, 1)
+ == 1;
+ }
+}
diff --git a/src/com/android/settings/location/LocationSettings.java b/src/com/android/settings/location/LocationSettings.java
index 03aa155992e..d6ff4dcaaea 100644
--- a/src/com/android/settings/location/LocationSettings.java
+++ b/src/com/android/settings/location/LocationSettings.java
@@ -18,6 +18,7 @@ package com.android.settings.location;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
+import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -95,11 +96,14 @@ public class LocationSettings extends LocationSettingsBase
private static final String KEY_LOCATION_MODE = "location_mode";
/** Key for preference category "Recent location requests" */
private static final String KEY_RECENT_LOCATION_REQUESTS = "recent_location_requests";
+ /** Key for preference "App-level permissions" */
+ private static final String KEY_APP_LEVEL_PERMISSIONS = "app_level_permissions";
/** Key for preference category "Location services" */
private static final String KEY_LOCATION_SERVICES = "location_services";
private static final int MENU_SCANNING = Menu.FIRST;
+ private static final String KEY_LOCATION_PERMISSION = "android.permission-group.LOCATION";
private SwitchBar mSwitchBar;
private Switch mSwitch;
private boolean mValidListener = false;
@@ -201,10 +205,21 @@ public class LocationSettings extends LocationSettingsBase
}
});
- mCategoryRecentLocationRequests =
- (PreferenceCategory) root.findPreference(KEY_RECENT_LOCATION_REQUESTS);
RecentLocationApps recentApps = new RecentLocationApps(activity);
List recentLocationRequests = recentApps.getAppList();
+
+ final AppLocationPermissionPreferenceController preferenceController =
+ new AppLocationPermissionPreferenceController(activity);
+ preferenceController.displayPreference(root);
+ if (preferenceController.isAvailable()) {
+ Preference preferenceAppLevelPermissions =
+ root.findPreference(KEY_APP_LEVEL_PERMISSIONS);
+ setupAppLevelPermissionsPreference(preferenceAppLevelPermissions);
+ }
+
+ mCategoryRecentLocationRequests =
+ (PreferenceCategory) root.findPreference(KEY_RECENT_LOCATION_REQUESTS);
+
List recentLocationPrefs = new ArrayList<>(recentLocationRequests.size());
for (final RecentLocationApps.Request request : recentLocationRequests) {
DimmableIconPreference pref = new DimmableIconPreference(getPrefContext(),
@@ -261,6 +276,23 @@ public class LocationSettings extends LocationSettingsBase
}
}
+ private void setupAppLevelPermissionsPreference(Preference preference) {
+ preference.setOnPreferenceClickListener(
+ new Preference.OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ Intent intent = new Intent(Intent.ACTION_MANAGE_PERMISSION_APPS)
+ .putExtra(Intent.EXTRA_PERMISSION_NAME, KEY_LOCATION_PERMISSION);
+ try {
+ getActivity().startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Log.w("Permission", "No app to handle " + intent);
+ }
+ return true;
+ }
+ });
+ }
+
private void changeManagedProfileLocationAccessStatus(boolean mainSwitchOn) {
if (mManagedProfileSwitch == null) {
return;
diff --git a/tests/robotests/src/com/android/settings/location/AppLocationPermissionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/location/AppLocationPermissionPreferenceControllerTest.java
new file mode 100644
index 00000000000..8a035e5140e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/location/AppLocationPermissionPreferenceControllerTest.java
@@ -0,0 +1,69 @@
+package com.android.settings.location;
+
+import android.content.Context;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowApplication;
+
+import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class AppLocationPermissionPreferenceControllerTest {
+ @Mock
+ private Preference mPreference;
+ @Mock(answer = RETURNS_DEEP_STUBS)
+ private PreferenceScreen mScreen;
+
+ private AppLocationPermissionPreferenceController mController;
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mScreen.findPreference(anyString())).thenReturn(mPreference);
+ mController = new AppLocationPermissionPreferenceController(mContext);
+ }
+
+ @Test
+ public void displayPreference_shouldRemovePreference() {
+ Settings.System.putInt(mContext.getContentResolver(),
+ android.provider.Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED,
+ 0);
+
+ mController.displayPreference(mScreen);
+
+ verify(mScreen).removePreference(any(Preference.class));
+ }
+
+ @Test
+ public void displayPreference_shouldNotRemovePreference() {
+ Settings.System.putInt(mContext.getContentResolver(),
+ android.provider.Settings.Global.LOCATION_SETTINGS_LINK_TO_PERMISSIONS_ENABLED,
+ 1);
+ mController.displayPreference(mScreen);
+
+ verify(mScreen, never()).removePreference(any(Preference.class));
+ }
+
+}