OSDN Git Service

Access mock location is no longer a runtime permission - settings
[android-x86/packages-apps-Settings.git] / src / com / android / settings / DevelopmentSettings.java
index e0091e1..5148e1a 100644 (file)
 
 package com.android.settings;
 
+import android.Manifest;
 import android.app.Activity;
 import android.app.ActivityManagerNative;
 import android.app.AlertDialog;
+import android.app.AppOpsManager;
+import android.app.AppOpsManager.PackageOps;
 import android.app.Dialog;
 import android.app.admin.DevicePolicyManager;
 import android.app.backup.IBackupManager;
 import android.bluetooth.BluetoothAdapter;
 import android.content.BroadcastReceiver;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -73,6 +77,7 @@ import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settings.widget.SwitchBar;
 
+import java.lang.Process;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -96,13 +101,15 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
      */
     public static final String PREF_SHOW = "show";
 
+    private static final ComponentName SYSUI_TUNER = new ComponentName("com.android.systemui",
+            "com.android.systemui.tuner.TunerActivity");
+
     private static final String ENABLE_ADB = "enable_adb";
     private static final String CLEAR_ADB_KEYS = "clear_adb_keys";
     private static final String ENABLE_TERMINAL = "enable_terminal";
     private static final String KEEP_SCREEN_ON = "keep_screen_on";
     private static final String BT_HCI_SNOOP_LOG = "bt_hci_snoop_log";
     private static final String ENABLE_OEM_UNLOCK = "oem_unlock_enable";
-    private static final String ALLOW_MOCK_LOCATION = "allow_mock_location";
     private static final String HDCP_CHECKING_KEY = "hdcp_checking";
     private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
     private static final String LOCAL_BACKUP_PASSWORD = "local_backup_password";
@@ -111,9 +118,11 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
     private static final String BUGREPORT = "bugreport";
     private static final String BUGREPORT_IN_POWER_KEY = "bugreport_in_power";
     private static final String OPENGL_TRACES_PROPERTY = "debug.egl.trace";
+    private static final String TUNER_UI_KEY = "tuner_ui";
 
     private static final String DEBUG_APP_KEY = "debug_app";
     private static final String WAIT_FOR_DEBUGGER_KEY = "wait_for_debugger";
+    private static final String MOCK_LOCATION_APP_KEY = "mock_location_app";
     private static final String VERIFY_APPS_OVER_USB_KEY = "verify_apps_over_usb";
     private static final String DEBUG_VIEW_ATTRIBUTES =  "debug_view_attributes";
     private static final String STRICT_MODE_KEY = "strict_mode";
@@ -154,6 +163,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
     private static final String USB_CONFIGURATION_KEY = "select_usb_configuration";
     private static final String SELECT_USB_CONFIGURATION_PROPERTY = "sys.usb.config";
     private static final String WIFI_LEGACY_DHCP_CLIENT_KEY = "legacy_dhcp_client";
+    private static final String MOBILE_DATA_ALWAYS_ON = "mobile_data_always_on";
 
     private static final String OPENGL_TRACES_KEY = "enable_opengl_traces";
 
@@ -163,13 +173,12 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
 
     private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
 
-    private static final String PROCESS_STATS = "proc_stats";
-
     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
 
     private static final String TERMINAL_APP_PACKAGE = "com.android.terminal";
 
     private static final int RESULT_DEBUG_APP = 1000;
+    private static final int RESULT_MOCK_LOCATION_APP = 1001;
 
     private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
 
@@ -177,6 +186,8 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
 
     private static String DEFAULT_LOG_RING_BUFFER_SIZE_IN_BYTES = "262144"; // 256K
 
+    private static final int[] MOCK_LOCATOIN_APP_OPS = new int[] {AppOpsManager.OP_MOCK_LOCATION};
+
     private static final String MULTI_WINDOW_SYSTEM_PROPERTY = "persist.sys.debug.multi_window";
     private IWindowManager mWindowManager;
     private IBackupManager mBackupManager;
@@ -197,18 +208,22 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
     private SwitchPreference mKeepScreenOn;
     private SwitchPreference mBtHciSnoopLog;
     private SwitchPreference mEnableOemUnlock;
-    private SwitchPreference mAllowMockLocation;
     private SwitchPreference mDebugViewAttributes;
 
     private PreferenceScreen mPassword;
     private String mDebugApp;
     private Preference mDebugAppPref;
+
+    private String mMockLocationApp;
+    private Preference mMockLocationAppPref;
+
     private SwitchPreference mWaitForDebugger;
     private SwitchPreference mVerifyAppsOverUsb;
     private SwitchPreference mWifiDisplayCertification;
     private SwitchPreference mWifiVerboseLogging;
     private SwitchPreference mWifiAggressiveHandover;
     private SwitchPreference mLegacyDhcpClient;
+    private SwitchPreference mMobileDataAlwaysOn;
 
     private SwitchPreference mWifiAllowScansWithTraffic;
     private SwitchPreference mStrictMode;
@@ -245,7 +260,6 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
 
     private SwitchPreference mShowAllANRs;
 
-    private PreferenceScreen mProcessStats;
     private final ArrayList<Preference> mAllPrefs = new ArrayList<Preference>();
 
     private final ArrayList<SwitchPreference> mResetSwitchPrefs
@@ -260,6 +274,8 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
     private Dialog mAdbKeysDialog;
     private boolean mUnavailable;
 
+    private SwitchPreference mTunerUiPref;
+
     @Override
     protected int getMetricsCategory() {
         return MetricsLogger.DEVELOPMENT;
@@ -311,7 +327,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
             removePreference(mEnableOemUnlock);
             mEnableOemUnlock = null;
         }
-        mAllowMockLocation = findAndInitSwitchPref(ALLOW_MOCK_LOCATION);
+
         mDebugViewAttributes = findAndInitSwitchPref(DEBUG_VIEW_ATTRIBUTES);
         mPassword = (PreferenceScreen) findPreference(LOCAL_BACKUP_PASSWORD);
         mAllPrefs.add(mPassword);
@@ -327,6 +343,10 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
         mDebugAppPref = findPreference(DEBUG_APP_KEY);
         mAllPrefs.add(mDebugAppPref);
         mWaitForDebugger = findAndInitSwitchPref(WAIT_FOR_DEBUGGER_KEY);
+
+        mMockLocationAppPref = findPreference(MOCK_LOCATION_APP_KEY);
+        mAllPrefs.add(mMockLocationAppPref);
+
         mVerifyAppsOverUsb = findAndInitSwitchPref(VERIFY_APPS_OVER_USB_KEY);
         if (!showVerifierSetting()) {
             if (debugDebuggingCategory != null) {
@@ -355,6 +375,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
         mWifiAggressiveHandover = findAndInitSwitchPref(WIFI_AGGRESSIVE_HANDOVER_KEY);
         mWifiAllowScansWithTraffic = findAndInitSwitchPref(WIFI_ALLOW_SCAN_WITH_TRAFFIC_KEY);
         mLegacyDhcpClient = findAndInitSwitchPref(WIFI_LEGACY_DHCP_CLIENT_KEY);
+        mMobileDataAlwaysOn = findAndInitSwitchPref(MOBILE_DATA_ALWAYS_ON);
         mLogdSize = addListPreference(SELECT_LOGD_SIZE_KEY);
         mUsbConfiguration = addListPreference(USB_CONFIGURATION_KEY);
 
@@ -391,14 +412,13 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
         mAllPrefs.add(mShowAllANRs);
         mResetSwitchPrefs.add(mShowAllANRs);
 
+        mTunerUiPref = findAndInitSwitchPref(TUNER_UI_KEY);
+
         Preference hdcpChecking = findPreference(HDCP_CHECKING_KEY);
         if (hdcpChecking != null) {
             mAllPrefs.add(hdcpChecking);
             removePreferenceForProduction(hdcpChecking);
         }
-
-        mProcessStats = (PreferenceScreen) findPreference(PROCESS_STATS);
-        mAllPrefs.add(mProcessStats);
     }
 
     private ListPreference addListPreference(String prefKey) {
@@ -552,13 +572,12 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
         if (mEnableOemUnlock != null) {
             updateSwitchPreference(mEnableOemUnlock, Utils.isOemUnlockEnabled(getActivity()));
         }
-        updateSwitchPreference(mAllowMockLocation, Settings.Secure.getInt(cr,
-                Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0);
         updateSwitchPreference(mDebugViewAttributes, Settings.Global.getInt(cr,
                 Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0);
         updateHdcpValues();
         updatePasswordSummary();
         updateDebuggerOptions();
+        updateMockLocation();
         updateStrictModeVisualOptions();
         updatePointerLocationOptions();
         updateShowTouchesOptions();
@@ -591,9 +610,11 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
         updateWifiAggressiveHandoverOptions();
         updateWifiAllowScansWithTrafficOptions();
         updateLegacyDhcpClientOptions();
+        updateMobileDataAlwaysOnOptions();
         updateSimulateColorSpace();
         updateUseNuplayerOptions();
         updateUSBAudioOptions();
+        updateTweakUi();
     }
 
     private void resetDangerousOptions() {
@@ -669,6 +690,41 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
         }
     }
 
+    private void writeMockLocation() {
+        AppOpsManager appOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
+
+        // Disable the app op of the previous mock location app if such.
+        List<PackageOps> packageOps = appOpsManager.getPackagesForOps(MOCK_LOCATOIN_APP_OPS);
+        if (packageOps != null) {
+            // Should be one but in case we are in a bad state due to use of command line tools.
+            for (PackageOps packageOp : packageOps) {
+                if (packageOp.getOps().get(0).getMode() != AppOpsManager.MODE_ERRORED) {
+                    String oldMockLocationApp = packageOp.getPackageName();
+                    try {
+                        ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(
+                                oldMockLocationApp, PackageManager.GET_DISABLED_COMPONENTS);
+                        appOpsManager.setMode(AppOpsManager.OP_MOCK_LOCATION, ai.uid,
+                                oldMockLocationApp, AppOpsManager.MODE_ERRORED);
+                    } catch (NameNotFoundException e) {
+                        /* ignore */
+                    }
+                }
+            }
+        }
+
+        // Enable the app op of the new mock location app if such.
+        if (!TextUtils.isEmpty(mMockLocationApp)) {
+            try {
+                ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(
+                        mMockLocationApp, PackageManager.GET_DISABLED_COMPONENTS);
+                appOpsManager.setMode(AppOpsManager.OP_MOCK_LOCATION, ai.uid,
+                        mMockLocationApp, AppOpsManager.MODE_ALLOWED);
+            } catch (NameNotFoundException e) {
+                /* ignore */
+            }
+        }
+    }
+
     private static void resetDebuggerOptions() {
         try {
             ActivityManagerNative.getDefault().setDebugApp(
@@ -701,6 +757,39 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
         }
     }
 
+    private void updateMockLocation() {
+        AppOpsManager appOpsManager = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
+
+        List<PackageOps> packageOps = appOpsManager.getPackagesForOps(MOCK_LOCATOIN_APP_OPS);
+        if (packageOps != null) {
+            for (PackageOps packageOp : packageOps) {
+                if (packageOp.getOps().get(0).getMode() == AppOpsManager.MODE_ALLOWED) {
+                    mMockLocationApp = packageOps.get(0).getPackageName();
+                    break;
+                }
+            }
+        }
+
+        if (!TextUtils.isEmpty(mMockLocationApp)) {
+            String label = mMockLocationApp;
+            try {
+                ApplicationInfo ai = getActivity().getPackageManager().getApplicationInfo(
+                        mMockLocationApp, PackageManager.GET_DISABLED_COMPONENTS);
+                CharSequence appLabel = getPackageManager().getApplicationLabel(ai);
+                if (appLabel != null) {
+                    label = appLabel.toString();
+                }
+            } catch (PackageManager.NameNotFoundException e) {
+                /* ignore */
+            }
+
+            mMockLocationAppPref.setSummary(getString(R.string.mock_location_app_set, label));
+            mHaveDebugSettings = true;
+        } else {
+            mMockLocationAppPref.setSummary(getString(R.string.mock_location_app_not_set));
+        }
+    }
+
     private void updateVerifyAppsOverUsbOptions() {
         updateSwitchPreference(mVerifyAppsOverUsb, Settings.Global.getInt(getActivity().getContentResolver(),
                 Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0);
@@ -751,6 +840,9 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
     }
 
     private void updateBugreportOptions() {
+        final ComponentName bugreportStorageProviderComponentName =
+                new ComponentName("com.android.shell",
+                        "com.android.shell.BugreportStorageProvider");
         if ("user".equals(Build.TYPE)) {
             final ContentResolver resolver = getActivity().getContentResolver();
             final boolean adbEnabled = Settings.Global.getInt(
@@ -758,14 +850,23 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
             if (adbEnabled) {
                 mBugreport.setEnabled(true);
                 mBugreportInPower.setEnabled(true);
+                getPackageManager().setComponentEnabledSetting(
+                        bugreportStorageProviderComponentName,
+                        PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
             } else {
                 mBugreport.setEnabled(false);
                 mBugreportInPower.setEnabled(false);
                 mBugreportInPower.setChecked(false);
                 Settings.Secure.putInt(resolver, Settings.Secure.BUGREPORT_IN_POWER_MENU, 0);
+                getPackageManager().setComponentEnabledSetting(
+                        bugreportStorageProviderComponentName,
+                        PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0);
             }
         } else {
             mBugreportInPower.setEnabled(true);
+            getPackageManager().setComponentEnabledSetting(
+                    bugreportStorageProviderComponentName,
+                    PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
         }
     }
 
@@ -1058,6 +1159,21 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
         }
     }
 
+    private void updateTweakUi() {
+        updateSwitchPreference(mTunerUiPref, getActivity().getPackageManager()
+                .getComponentEnabledSetting(SYSUI_TUNER)
+                == PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
+        mTunerUiPref.setOnPreferenceChangeListener(this);
+    }
+
+    private void writeTweakUi(Object newValue) {
+        Boolean enabled = (Boolean) newValue;
+        getActivity().getPackageManager().setComponentEnabledSetting(SYSUI_TUNER,
+                enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                        : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+                        PackageManager.DONT_KILL_APP);
+    }
+
     private void updateUseNuplayerOptions() {
         updateSwitchPreference(
                 mUseAwesomePlayer, SystemProperties.getBoolean(USE_AWESOMEPLAYER_PROPERTY, false));
@@ -1145,6 +1261,18 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
                 mLegacyDhcpClient.isChecked() ? 1 : 0);
     }
 
+    private void updateMobileDataAlwaysOnOptions() {
+        updateSwitchPreference(mMobileDataAlwaysOn, Settings.Global.getInt(
+                getActivity().getContentResolver(),
+                Settings.Global.MOBILE_DATA_ALWAYS_ON, 0) != 0);
+    }
+
+    private void writeMobileDataAlwaysOnOptions() {
+        Settings.Global.putInt(getActivity().getContentResolver(),
+                Settings.Global.MOBILE_DATA_ALWAYS_ON,
+                mMobileDataAlwaysOn.isChecked() ? 1 : 0);
+    }
+
     private void updateLogdSizeValues() {
         if (mLogdSize != null) {
             String currentValue = SystemProperties.get(SELECT_LOGD_SIZE_PROPERTY);
@@ -1459,6 +1587,12 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
                 writeDebuggerOptions();
                 updateDebuggerOptions();
             }
+        } else if (requestCode == RESULT_MOCK_LOCATION_APP) {
+            if (resultCode == Activity.RESULT_OK) {
+                mMockLocationApp = data.getAction();
+                writeMockLocation();
+                updateMockLocation();
+            }
         } else if (requestCode == REQUEST_CODE_ENABLE_OEM_UNLOCK) {
             if (resultCode == Activity.RESULT_OK) {
                 if (mEnableOemUnlock.isChecked()) {
@@ -1527,16 +1661,19 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
                     Utils.setOemUnlockEnabled(getActivity(), false);
                 }
             }
-        } else if (preference == mAllowMockLocation) {
-            Settings.Secure.putInt(getActivity().getContentResolver(),
-                    Settings.Secure.ALLOW_MOCK_LOCATION,
-                    mAllowMockLocation.isChecked() ? 1 : 0);
+        } else if (preference == mMockLocationAppPref) {
+            Intent intent = new Intent(getActivity(), AppPicker.class);
+            intent.putExtra(AppPicker.EXTRA_REQUESTIING_PERMISSION,
+                    Manifest.permission.ACCESS_MOCK_LOCATION);
+            startActivityForResult(intent, RESULT_MOCK_LOCATION_APP);
         } else if (preference == mDebugViewAttributes) {
             Settings.Global.putInt(getActivity().getContentResolver(),
                     Settings.Global.DEBUG_VIEW_ATTRIBUTES,
                     mDebugViewAttributes.isChecked() ? 1 : 0);
         } else if (preference == mDebugAppPref) {
-            startActivityForResult(new Intent(getActivity(), AppPicker.class), RESULT_DEBUG_APP);
+            Intent intent = new Intent(getActivity(), AppPicker.class);
+            intent.putExtra(AppPicker.EXTRA_DEBUGGABLE, true);
+            startActivityForResult(intent, RESULT_DEBUG_APP);
         } else if (preference == mWaitForDebugger) {
             writeDebuggerOptions();
         } else if (preference == mVerifyAppsOverUsb) {
@@ -1585,6 +1722,8 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
             writeWifiAllowScansWithTrafficOptions();
         } else if (preference == mLegacyDhcpClient) {
             writeLegacyDhcpClientOptions();
+        } else if (preference == mMobileDataAlwaysOn) {
+            writeMobileDataAlwaysOnOptions();
         } else if (preference == mUseAwesomePlayer) {
             writeUseAwesomePlayerOptions();
         } else if (preference == mUSBAudio) {
@@ -1597,10 +1736,8 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
     }
 
     private boolean showKeyguardConfirmation(Resources resources, int requestCode) {
-        return new ChooseLockSettingsHelper(getActivity(), this)
-                .launchConfirmationActivity(requestCode,
-                        resources.getString(R.string.oem_unlock_enable_pin_prompt),
-                        resources.getString(R.string.oem_unlock_enable_pin_description));
+        return new ChooseLockSettingsHelper(getActivity(), this).launchConfirmationActivity(
+                requestCode, resources.getString(R.string.oem_unlock_enable));
     }
 
     @Override
@@ -1646,6 +1783,9 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
         } else if (preference == mSimulateColorSpace) {
             writeSimulateColorSpace(newValue);
             return true;
+        } else if (preference == mTunerUiPref) {
+            writeTweakUi(newValue);
+            return true;
         }
         return false;
     }