From eb51bde8c91ff25e79c35acfdbc1152953656850 Mon Sep 17 00:00:00 2001 From: Doris Ling Date: Thu, 3 Nov 2016 16:54:44 -0700 Subject: [PATCH] Add Usb preference to connected devices dashboard. Add Usb preference and the corresponding controller. Change-Id: I79e3f20b5c024ece0515f9a6cba1185ba8b8c7be Fixes: 31800290 Test: make RunSettingsRoboTests --- res/values/strings.xml | 5 + res/xml/connected_devices.xml | 29 +-- .../ConnectedDeviceDashboardFragment.java | 7 +- .../UsbModePreferenceController.java | 169 ++++++++++++++++++ .../deviceinfo/UsbModeChooserActivity.java | 36 +--- .../UsbModePreferenceControllerTest.java | 137 ++++++++++++++ 6 files changed, 339 insertions(+), 44 deletions(-) create mode 100644 src/com/android/settings/connecteddevice/UsbModePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/connecteddevice/UsbModePreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 010706f27cd..699a0c34c97 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -7057,6 +7057,11 @@ usb_use_file_transfer, use_use_photo_transfer, and usb_use_MIDI --> Use USB to + + USB + + Nothing connected + Background check diff --git a/res/xml/connected_devices.xml b/res/xml/connected_devices.xml index 42895502def..e758702dc91 100644 --- a/res/xml/connected_devices.xml +++ b/res/xml/connected_devices.xml @@ -16,16 +16,25 @@ - + - + + + + + \ No newline at end of file diff --git a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java index b913669ec8d..57133b1b89c 100644 --- a/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java +++ b/src/com/android/settings/connecteddevice/ConnectedDeviceDashboardFragment.java @@ -20,6 +20,7 @@ import android.content.Context; import com.android.settings.R; import com.android.settings.core.PreferenceController; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.deviceinfo.UsbBackend; import com.android.settings.nfc.NfcPreferenceController; import com.android.settingslib.drawer.CategoryKey; @@ -29,6 +30,7 @@ import java.util.List; public class ConnectedDeviceDashboardFragment extends DashboardFragment { private static final String TAG = "ConnectedDeviceFrag"; + private UsbModePreferenceController mUsbPrefController; @Override public int getMetricsCategory() { @@ -52,11 +54,14 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment { @Override protected List getPreferenceControllers(Context context) { + final List controllers = new ArrayList<>(); final NfcPreferenceController nfcPreferenceController = new NfcPreferenceController(context); getLifecycle().addObserver(nfcPreferenceController); - final List controllers = new ArrayList<>(); controllers.add(nfcPreferenceController); + mUsbPrefController = new UsbModePreferenceController(context, new UsbBackend(context)); + getLifecycle().addObserver(mUsbPrefController); + controllers.add(mUsbPrefController); return controllers; } diff --git a/src/com/android/settings/connecteddevice/UsbModePreferenceController.java b/src/com/android/settings/connecteddevice/UsbModePreferenceController.java new file mode 100644 index 00000000000..f782e9e60f7 --- /dev/null +++ b/src/com/android/settings/connecteddevice/UsbModePreferenceController.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2016 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.connecteddevice; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.hardware.usb.UsbManager; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.core.PreferenceController; +import com.android.settings.R; +import com.android.settings.core.lifecycle.LifecycleObserver; +import com.android.settings.core.lifecycle.events.OnPause; +import com.android.settings.core.lifecycle.events.OnResume; +import com.android.settings.deviceinfo.UsbBackend; + +public class UsbModePreferenceController extends PreferenceController + implements LifecycleObserver, OnResume, OnPause { + + private static final String KEY_USB_MODE = "usb_mode"; + + private UsbBackend mUsbBackend; + private UsbConnectionBroadcastReceiver mUsbReceiver; + private Preference mUsbPreference; + + public UsbModePreferenceController(Context context, UsbBackend usbBackend) { + super(context); + mUsbBackend = usbBackend; + mUsbReceiver = new UsbConnectionBroadcastReceiver(); + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mUsbPreference = screen.findPreference(KEY_USB_MODE); + updataSummary(mUsbPreference); + } + + @Override + public void updateState(Preference preference) { + updataSummary(preference); + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + return false; + } + + @Override + public boolean isAvailable() { + return true; + } + + @Override + public String getPreferenceKey() { + return KEY_USB_MODE; + } + + @Override + public void onPause() { + mUsbReceiver.unregister(); + } + + @Override + public void onResume() { + mUsbReceiver.register(); + } + + public static int getSummary(int mode) { + switch (mode) { + case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE: + return R.string.usb_use_charging_only_desc; + case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_NONE: + return R.string.usb_use_power_only_desc; + case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MTP: + return R.string.usb_use_file_transfers_desc; + case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_PTP: + return R.string.usb_use_photo_transfers_desc; + case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MIDI: + return R.string.usb_use_MIDI_desc; + } + return 0; + } + + public static int getTitle(int mode) { + switch (mode) { + case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE: + return R.string.usb_use_charging_only; + case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_NONE: + return R.string.usb_use_power_only; + case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MTP: + return R.string.usb_use_file_transfers; + case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_PTP: + return R.string.usb_use_photo_transfers; + case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MIDI: + return R.string.usb_use_MIDI; + } + return 0; + } + + private void updataSummary(Preference preference) { + updataSummary(preference, mUsbBackend.getCurrentMode()); + } + + private void updataSummary(Preference preference, int mode) { + if (preference != null) { + if (mUsbReceiver.isConnected()) { + preference.setEnabled(true); + preference.setSummary(getTitle(mode)); + } else { + preference.setSummary(R.string.usb_nothing_connected); + preference.setEnabled(false); + } + } + } + + private class UsbConnectionBroadcastReceiver extends BroadcastReceiver { + private boolean mListeningToUsbEvents; + private boolean mConnected; + + @Override + public void onReceive(Context context, Intent intent) { + boolean connected = intent != null + && intent.getExtras().getBoolean(UsbManager.USB_CONNECTED); + if (connected != mConnected) { + mConnected = connected; + updataSummary(mUsbPreference); + } + } + + public void register() { + if (!mListeningToUsbEvents) { + IntentFilter intentFilter = new IntentFilter(UsbManager.ACTION_USB_STATE); + Intent intent = mContext.registerReceiver(this, intentFilter); + mConnected = intent != null + && intent.getExtras().getBoolean(UsbManager.USB_CONNECTED); + mListeningToUsbEvents = true; + } + } + + public void unregister() { + if (mListeningToUsbEvents) { + mContext.unregisterReceiver(this); + mListeningToUsbEvents = false; + } + } + + public boolean isConnected() { + return mConnected; + } + } + +} diff --git a/src/com/android/settings/deviceinfo/UsbModeChooserActivity.java b/src/com/android/settings/deviceinfo/UsbModeChooserActivity.java index d592fcc5058..5ac16d40f76 100644 --- a/src/com/android/settings/deviceinfo/UsbModeChooserActivity.java +++ b/src/com/android/settings/deviceinfo/UsbModeChooserActivity.java @@ -40,6 +40,7 @@ import android.widget.TextView; import com.android.settings.R; import com.android.settingslib.RestrictedLockUtils; +import com.android.settings.connecteddevice.UsbModePreferenceController; import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; @@ -135,9 +136,9 @@ public class UsbModeChooserActivity extends Activity { View v = mLayoutInflater.inflate(R.layout.restricted_radio_with_summary, container, false); TextView titleView = (TextView) v.findViewById(android.R.id.title); - titleView.setText(getTitle(mode)); + titleView.setText(UsbModePreferenceController.getTitle(mode)); TextView summaryView = (TextView) v.findViewById(android.R.id.summary); - summaryView.setText(getSummary(mode)); + summaryView.setText(UsbModePreferenceController.getSummary(mode)); if (disallowedByAdmin) { if (mEnforcedAdmin != null) { @@ -177,35 +178,4 @@ public class UsbModeChooserActivity extends Activity { } } - private static int getSummary(int mode) { - switch (mode) { - case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE: - return R.string.usb_use_charging_only_desc; - case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_NONE: - return R.string.usb_use_power_only_desc; - case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MTP: - return R.string.usb_use_file_transfers_desc; - case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_PTP: - return R.string.usb_use_photo_transfers_desc; - case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MIDI: - return R.string.usb_use_MIDI_desc; - } - return 0; - } - - private static int getTitle(int mode) { - switch (mode) { - case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE: - return R.string.usb_use_charging_only; - case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_NONE: - return R.string.usb_use_power_only; - case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MTP: - return R.string.usb_use_file_transfers; - case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_PTP: - return R.string.usb_use_photo_transfers; - case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MIDI: - return R.string.usb_use_MIDI; - } - return 0; - } } diff --git a/tests/robotests/src/com/android/settings/connecteddevice/UsbModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/connecteddevice/UsbModePreferenceControllerTest.java new file mode 100644 index 00000000000..da25f0f41b1 --- /dev/null +++ b/tests/robotests/src/com/android/settings/connecteddevice/UsbModePreferenceControllerTest.java @@ -0,0 +1,137 @@ +package com.android.settings.connecteddevice; + +import android.content.Context; +import android.content.Intent; +import android.hardware.usb.UsbManager; +import android.support.v7.preference.Preference; +import android.support.v7.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.SettingsRobolectricTestRunner; +import com.android.settings.TestConfig; +import com.android.settings.deviceinfo.UsbBackend; +import com.android.settings.deviceinfo.UsbModeChooserActivity; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowApplication; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Answers.RETURNS_DEEP_STUBS; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyString; +import static org.mockito.Mockito.when; + +@RunWith(SettingsRobolectricTestRunner.class) +@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) +public class UsbModePreferenceControllerTest { + + @Mock(answer = RETURNS_DEEP_STUBS) + private UsbBackend mUsbBackend; + @Mock(answer = RETURNS_DEEP_STUBS) + private PreferenceScreen mScreen; + + private Context mContext; + private UsbModePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = ShadowApplication.getInstance().getApplicationContext(); + mController = new UsbModePreferenceController(mContext, mUsbBackend); + } + + @Test + public void testGetSummary_chargeDevice() { + assertThat(UsbModePreferenceController.getSummary(UsbModeChooserActivity.DEFAULT_MODES[0])) + .isEqualTo(R.string.usb_use_charging_only_desc); + } + + @Test + public void testGetSummary_supplyPower() { + assertThat(UsbModePreferenceController.getSummary(UsbModeChooserActivity.DEFAULT_MODES[1])) + .isEqualTo(R.string.usb_use_power_only_desc); + } + + @Test + public void testGetSummary_TransferFiles() { + assertThat(UsbModePreferenceController.getSummary(UsbModeChooserActivity.DEFAULT_MODES[2])) + .isEqualTo(R.string.usb_use_file_transfers_desc); + } + + @Test + public void testGetSummary_TransferPhoto() { + assertThat(UsbModePreferenceController.getSummary(UsbModeChooserActivity.DEFAULT_MODES[3])) + .isEqualTo(R.string.usb_use_photo_transfers_desc); + } + + @Test + public void testGetSummary_MIDI() { + assertThat(UsbModePreferenceController.getSummary(UsbModeChooserActivity.DEFAULT_MODES[4])) + .isEqualTo(R.string.usb_use_MIDI_desc); + } + + @Test + public void testGetTitle_chargeDevice() { + assertThat(UsbModePreferenceController.getTitle(UsbModeChooserActivity.DEFAULT_MODES[0])) + .isEqualTo(R.string.usb_use_charging_only); + } + + @Test + public void testGetTitle_supplyPower() { + assertThat(UsbModePreferenceController.getTitle(UsbModeChooserActivity.DEFAULT_MODES[1])) + .isEqualTo(R.string.usb_use_power_only); + } + + @Test + public void testGetTitle_TransferFiles() { + assertThat(UsbModePreferenceController.getTitle(UsbModeChooserActivity.DEFAULT_MODES[2])) + .isEqualTo(R.string.usb_use_file_transfers); + } + + @Test + public void testGetTitle_TransferPhoto() { + assertThat(UsbModePreferenceController.getTitle(UsbModeChooserActivity.DEFAULT_MODES[3])) + .isEqualTo(R.string.usb_use_photo_transfers); + } + + @Test + public void testGetTitle_MIDI() { + assertThat(UsbModePreferenceController.getTitle(UsbModeChooserActivity.DEFAULT_MODES[4])) + .isEqualTo(R.string.usb_use_MIDI); + } + + @Test + public void testPreferenceSummary_usbDisconnected() { + final Preference preference = new Preference(mContext); + preference.setKey("usb_mode"); + preference.setEnabled(true); + mController.updateState(preference); + assertThat(preference.getSummary()).isEqualTo( + mContext.getString(R.string.usb_nothing_connected)); + } + + @Test + public void testUsbBoradcastReceiver_usbConnected_shouldUpdateSummary() { + final Preference preference = new Preference(mContext); + preference.setKey("usb_mode"); + preference.setEnabled(true); + when(mUsbBackend.getCurrentMode()).thenReturn(UsbModeChooserActivity.DEFAULT_MODES[0]); + when(mScreen.findPreference("usb_mode")).thenReturn(preference); + + mController.displayPreference(mScreen); + mController.onResume(); + final Intent intent = new Intent(UsbManager.ACTION_USB_STATE); + intent.putExtra(UsbManager.USB_CONNECTED, true); + mContext.sendStickyBroadcast(intent); + + assertThat(preference.getSummary()).isEqualTo( + mContext.getString(R.string.usb_use_charging_only)); + } + +} \ No newline at end of file