1 /* 2 * Copyright (C) 2015 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 17 package com.android.settings.deviceinfo; 18 19 import android.annotation.Nullable; 20 import android.app.Activity; 21 import android.app.ActivityManager; 22 import android.app.AlertDialog; 23 import android.content.BroadcastReceiver; 24 import android.content.Context; 25 import android.content.DialogInterface; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.graphics.drawable.Drawable; 29 import android.graphics.PorterDuff; 30 import android.hardware.usb.UsbManager; 31 import android.os.Bundle; 32 import android.os.UserHandle; 33 import android.os.UserManager; 34 import android.view.LayoutInflater; 35 import android.view.View; 36 import android.view.View.OnClickListener; 37 import android.widget.Checkable; 38 import android.widget.LinearLayout; 39 import android.widget.TextView; 40 41 import com.android.settings.R; 42 import com.android.settingslib.RestrictedLockUtils; 43 44 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin; 45 46 /** 47 * UI for the USB chooser dialog. 48 * 49 */ 50 public class UsbModeChooserActivity extends Activity { 51 52 public static final int[] DEFAULT_MODES = { 53 UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE, 54 UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_NONE, 55 UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MTP, 56 UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_PTP, 57 UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MIDI 58 }; 59 60 private UsbBackend mBackend; 61 private AlertDialog mDialog; 62 private LayoutInflater mLayoutInflater; 63 private EnforcedAdmin mEnforcedAdmin; 64 65 private BroadcastReceiver mDisconnectedReceiver = new BroadcastReceiver() { 66 @Override 67 public void onReceive(Context context, Intent intent) { 68 String action = intent.getAction(); 69 if (UsbManager.ACTION_USB_STATE.equals(action)) { 70 boolean connected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); 71 boolean hostConnected = 72 intent.getBooleanExtra(UsbManager.USB_HOST_CONNECTED, false); 73 if (!connected && !hostConnected) { 74 mDialog.dismiss(); 75 } 76 } 77 } 78 }; 79 80 @Override onCreate(@ullable Bundle savedInstanceState)81 protected void onCreate(@Nullable Bundle savedInstanceState) { 82 83 super.onCreate(savedInstanceState); 84 85 mLayoutInflater = LayoutInflater.from(this); 86 87 mDialog = new AlertDialog.Builder(this) 88 .setTitle(R.string.usb_use) 89 .setView(R.layout.usb_dialog_container) 90 .setOnDismissListener(new DialogInterface.OnDismissListener() { 91 @Override 92 public void onDismiss(DialogInterface dialog) { 93 finish(); 94 } 95 }) 96 .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 97 @Override 98 public void onClick(DialogInterface dialog, int which) { 99 finish(); 100 } 101 }).create(); 102 mDialog.show(); 103 104 LinearLayout container = (LinearLayout) mDialog.findViewById(R.id.container); 105 106 mEnforcedAdmin = RestrictedLockUtils.checkIfRestrictionEnforced(this, 107 UserManager.DISALLOW_USB_FILE_TRANSFER, UserHandle.myUserId()); 108 mBackend = new UsbBackend(this); 109 int current = mBackend.getCurrentMode(); 110 for (int i = 0; i < DEFAULT_MODES.length; i++) { 111 if (mBackend.isModeSupported(DEFAULT_MODES[i]) 112 && !mBackend.isModeDisallowedBySystem(DEFAULT_MODES[i])) { 113 inflateOption(DEFAULT_MODES[i], current == DEFAULT_MODES[i], container, 114 mBackend.isModeDisallowed(DEFAULT_MODES[i])); 115 } 116 } 117 } 118 119 @Override onStart()120 public void onStart() { 121 super.onStart(); 122 123 IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_STATE); 124 registerReceiver(mDisconnectedReceiver, filter); 125 } 126 127 @Override onStop()128 protected void onStop() { 129 unregisterReceiver(mDisconnectedReceiver); 130 super.onStop(); 131 } 132 inflateOption(final int mode, boolean selected, LinearLayout container, final boolean disallowedByAdmin)133 private void inflateOption(final int mode, boolean selected, LinearLayout container, 134 final boolean disallowedByAdmin) { 135 View v = mLayoutInflater.inflate(R.layout.restricted_radio_with_summary, container, false); 136 137 TextView titleView = (TextView) v.findViewById(android.R.id.title); 138 titleView.setText(getTitle(mode)); 139 TextView summaryView = (TextView) v.findViewById(android.R.id.summary); 140 summaryView.setText(getSummary(mode)); 141 142 if (disallowedByAdmin) { 143 if (mEnforcedAdmin != null) { 144 setDisabledByAdmin(v, titleView, summaryView); 145 } else { 146 return; 147 } 148 } 149 150 v.setOnClickListener(new OnClickListener() { 151 @Override 152 public void onClick(View v) { 153 if (disallowedByAdmin && mEnforcedAdmin != null) { 154 RestrictedLockUtils.sendShowAdminSupportDetailsIntent( 155 UsbModeChooserActivity.this, mEnforcedAdmin); 156 return; 157 } 158 if (!ActivityManager.isUserAMonkey()) { 159 mBackend.setMode(mode); 160 } 161 mDialog.dismiss(); 162 finish(); 163 } 164 }); 165 ((Checkable) v).setChecked(selected); 166 container.addView(v); 167 } 168 setDisabledByAdmin(View rootView, TextView titleView, TextView summaryView)169 private void setDisabledByAdmin(View rootView, TextView titleView, TextView summaryView) { 170 if (mEnforcedAdmin != null) { 171 titleView.setEnabled(false); 172 summaryView.setEnabled(false); 173 rootView.findViewById(R.id.restricted_icon).setVisibility(View.VISIBLE); 174 Drawable[] compoundDrawables = titleView.getCompoundDrawablesRelative(); 175 compoundDrawables[0 /* start */].mutate().setColorFilter( 176 getColor(R.color.disabled_text_color), PorterDuff.Mode.MULTIPLY); 177 } 178 } 179 getSummary(int mode)180 private static int getSummary(int mode) { 181 switch (mode) { 182 case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE: 183 return R.string.usb_use_charging_only_desc; 184 case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_NONE: 185 return R.string.usb_use_power_only_desc; 186 case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MTP: 187 return R.string.usb_use_file_transfers_desc; 188 case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_PTP: 189 return R.string.usb_use_photo_transfers_desc; 190 case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MIDI: 191 return R.string.usb_use_MIDI_desc; 192 } 193 return 0; 194 } 195 getTitle(int mode)196 private static int getTitle(int mode) { 197 switch (mode) { 198 case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_NONE: 199 return R.string.usb_use_charging_only; 200 case UsbBackend.MODE_POWER_SOURCE | UsbBackend.MODE_DATA_NONE: 201 return R.string.usb_use_power_only; 202 case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MTP: 203 return R.string.usb_use_file_transfers; 204 case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_PTP: 205 return R.string.usb_use_photo_transfers; 206 case UsbBackend.MODE_POWER_SINK | UsbBackend.MODE_DATA_MIDI: 207 return R.string.usb_use_MIDI; 208 } 209 return 0; 210 } 211 } 212