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 static com.android.settingslib.RestrictedLockUtilsInternal.checkIfUsbDataSignalingIsDisabled; 23 24 import android.content.Context; 25 import android.hardware.usb.UsbManager; 26 import android.os.UserHandle; 27 28 import androidx.annotation.VisibleForTesting; 29 import androidx.preference.Preference; 30 31 import com.android.settings.R; 32 import com.android.settings.connecteddevice.DevicePreferenceCallback; 33 import com.android.settings.core.SubSettingLauncher; 34 import com.android.settings.dashboard.DashboardFragment; 35 import com.android.settings.overlay.FeatureFactory; 36 import com.android.settingslib.RestrictedPreference; 37 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 38 39 /** 40 * Controller to maintain connected usb device 41 */ 42 public class ConnectedUsbDeviceUpdater { 43 44 private static final String PREF_KEY = "connected_usb"; 45 46 private final MetricsFeatureProvider mMetricsFeatureProvider; 47 48 private DashboardFragment mFragment; 49 private UsbBackend mUsbBackend; 50 private DevicePreferenceCallback mDevicePreferenceCallback; 51 @VisibleForTesting 52 RestrictedPreference mUsbPreference; 53 @VisibleForTesting 54 UsbConnectionBroadcastReceiver mUsbReceiver; 55 56 @VisibleForTesting 57 UsbConnectionBroadcastReceiver.UsbConnectionListener mUsbConnectionListener = 58 (connected, functions, powerRole, dataRole) -> { 59 if (connected) { 60 mUsbPreference.setSummary(getSummary(dataRole == DATA_ROLE_DEVICE 61 ? functions : UsbManager.FUNCTION_NONE, powerRole)); 62 mDevicePreferenceCallback.onDeviceAdded(mUsbPreference); 63 } else { 64 mDevicePreferenceCallback.onDeviceRemoved(mUsbPreference); 65 } 66 }; 67 ConnectedUsbDeviceUpdater(Context context, DashboardFragment fragment, DevicePreferenceCallback devicePreferenceCallback)68 public ConnectedUsbDeviceUpdater(Context context, DashboardFragment fragment, 69 DevicePreferenceCallback devicePreferenceCallback) { 70 this(context, fragment, devicePreferenceCallback, new UsbBackend(context)); 71 } 72 73 @VisibleForTesting ConnectedUsbDeviceUpdater(Context context, DashboardFragment fragment, DevicePreferenceCallback devicePreferenceCallback, UsbBackend usbBackend)74 ConnectedUsbDeviceUpdater(Context context, DashboardFragment fragment, 75 DevicePreferenceCallback devicePreferenceCallback, UsbBackend usbBackend) { 76 mFragment = fragment; 77 mDevicePreferenceCallback = devicePreferenceCallback; 78 mUsbBackend = usbBackend; 79 mUsbReceiver = new UsbConnectionBroadcastReceiver(context, 80 mUsbConnectionListener, mUsbBackend); 81 mMetricsFeatureProvider = FeatureFactory.getFactory(mFragment.getContext()) 82 .getMetricsFeatureProvider(); 83 } 84 registerCallback()85 public void registerCallback() { 86 // This method could handle multiple register 87 mUsbReceiver.register(); 88 } 89 unregisterCallback()90 public void unregisterCallback() { 91 mUsbReceiver.unregister(); 92 } 93 initUsbPreference(Context context)94 public void initUsbPreference(Context context) { 95 mUsbPreference = new RestrictedPreference(context, null /* AttributeSet */); 96 mUsbPreference.setTitle(R.string.usb_pref); 97 mUsbPreference.setIcon(R.drawable.ic_usb); 98 mUsbPreference.setKey(PREF_KEY); 99 mUsbPreference.setDisabledByAdmin( 100 checkIfUsbDataSignalingIsDisabled(context, UserHandle.myUserId())); 101 mUsbPreference.setOnPreferenceClickListener((Preference p) -> { 102 mMetricsFeatureProvider.logClickedPreference(p, mFragment.getMetricsCategory()); 103 // New version - uses a separate screen. 104 new SubSettingLauncher(mFragment.getContext()) 105 .setDestination(UsbDetailsFragment.class.getName()) 106 .setTitleRes(R.string.usb_preference) 107 .setSourceMetricsCategory(mFragment.getMetricsCategory()) 108 .launch(); 109 return true; 110 }); 111 112 forceUpdate(); 113 } 114 forceUpdate()115 private void forceUpdate() { 116 // Register so we can get the connection state from sticky intent. 117 //TODO(b/70336520): Use an API to get data instead of sticky intent 118 mUsbReceiver.register(); 119 } 120 getSummary(long functions, int power)121 public static int getSummary(long functions, int power) { 122 switch (power) { 123 case POWER_ROLE_SINK: 124 if (functions == UsbManager.FUNCTION_MTP) { 125 return R.string.usb_summary_file_transfers; 126 } else if (functions == UsbManager.FUNCTION_RNDIS) { 127 return R.string.usb_summary_tether; 128 } else if (functions == UsbManager.FUNCTION_PTP) { 129 return R.string.usb_summary_photo_transfers; 130 } else if (functions == UsbManager.FUNCTION_MIDI) { 131 return R.string.usb_summary_MIDI; 132 } else { 133 return R.string.usb_summary_charging_only; 134 } 135 case POWER_ROLE_SOURCE: 136 if (functions == UsbManager.FUNCTION_MTP) { 137 return R.string.usb_summary_file_transfers_power; 138 } else if (functions == UsbManager.FUNCTION_RNDIS) { 139 return R.string.usb_summary_tether_power; 140 } else if (functions == UsbManager.FUNCTION_PTP) { 141 return R.string.usb_summary_photo_transfers_power; 142 } else if (functions == UsbManager.FUNCTION_MIDI) { 143 return R.string.usb_summary_MIDI_power; 144 } else { 145 return R.string.usb_summary_power_only; 146 } 147 default: 148 return R.string.usb_summary_charging_only; 149 } 150 } 151 } 152