New UI for controlling USB

Create a new UI for managing USB access control. This UI is implemented
as a transparent popup triggered by a persistent notification.

Delete the old UI for controlling this. It is no longer used.

Bug: 18905620
Change-Id: I54186961414447a9d37f68e946e1c167506170ae
This commit is contained in:
Nick Kralevich
2015-05-13 11:54:20 -07:00
parent 07851208fc
commit 7000d54338
13 changed files with 142 additions and 252 deletions

View File

@@ -1786,6 +1786,13 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".deviceinfo.UsbModeChooserActivity"
android:excludeFromRecents="true"
android:exported="true"
android:permission="android.permission.MANAGE_USB"
android:theme="@style/Transparent">
</activity>
<activity android:name=".bluetooth.RequestPermissionHelperActivity" <activity android:name=".bluetooth.RequestPermissionHelperActivity"
android:label="@string/bluetooth_pairing_request" android:label="@string/bluetooth_pairing_request"
android:excludeFromRecents="true" android:excludeFromRecents="true"

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2012 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/storage_usb"
android:title="@string/storage_menu_usb" />
</menu>

View File

@@ -30,7 +30,4 @@
<item <item
android:id="@+id/storage_migrate" android:id="@+id/storage_migrate"
android:title="@string/storage_menu_migrate" /> android:title="@string/storage_menu_migrate" />
<item
android:id="@+id/storage_usb"
android:title="@string/storage_menu_usb" />
</menu> </menu>

View File

@@ -1365,4 +1365,12 @@
<item>0</item> <item>0</item>
</string-array> </string-array>
<!-- These values must match up with the code in UsbModeChooserActivity.java. -->
<string-array name="usb_available_functions">
<item>@string/usb_use_charging_only</item>
<item>@string/usb_use_file_transfers</item>
<item>@string/usb_use_photo_transfers</item>
<item>@string/usb_use_MIDI</item>
</string-array>
</resources> </resources>

View File

@@ -2293,8 +2293,6 @@
<string name="storage_menu_migrate">Migrate data</string> <string name="storage_menu_migrate">Migrate data</string>
<!-- Storage setting. Menu option for forgetting a storage device [CHAR LIMIT=30]--> <!-- Storage setting. Menu option for forgetting a storage device [CHAR LIMIT=30]-->
<string name="storage_menu_forget">Forget</string> <string name="storage_menu_forget">Forget</string>
<!-- Storage setting. Menu option for USB transfer settings [CHAR LIMIT=30]-->
<string name="storage_menu_usb">USB computer connection</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>
@@ -6601,4 +6599,25 @@
<!-- Description of how many more permissions to view on next page [CHAR LIMIT=30] --> <!-- Description of how many more permissions to view on next page [CHAR LIMIT=30] -->
<string name="additional_permissions_more"><xliff:g id="count" example="2">%1$d</xliff:g> more</string> <string name="additional_permissions_more"><xliff:g id="count" example="2">%1$d</xliff:g> more</string>
<!-- One of the choices in a dialog (with title defined in usb_use) that lets the user
select what the USB connection for this device should be used for. This choice
is for charging only. -->
<string name="usb_use_charging_only">Charging only</string>
<!-- One of the choices in a dialog (with title defined in usb_use) that lets the user
select what the USB connection for this device should be used for. This choice
is for transferring files via MTP. -->
<string name="usb_use_file_transfers">Transfer files (MTP)</string>
<!-- One of the choices in a dialog (with title defined in usb_use) that lets the user
select what the USB connection for this device should be used for. This choice
is for transferring photos via PTP. -->
<string name="usb_use_photo_transfers">Transfer photos (PTP)</string>
<!-- One of the choices in a dialog (with title defined in usb_use) that lets the user
select what the USB connection for this device should be used for. This choice
is for entering MIDI mode. -->
<string name="usb_use_MIDI">MIDI</string>
<!-- The title used in a dialog which lets the user select what the USB connection
for this device should be used for. Choices are usb_use_charging_only,
usb_use_file_transfer, use_use_photo_transfer, and usb_use_MIDI -->
<string name="usb_use">Use USB for</string>
</resources> </resources>

View File

@@ -1274,7 +1274,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
private void writeUsbConfigurationOption(Object newValue) { private void writeUsbConfigurationOption(Object newValue) {
UsbManager manager = (UsbManager)getActivity().getSystemService(Context.USB_SERVICE); UsbManager manager = (UsbManager)getActivity().getSystemService(Context.USB_SERVICE);
manager.setCurrentFunction(newValue.toString(), false); manager.setCurrentFunction(newValue.toString());
} }
private void updateCpuUsageOptions() { private void updateCpuUsageOptions() {

View File

@@ -87,7 +87,6 @@ import com.android.settings.deviceinfo.PrivateVolumeForget;
import com.android.settings.deviceinfo.PrivateVolumeSettings; import com.android.settings.deviceinfo.PrivateVolumeSettings;
import com.android.settings.deviceinfo.PublicVolumeSettings; import com.android.settings.deviceinfo.PublicVolumeSettings;
import com.android.settings.deviceinfo.StorageSettings; import com.android.settings.deviceinfo.StorageSettings;
import com.android.settings.deviceinfo.UsbSettings;
import com.android.settings.fuelgauge.BatterySaverSettings; import com.android.settings.fuelgauge.BatterySaverSettings;
import com.android.settings.fuelgauge.PowerUsageDetail; import com.android.settings.fuelgauge.PowerUsageDetail;
import com.android.settings.fuelgauge.PowerUsageSummary; import com.android.settings.fuelgauge.PowerUsageSummary;
@@ -318,7 +317,6 @@ public class SettingsActivity extends Activity
PrivateVolumeSettings.class.getName(), PrivateVolumeSettings.class.getName(),
PublicVolumeSettings.class.getName(), PublicVolumeSettings.class.getName(),
DevelopmentSettings.class.getName(), DevelopmentSettings.class.getName(),
UsbSettings.class.getName(),
AndroidBeam.class.getName(), AndroidBeam.class.getName(),
WifiDisplaySettings.class.getName(), WifiDisplaySettings.class.getName(),
PowerUsageSummary.class.getName(), PowerUsageSummary.class.getName(),

View File

@@ -273,7 +273,6 @@ public class PrivateVolumeSettings extends SettingsPreferenceFragment {
final MenuItem unmount = menu.findItem(R.id.storage_unmount); final MenuItem unmount = menu.findItem(R.id.storage_unmount);
final MenuItem format = menu.findItem(R.id.storage_format); final MenuItem format = menu.findItem(R.id.storage_format);
final MenuItem migrate = menu.findItem(R.id.storage_migrate); final MenuItem migrate = menu.findItem(R.id.storage_migrate);
final MenuItem usb = menu.findItem(R.id.storage_usb);
// Actions live in menu for non-internal private volumes; they're shown // Actions live in menu for non-internal private volumes; they're shown
// as preference items for public volumes. // as preference items for public volumes.
@@ -293,9 +292,6 @@ public class PrivateVolumeSettings extends SettingsPreferenceFragment {
final VolumeInfo privateVol = getActivity().getPackageManager() final VolumeInfo privateVol = getActivity().getPackageManager()
.getPrimaryStorageCurrentVolume(); .getPrimaryStorageCurrentVolume();
migrate.setVisible(!Objects.equals(mVolume, privateVol)); migrate.setVisible(!Objects.equals(mVolume, privateVol));
// TODO: show usb if we jumped past first screen
usb.setVisible(false);
} }
@Override @Override
@@ -324,10 +320,6 @@ public class PrivateVolumeSettings extends SettingsPreferenceFragment {
intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, mVolume.getId()); intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, mVolume.getId());
startActivity(intent); startActivity(intent);
return true; return true;
case R.id.storage_usb:
startFragment(this, UsbSettings.class.getCanonicalName(),
R.string.storage_title_usb, 0, null);
return true;
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }

View File

@@ -148,29 +148,6 @@ public class StorageSettings extends SettingsPreferenceFragment implements Index
mStorageManager.unregisterListener(mStorageListener); mStorageManager.unregisterListener(mStorageListener);
} }
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.storage, menu);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
final MenuItem usb = menu.findItem(R.id.storage_usb);
usb.setVisible(!mUserManager.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER));
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.storage_usb:
startFragment(this, UsbSettings.class.getCanonicalName(),
R.string.storage_title_usb, 0, null);
return true;
}
return super.onOptionsItemSelected(item);
}
@Override @Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference pref) { public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference pref) {
final String volId = pref.getKey(); final String volId = pref.getKey();

View File

@@ -0,0 +1,105 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.deviceinfo;
import android.annotation.Nullable;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.util.Log;
import com.android.settings.R;
/**
* UI for the USB chooser dialog.
*
* TODO: Don't show some UI elements if UserManager.DISALLOW_USB_FILE_TRANSFER is disabled.
*/
public class UsbModeChooserActivity extends Activity {
private UsbManager mUsbManager;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
final AlertDialog levelDialog;
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.usb_use);
builder.setSingleChoiceItems(R.array.usb_available_functions, getCurrentFunction(),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setCurrentFunction(which);
dialog.dismiss();
UsbModeChooserActivity.this.finish();
}
});
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
UsbModeChooserActivity.this.finish();
}
});
builder.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
UsbModeChooserActivity.this.finish();
}
});
levelDialog = builder.create();
levelDialog.show();
}
/*
* If you change the numbers here, you also need to change R.array.usb_available_functions
* so that everything matches.
*/
private int getCurrentFunction() {
if (mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_MTP)) {
return 1;
} else if (mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_PTP)) {
return 2;
} else if (mUsbManager.isFunctionEnabled(UsbManager.USB_FUNCTION_MIDI)) {
return 3;
}
return 0;
}
/*
* If you change the numbers here, you also need to change R.array.usb_available_functions
* so that everything matches.
*/
private void setCurrentFunction(int which) {
switch (which) {
case 0:
mUsbManager.setCurrentFunction("none");
break;
case 1:
mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MTP);
break;
case 2:
mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_PTP);
break;
case 3:
mUsbManager.setCurrentFunction(UsbManager.USB_FUNCTION_MIDI);
break;
}
}
}

View File

@@ -1,182 +0,0 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.deviceinfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.UserManager;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceScreen;
import android.util.Log;
import com.android.internal.logging.MetricsLogger;
import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.Utils;
/**
* USB storage settings.
*/
public class UsbSettings extends SettingsPreferenceFragment {
private static final String TAG = "UsbSettings";
private static final String KEY_MTP = "usb_mtp";
private static final String KEY_PTP = "usb_ptp";
private static final String KEY_MIDI = "usb_midi";
private UsbManager mUsbManager;
private CheckBoxPreference mMtp;
private CheckBoxPreference mPtp;
private CheckBoxPreference mMidi;
private boolean mUsbAccessoryMode;
private final BroadcastReceiver mStateReceiver = new BroadcastReceiver() {
public void onReceive(Context content, Intent intent) {
String action = intent.getAction();
if (action.equals(UsbManager.ACTION_USB_STATE)) {
mUsbAccessoryMode = intent.getBooleanExtra(UsbManager.USB_FUNCTION_ACCESSORY, false);
Log.e(TAG, "UsbAccessoryMode " + mUsbAccessoryMode);
}
updateToggles(mUsbManager.getDefaultFunction());
}
};
private PreferenceScreen createPreferenceHierarchy() {
PreferenceScreen root = getPreferenceScreen();
if (root != null) {
root.removeAll();
}
addPreferencesFromResource(R.xml.usb_settings);
root = getPreferenceScreen();
mMtp = (CheckBoxPreference)root.findPreference(KEY_MTP);
mPtp = (CheckBoxPreference)root.findPreference(KEY_PTP);
mMidi = (CheckBoxPreference)root.findPreference(KEY_MIDI);
UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
if (um.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
mMtp.setEnabled(false);
mPtp.setEnabled(false);
}
return root;
}
@Override
protected int getMetricsCategory() {
return MetricsLogger.DEVICEINFO_USB;
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
}
@Override
public void onPause() {
super.onPause();
getActivity().unregisterReceiver(mStateReceiver);
}
@Override
public void onResume() {
super.onResume();
// Make sure we reload the preference hierarchy since some of these settings
// depend on others...
createPreferenceHierarchy();
// ACTION_USB_STATE is sticky so this will call updateToggles
getActivity().registerReceiver(mStateReceiver,
new IntentFilter(UsbManager.ACTION_USB_STATE));
}
private void updateToggles(String function) {
if (UsbManager.USB_FUNCTION_MTP.equals(function)) {
mMtp.setChecked(true);
mPtp.setChecked(false);
mMidi.setChecked(false);
} else if (UsbManager.USB_FUNCTION_PTP.equals(function)) {
mMtp.setChecked(false);
mPtp.setChecked(true);
mMidi.setChecked(false);
} else if (UsbManager.USB_FUNCTION_MIDI.equals(function)) {
mMtp.setChecked(false);
mPtp.setChecked(false);
mMidi.setChecked(true);
} else {
mMtp.setChecked(false);
mPtp.setChecked(false);
mMidi.setChecked(false);
}
UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
if (um.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
Log.e(TAG, "USB is locked down");
mMtp.setEnabled(false);
mPtp.setEnabled(false);
mMidi.setEnabled(true);
} else if (!mUsbAccessoryMode) {
//Enable MTP and PTP switch while USB is not in Accessory Mode, otherwise disable it
Log.e(TAG, "USB Normal Mode");
mMtp.setEnabled(true);
mPtp.setEnabled(true);
mMidi.setEnabled(true);
} else {
Log.e(TAG, "USB Accessory Mode");
mMtp.setEnabled(false);
mPtp.setEnabled(false);
mMidi.setEnabled(false);
}
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
// Don't allow any changes to take effect as the USB host will be disconnected, killing
// the monkeys
if (Utils.isMonkeyRunning()) {
return true;
}
// If this user is disallowed from using USB, don't handle their attempts to change the
// setting.
UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
if (um.hasUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER)) {
return true;
}
String function = "none";
if (preference == mMtp && mMtp.isChecked()) {
function = UsbManager.USB_FUNCTION_MTP;
} else if (preference == mPtp && mPtp.isChecked()) {
function = UsbManager.USB_FUNCTION_PTP;
} else if (preference == mMidi && mMidi.isChecked()) {
function = UsbManager.USB_FUNCTION_MIDI;
}
mUsbManager.setCurrentFunction(function, true);
updateToggles(function);
return true;
}
}

View File

@@ -34,7 +34,6 @@ import com.android.settings.applications.AdvancedAppSettings;
import com.android.settings.applications.ManageDefaultApps; import com.android.settings.applications.ManageDefaultApps;
import com.android.settings.bluetooth.BluetoothSettings; import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.deviceinfo.StorageSettings; import com.android.settings.deviceinfo.StorageSettings;
import com.android.settings.deviceinfo.UsbSettings;
import com.android.settings.fuelgauge.BatterySaverSettings; import com.android.settings.fuelgauge.BatterySaverSettings;
import com.android.settings.fuelgauge.PowerUsageSummary; import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.inputmethod.InputMethodAndLanguageSettings; import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
@@ -131,7 +130,6 @@ public final class Ranking {
// Storage // Storage
sRankMap.put(StorageSettings.class.getName(), RANK_STORAGE); sRankMap.put(StorageSettings.class.getName(), RANK_STORAGE);
sRankMap.put(UsbSettings.class.getName(), RANK_STORAGE);
// Battery // Battery
sRankMap.put(PowerUsageSummary.class.getName(), RANK_POWER_USAGE); sRankMap.put(PowerUsageSummary.class.getName(), RANK_POWER_USAGE);

View File

@@ -36,7 +36,6 @@ import com.android.settings.applications.AdvancedAppSettings;
import com.android.settings.applications.ManageDefaultApps; import com.android.settings.applications.ManageDefaultApps;
import com.android.settings.bluetooth.BluetoothSettings; import com.android.settings.bluetooth.BluetoothSettings;
import com.android.settings.deviceinfo.StorageSettings; import com.android.settings.deviceinfo.StorageSettings;
import com.android.settings.deviceinfo.UsbSettings;
import com.android.settings.fuelgauge.BatterySaverSettings; import com.android.settings.fuelgauge.BatterySaverSettings;
import com.android.settings.fuelgauge.PowerUsageSummary; import com.android.settings.fuelgauge.PowerUsageSummary;
import com.android.settings.inputmethod.InputMethodAndLanguageSettings; import com.android.settings.inputmethod.InputMethodAndLanguageSettings;
@@ -178,13 +177,6 @@ public final class SearchIndexableResources {
StorageSettings.class.getName(), StorageSettings.class.getName(),
R.drawable.ic_settings_storage)); R.drawable.ic_settings_storage));
sResMap.put(UsbSettings.class.getName(),
new SearchIndexableResource(
Ranking.getRankForClassName(UsbSettings.class.getName()),
R.xml.usb_settings,
UsbSettings.class.getName(),
R.drawable.ic_settings_storage));
sResMap.put(PowerUsageSummary.class.getName(), sResMap.put(PowerUsageSummary.class.getName(),
new SearchIndexableResource( new SearchIndexableResource(
Ranking.getRankForClassName(PowerUsageSummary.class.getName()), Ranking.getRankForClassName(PowerUsageSummary.class.getName()),