1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.settings.connecteddevice.usb; 17 18 import static android.hardware.usb.UsbPortStatus.DATA_ROLE_DEVICE; 19 import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SINK; 20 import static android.hardware.usb.UsbPortStatus.POWER_ROLE_SOURCE; 21 22 import android.content.Context; 23 import android.hardware.usb.UsbManager; 24 25 import androidx.annotation.VisibleForTesting; 26 import androidx.preference.Preference; 27 28 import com.android.settings.R; 29 import com.android.settings.connecteddevice.DevicePreferenceCallback; 30 import com.android.settings.core.SubSettingLauncher; 31 import com.android.settings.dashboard.DashboardFragment; 32 import com.android.settings.overlay.FeatureFactory; 33 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 34 35 /** 36 * Controller to maintain connected usb device 37 */ 38 public class ConnectedUsbDeviceUpdater { 39 40 private static final String PREF_KEY = "connected_usb"; 41 42 private final MetricsFeatureProvider mMetricsFeatureProvider; 43 44 private DashboardFragment mFragment; 45 private UsbBackend mUsbBackend; 46 private DevicePreferenceCallback mDevicePreferenceCallback; 47 @VisibleForTesting 48 Preference mUsbPreference; 49 @VisibleForTesting 50 UsbConnectionBroadcastReceiver mUsbReceiver; 51 52 @VisibleForTesting 53 UsbConnectionBroadcastReceiver.UsbConnectionListener mUsbConnectionListener = 54 (connected, functions, powerRole, dataRole) -> { 55 if (connected) { 56 mUsbPreference.setSummary(getSummary(dataRole == DATA_ROLE_DEVICE 57 ? functions : UsbManager.FUNCTION_NONE, powerRole)); 58 mDevicePreferenceCallback.onDeviceAdded(mUsbPreference); 59 } else { 60 mDevicePreferenceCallback.onDeviceRemoved(mUsbPreference); 61 } 62 }; 63 ConnectedUsbDeviceUpdater(Context context, DashboardFragment fragment, DevicePreferenceCallback devicePreferenceCallback)64 public ConnectedUsbDeviceUpdater(Context context, DashboardFragment fragment, 65 DevicePreferenceCallback devicePreferenceCallback) { 66 this(context, fragment, devicePreferenceCallback, new UsbBackend(context)); 67 } 68 69 @VisibleForTesting ConnectedUsbDeviceUpdater(Context context, DashboardFragment fragment, DevicePreferenceCallback devicePreferenceCallback, UsbBackend usbBackend)70 ConnectedUsbDeviceUpdater(Context context, DashboardFragment fragment, 71 DevicePreferenceCallback devicePreferenceCallback, UsbBackend usbBackend) { 72 mFragment = fragment; 73 mDevicePreferenceCallback = devicePreferenceCallback; 74 mUsbBackend = usbBackend; 75 mUsbReceiver = new UsbConnectionBroadcastReceiver(context, 76 mUsbConnectionListener, mUsbBackend); 77 mMetricsFeatureProvider = FeatureFactory.getFactory(mFragment.getContext()) 78 .getMetricsFeatureProvider(); 79 } 80 registerCallback()81 public void registerCallback() { 82 // This method could handle multiple register 83 mUsbReceiver.register(); 84 } 85 unregisterCallback()86 public void unregisterCallback() { 87 mUsbReceiver.unregister(); 88 } 89 initUsbPreference(Context context)90 public void initUsbPreference(Context context) { 91 mUsbPreference = new Preference(context, null /* AttributeSet */); 92 mUsbPreference.setTitle(R.string.usb_pref); 93 mUsbPreference.setIcon(R.drawable.ic_usb); 94 mUsbPreference.setKey(PREF_KEY); 95 mUsbPreference.setOnPreferenceClickListener((Preference p) -> { 96 mMetricsFeatureProvider.logClickedPreference(p, mFragment.getMetricsCategory()); 97 // New version - uses a separate screen. 98 new SubSettingLauncher(mFragment.getContext()) 99 .setDestination(UsbDetailsFragment.class.getName()) 100 .setTitleRes(R.string.device_details_title) 101 .setSourceMetricsCategory(mFragment.getMetricsCategory()) 102 .launch(); 103 return true; 104 }); 105 106 forceUpdate(); 107 } 108 forceUpdate()109 private void forceUpdate() { 110 // Register so we can get the connection state from sticky intent. 111 //TODO(b/70336520): Use an API to get data instead of sticky intent 112 mUsbReceiver.register(); 113 } 114 getSummary(long functions, int power)115 public static int getSummary(long functions, int power) { 116 switch (power) { 117 case POWER_ROLE_SINK: 118 if (functions == UsbManager.FUNCTION_MTP) { 119 return R.string.usb_summary_file_transfers; 120 } else if (functions == UsbManager.FUNCTION_RNDIS) { 121 return R.string.usb_summary_tether; 122 } else if (functions == UsbManager.FUNCTION_PTP) { 123 return R.string.usb_summary_photo_transfers; 124 } else if (functions == UsbManager.FUNCTION_MIDI) { 125 return R.string.usb_summary_MIDI; 126 } else { 127 return R.string.usb_summary_charging_only; 128 } 129 case POWER_ROLE_SOURCE: 130 if (functions == UsbManager.FUNCTION_MTP) { 131 return R.string.usb_summary_file_transfers_power; 132 } else if (functions == UsbManager.FUNCTION_RNDIS) { 133 return R.string.usb_summary_tether_power; 134 } else if (functions == UsbManager.FUNCTION_PTP) { 135 return R.string.usb_summary_photo_transfers_power; 136 } else if (functions == UsbManager.FUNCTION_MIDI) { 137 return R.string.usb_summary_MIDI_power; 138 } else { 139 return R.string.usb_summary_power_only; 140 } 141 default: 142 return R.string.usb_summary_charging_only; 143 } 144 } 145 } 146