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