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