Enforce READ_EXTERNAL in Developer Options.
Move from Storage to Developer Options, and add interstitial dialog with more details. Bug: 6461446 Change-Id: I6d3d8fdc61a3e920ed58ab4d726949ac3c31feab
This commit is contained in:
@@ -18,8 +18,4 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/storage_usb"
|
android:id="@+id/storage_usb"
|
||||||
android:title="@string/storage_menu_usb" />
|
android:title="@string/storage_menu_usb" />
|
||||||
<item
|
|
||||||
android:id="@+id/storage_enforce_read_external"
|
|
||||||
android:title="@string/storage_menu_enforce_read_external"
|
|
||||||
android:checkable="true" />
|
|
||||||
</menu>
|
</menu>
|
||||||
|
@@ -1904,8 +1904,6 @@
|
|||||||
|
|
||||||
<!-- Storage setting. Menu option for USB transfer settings [CHAR LIMIT=30]-->
|
<!-- Storage setting. Menu option for USB transfer settings [CHAR LIMIT=30]-->
|
||||||
<string name="storage_menu_usb">USB computer connection</string>
|
<string name="storage_menu_usb">USB computer connection</string>
|
||||||
<!-- Storage setting. Menu option to enforce read external storage permission. [CHAR LIMIT=30]-->
|
|
||||||
<string name="storage_menu_enforce_read_external">Enforce read external</string>
|
|
||||||
|
|
||||||
<!-- Storage setting. Title for USB transfer settings [CHAR LIMIT=30]-->
|
<!-- Storage setting. Title for USB transfer settings [CHAR LIMIT=30]-->
|
||||||
<string name="storage_title_usb">USB computer connection</string>
|
<string name="storage_title_usb">USB computer connection</string>
|
||||||
@@ -2806,6 +2804,24 @@
|
|||||||
<!-- Warning text to user about the implications of enabling USB debugging -->
|
<!-- Warning text to user about the implications of enabling USB debugging -->
|
||||||
<string name="dev_settings_warning_message">These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave.</string>
|
<string name="dev_settings_warning_message">These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave.</string>
|
||||||
|
|
||||||
|
<!-- Title of checkbox setting that protects external storage. [CHAR LIMIT=32] -->
|
||||||
|
<string name="enforce_read_external_title" product="nosdcard">Protect USB storage</string>
|
||||||
|
<!-- Summary of checkbox setting that protects external storage. [CHAR LIMIT=64] -->
|
||||||
|
<string name="enforce_read_external_summary" product="nosdcard">Apps must request permission to read USB storage</string>
|
||||||
|
<!-- Title of dialog confirming that user wants to protect external storage. [CHAR LIMIT=32] -->
|
||||||
|
<string name="enforce_read_external_confirm_title" product="nosdcard">Protect USB storage?</string>
|
||||||
|
<!-- Message of dialog confirming that user wants to protect external storage. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="enforce_read_external_confirm_message" product="nosdcard">When USB storage is protected, apps must request permission to read data from external storage.\n\nSome apps may not work until updated by their developers.</string>
|
||||||
|
|
||||||
|
<!-- Title of checkbox setting that protects external storage. [CHAR LIMIT=32] -->
|
||||||
|
<string name="enforce_read_external_title" product="default">Protect SD card</string>
|
||||||
|
<!-- Summary of checkbox setting that protects external storage. [CHAR LIMIT=64] -->
|
||||||
|
<string name="enforce_read_external_summary" product="default">Apps must request permission to read SD card</string>
|
||||||
|
<!-- Title of dialog confirming that user wants to protect external storage. [CHAR LIMIT=32] -->
|
||||||
|
<string name="enforce_read_external_confirm_title" product="default">Protect SD card?</string>
|
||||||
|
<!-- Message of dialog confirming that user wants to protect external storage. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="enforce_read_external_confirm_message" product="default">When SD card is protected, apps must request permission to read data from external storage.\n\nSome apps may not work until updated by their developers.</string>
|
||||||
|
|
||||||
<!-- Title for the screen that lets the user choose a gadget to add to the home screen
|
<!-- Title for the screen that lets the user choose a gadget to add to the home screen
|
||||||
(or other screens that can host gadgets). Note to translators: we're still determining
|
(or other screens that can host gadgets). Note to translators: we're still determining
|
||||||
the final name for Gadgets/Widgets, so please translate both for now. -->
|
the final name for Gadgets/Widgets, so please translate both for now. -->
|
||||||
|
@@ -39,6 +39,11 @@
|
|||||||
android:entries="@array/hdcp_checking_titles"
|
android:entries="@array/hdcp_checking_titles"
|
||||||
android:entryValues="@array/hdcp_checking_values" />
|
android:entryValues="@array/hdcp_checking_values" />
|
||||||
|
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="enforce_read_external"
|
||||||
|
android:title="@string/enforce_read_external_title"
|
||||||
|
android:summary="@string/enforce_read_external_summary" />
|
||||||
|
|
||||||
<PreferenceCategory android:key="debug_debugging_category"
|
<PreferenceCategory android:key="debug_debugging_category"
|
||||||
android:title="@string/debug_debugging_category">
|
android:title="@string/debug_debugging_category">
|
||||||
|
|
||||||
|
@@ -16,17 +16,20 @@
|
|||||||
|
|
||||||
package com.android.settings;
|
package com.android.settings;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
|
||||||
|
|
||||||
import android.app.ActionBar;
|
import android.app.ActionBar;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ActivityManagerNative;
|
import android.app.ActivityManagerNative;
|
||||||
|
import android.app.ActivityThread;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
|
import android.app.DialogFragment;
|
||||||
import android.app.backup.IBackupManager;
|
import android.app.backup.IBackupManager;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
|
import android.content.DialogInterface.OnClickListener;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
@@ -45,12 +48,11 @@ import android.preference.CheckBoxPreference;
|
|||||||
import android.preference.ListPreference;
|
import android.preference.ListPreference;
|
||||||
import android.preference.MultiCheckPreference;
|
import android.preference.MultiCheckPreference;
|
||||||
import android.preference.Preference;
|
import android.preference.Preference;
|
||||||
|
import android.preference.Preference.OnPreferenceChangeListener;
|
||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceScreen;
|
import android.preference.PreferenceScreen;
|
||||||
import android.preference.Preference.OnPreferenceChangeListener;
|
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.HardwareRenderer;
|
import android.view.HardwareRenderer;
|
||||||
import android.view.IWindowManager;
|
import android.view.IWindowManager;
|
||||||
@@ -58,6 +60,8 @@ import android.view.View;
|
|||||||
import android.widget.CompoundButton;
|
import android.widget.CompoundButton;
|
||||||
import android.widget.Switch;
|
import android.widget.Switch;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Displays preferences for application developers.
|
* Displays preferences for application developers.
|
||||||
*/
|
*/
|
||||||
@@ -70,6 +74,7 @@ public class DevelopmentSettings extends PreferenceFragment
|
|||||||
private static final String ALLOW_MOCK_LOCATION = "allow_mock_location";
|
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_KEY = "hdcp_checking";
|
||||||
private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
|
private static final String HDCP_CHECKING_PROPERTY = "persist.sys.hdcp_checking";
|
||||||
|
private static final String ENFORCE_READ_EXTERNAL = "enforce_read_external";
|
||||||
private static final String LOCAL_BACKUP_PASSWORD = "local_backup_password";
|
private static final String LOCAL_BACKUP_PASSWORD = "local_backup_password";
|
||||||
private static final String HARDWARE_UI_PROPERTY = "persist.sys.ui.hw";
|
private static final String HARDWARE_UI_PROPERTY = "persist.sys.ui.hw";
|
||||||
|
|
||||||
@@ -97,6 +102,8 @@ public class DevelopmentSettings extends PreferenceFragment
|
|||||||
|
|
||||||
private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
|
private static final String SHOW_ALL_ANRS_KEY = "show_all_anrs";
|
||||||
|
|
||||||
|
private static final String TAG_CONFIRM_ENFORCE = "confirm_enforce";
|
||||||
|
|
||||||
private static final int RESULT_DEBUG_APP = 1000;
|
private static final int RESULT_DEBUG_APP = 1000;
|
||||||
|
|
||||||
private IWindowManager mWindowManager;
|
private IWindowManager mWindowManager;
|
||||||
@@ -109,6 +116,7 @@ public class DevelopmentSettings extends PreferenceFragment
|
|||||||
|
|
||||||
private CheckBoxPreference mEnableAdb;
|
private CheckBoxPreference mEnableAdb;
|
||||||
private CheckBoxPreference mKeepScreenOn;
|
private CheckBoxPreference mKeepScreenOn;
|
||||||
|
private CheckBoxPreference mEnforceReadExternal;
|
||||||
private CheckBoxPreference mAllowMockLocation;
|
private CheckBoxPreference mAllowMockLocation;
|
||||||
private PreferenceScreen mPassword;
|
private PreferenceScreen mPassword;
|
||||||
|
|
||||||
@@ -157,6 +165,7 @@ public class DevelopmentSettings extends PreferenceFragment
|
|||||||
|
|
||||||
mEnableAdb = findAndInitCheckboxPref(ENABLE_ADB);
|
mEnableAdb = findAndInitCheckboxPref(ENABLE_ADB);
|
||||||
mKeepScreenOn = findAndInitCheckboxPref(KEEP_SCREEN_ON);
|
mKeepScreenOn = findAndInitCheckboxPref(KEEP_SCREEN_ON);
|
||||||
|
mEnforceReadExternal = findAndInitCheckboxPref(ENFORCE_READ_EXTERNAL);
|
||||||
mAllowMockLocation = findAndInitCheckboxPref(ALLOW_MOCK_LOCATION);
|
mAllowMockLocation = findAndInitCheckboxPref(ALLOW_MOCK_LOCATION);
|
||||||
mPassword = (PreferenceScreen) findPreference(LOCAL_BACKUP_PASSWORD);
|
mPassword = (PreferenceScreen) findPreference(LOCAL_BACKUP_PASSWORD);
|
||||||
mAllPrefs.add(mPassword);
|
mAllPrefs.add(mPassword);
|
||||||
@@ -302,12 +311,14 @@ public class DevelopmentSettings extends PreferenceFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateAllOptions() {
|
private void updateAllOptions() {
|
||||||
final ContentResolver cr = getActivity().getContentResolver();
|
final Context context = getActivity();
|
||||||
|
final ContentResolver cr = context.getContentResolver();
|
||||||
mHaveDebugSettings = false;
|
mHaveDebugSettings = false;
|
||||||
updateCheckBox(mEnableAdb, Settings.Secure.getInt(cr,
|
updateCheckBox(mEnableAdb, Settings.Secure.getInt(cr,
|
||||||
Settings.Secure.ADB_ENABLED, 0) != 0);
|
Settings.Secure.ADB_ENABLED, 0) != 0);
|
||||||
updateCheckBox(mKeepScreenOn, Settings.System.getInt(cr,
|
updateCheckBox(mKeepScreenOn, Settings.System.getInt(cr,
|
||||||
Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
|
Settings.System.STAY_ON_WHILE_PLUGGED_IN, 0) != 0);
|
||||||
|
updateCheckBox(mEnforceReadExternal, isPermissionEnforced(context, READ_EXTERNAL_STORAGE));
|
||||||
updateCheckBox(mAllowMockLocation, Settings.Secure.getInt(cr,
|
updateCheckBox(mAllowMockLocation, Settings.Secure.getInt(cr,
|
||||||
Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0);
|
Settings.Secure.ALLOW_MOCK_LOCATION, 0) != 0);
|
||||||
updateHdcpValues();
|
updateHdcpValues();
|
||||||
@@ -786,6 +797,12 @@ public class DevelopmentSettings extends PreferenceFragment
|
|||||||
Settings.System.STAY_ON_WHILE_PLUGGED_IN,
|
Settings.System.STAY_ON_WHILE_PLUGGED_IN,
|
||||||
mKeepScreenOn.isChecked() ?
|
mKeepScreenOn.isChecked() ?
|
||||||
(BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB) : 0);
|
(BatteryManager.BATTERY_PLUGGED_AC | BatteryManager.BATTERY_PLUGGED_USB) : 0);
|
||||||
|
} else if (preference == mEnforceReadExternal) {
|
||||||
|
if (mEnforceReadExternal.isChecked()) {
|
||||||
|
ConfirmEnforceFragment.show(this);
|
||||||
|
} else {
|
||||||
|
setPermissionEnforced(getActivity(), READ_EXTERNAL_STORAGE, false);
|
||||||
|
}
|
||||||
} else if (preference == mAllowMockLocation) {
|
} else if (preference == mAllowMockLocation) {
|
||||||
Settings.Secure.putInt(getActivity().getContentResolver(),
|
Settings.Secure.putInt(getActivity().getContentResolver(),
|
||||||
Settings.Secure.ALLOW_MOCK_LOCATION,
|
Settings.Secure.ALLOW_MOCK_LOCATION,
|
||||||
@@ -934,4 +951,59 @@ public class DevelopmentSettings extends PreferenceFragment
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dialog to confirm enforcement of {@link #READ_EXTERNAL_STORAGE}.
|
||||||
|
*/
|
||||||
|
public static class ConfirmEnforceFragment extends DialogFragment {
|
||||||
|
public static void show(DevelopmentSettings parent) {
|
||||||
|
final ConfirmEnforceFragment dialog = new ConfirmEnforceFragment();
|
||||||
|
dialog.setTargetFragment(parent, 0);
|
||||||
|
dialog.show(parent.getFragmentManager(), TAG_CONFIRM_ENFORCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
|
final Context context = getActivity();
|
||||||
|
|
||||||
|
final AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
builder.setTitle(R.string.enforce_read_external_confirm_title);
|
||||||
|
builder.setMessage(R.string.enforce_read_external_confirm_message);
|
||||||
|
|
||||||
|
builder.setPositiveButton(android.R.string.ok, new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
setPermissionEnforced(context, READ_EXTERNAL_STORAGE, true);
|
||||||
|
((DevelopmentSettings) getTargetFragment()).updateAllOptions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.setNegativeButton(android.R.string.cancel, new OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
((DevelopmentSettings) getTargetFragment()).updateAllOptions();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isPermissionEnforced(Context context, String permission) {
|
||||||
|
try {
|
||||||
|
return ActivityThread.getPackageManager().isPermissionEnforced(READ_EXTERNAL_STORAGE);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw new RuntimeException("Problem talking with PackageManager", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setPermissionEnforced(
|
||||||
|
Context context, String permission, boolean enforced) {
|
||||||
|
try {
|
||||||
|
// TODO: offload to background thread
|
||||||
|
ActivityThread.getPackageManager()
|
||||||
|
.setPermissionEnforced(READ_EXTERNAL_STORAGE, enforced);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw new RuntimeException("Problem talking with PackageManager", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package com.android.settings.deviceinfo;
|
package com.android.settings.deviceinfo;
|
||||||
|
|
||||||
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
|
|
||||||
|
|
||||||
import android.app.ActivityThread;
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
@@ -26,7 +23,6 @@ import android.content.Context;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.pm.IPackageManager;
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.os.Environment;
|
||||||
@@ -68,7 +64,6 @@ public class Memory extends SettingsPreferenceFragment {
|
|||||||
private IMountService mMountService = null;
|
private IMountService mMountService = null;
|
||||||
|
|
||||||
private StorageManager mStorageManager = null;
|
private StorageManager mStorageManager = null;
|
||||||
private IPackageManager mPackageService;
|
|
||||||
|
|
||||||
private StorageVolumePreferenceCategory mInternalStorageVolumePreferenceCategory;
|
private StorageVolumePreferenceCategory mInternalStorageVolumePreferenceCategory;
|
||||||
private StorageVolumePreferenceCategory[] mStorageVolumePreferenceCategories;
|
private StorageVolumePreferenceCategory[] mStorageVolumePreferenceCategories;
|
||||||
@@ -82,8 +77,6 @@ public class Memory extends SettingsPreferenceFragment {
|
|||||||
mStorageManager.registerListener(mStorageListener);
|
mStorageManager.registerListener(mStorageListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
mPackageService = ActivityThread.getPackageManager();
|
|
||||||
|
|
||||||
addPreferencesFromResource(R.xml.device_info_memory);
|
addPreferencesFromResource(R.xml.device_info_memory);
|
||||||
|
|
||||||
mResources = getResources();
|
mResources = getResources();
|
||||||
@@ -178,16 +171,6 @@ public class Memory extends SettingsPreferenceFragment {
|
|||||||
public void onPrepareOptionsMenu(Menu menu) {
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
final MenuItem usb = menu.findItem(R.id.storage_usb);
|
final MenuItem usb = menu.findItem(R.id.storage_usb);
|
||||||
usb.setVisible(!isMassStorageEnabled());
|
usb.setVisible(!isMassStorageEnabled());
|
||||||
|
|
||||||
final boolean enforced;
|
|
||||||
try {
|
|
||||||
enforced = mPackageService.isPermissionEnforced(READ_EXTERNAL_STORAGE);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw new RuntimeException("Problem talking with PackageManager", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
final MenuItem enforceReadExternal = menu.findItem(R.id.storage_enforce_read_external);
|
|
||||||
enforceReadExternal.setChecked(enforced);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -204,18 +187,6 @@ public class Memory extends SettingsPreferenceFragment {
|
|||||||
startFragment(this, UsbSettings.class.getCanonicalName(), -1, null);
|
startFragment(this, UsbSettings.class.getCanonicalName(), -1, null);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case R.id.storage_enforce_read_external: {
|
|
||||||
final boolean checked = !item.isChecked();
|
|
||||||
item.setChecked(checked);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// TODO: offload to background thread
|
|
||||||
mPackageService.setPermissionEnforced(READ_EXTERNAL_STORAGE, checked);
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
throw new RuntimeException("Problem talking with PackageManager", e);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user