1 /*
2  * Copyright (C) 2011 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.systemui.usb;
18 
19 import android.app.AlertDialog;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.DialogInterface;
23 import android.content.Intent;
24 import android.content.PermissionChecker;
25 import android.content.pm.PackageManager;
26 import android.content.pm.ResolveInfo;
27 import android.hardware.usb.IUsbManager;
28 import android.hardware.usb.UsbAccessory;
29 import android.hardware.usb.UsbDevice;
30 import android.hardware.usb.UsbManager;
31 import android.os.Bundle;
32 import android.os.IBinder;
33 import android.os.ServiceManager;
34 import android.os.UserHandle;
35 import android.util.Log;
36 import android.view.LayoutInflater;
37 import android.view.View;
38 import android.widget.CheckBox;
39 import android.widget.CompoundButton;
40 import android.widget.TextView;
41 
42 import com.android.internal.app.AlertActivity;
43 import com.android.internal.app.AlertController;
44 import com.android.systemui.R;
45 
46 public class UsbConfirmActivity extends AlertActivity
47         implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener {
48 
49     private static final String TAG = "UsbConfirmActivity";
50 
51     private CheckBox mAlwaysUse;
52     private TextView mClearDefaultHint;
53     private UsbDevice mDevice;
54     private UsbAccessory mAccessory;
55     private ResolveInfo mResolveInfo;
56     private boolean mPermissionGranted;
57     private UsbDisconnectedReceiver mDisconnectedReceiver;
58 
59     @Override
onCreate(Bundle icicle)60     public void onCreate(Bundle icicle) {
61         super.onCreate(icicle);
62 
63         Intent intent = getIntent();
64         mDevice = (UsbDevice) intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
65         mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
66         mResolveInfo = (ResolveInfo) intent.getParcelableExtra("rinfo");
67         String packageName = intent.getStringExtra(UsbManager.EXTRA_PACKAGE);
68 
69         PackageManager packageManager = getPackageManager();
70         String appName = mResolveInfo.loadLabel(packageManager).toString();
71 
72         final AlertController.AlertParams ap = mAlertParams;
73         ap.mTitle = appName;
74         boolean useRecordWarning = false;
75         if (mDevice == null) {
76             ap.mMessage = getString(R.string.usb_accessory_confirm_prompt, appName,
77                     mAccessory.getDescription());
78             mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);
79         } else {
80             int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
81             boolean hasRecordPermission =
82                     PermissionChecker.checkPermissionForPreflight(
83                             this, android.Manifest.permission.RECORD_AUDIO, -1, uid,
84                             packageName)
85                             == android.content.pm.PackageManager.PERMISSION_GRANTED;
86             boolean isAudioCaptureDevice = mDevice.getHasAudioCapture();
87             useRecordWarning = isAudioCaptureDevice && !hasRecordPermission;
88 
89             int strID = useRecordWarning
90                     ? R.string.usb_device_confirm_prompt_warn
91                     : R.string.usb_device_confirm_prompt;
92 
93             ap.mMessage = getString(strID, appName, mDevice.getProductName());
94             mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);
95         }
96         ap.mPositiveButtonText = getString(android.R.string.ok);
97         ap.mNegativeButtonText = getString(android.R.string.cancel);
98         ap.mPositiveButtonListener = this;
99         ap.mNegativeButtonListener = this;
100 
101         // add "always use" checkbox
102         if (!useRecordWarning) {
103             LayoutInflater inflater = (LayoutInflater) getSystemService(
104                     Context.LAYOUT_INFLATER_SERVICE);
105             ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
106             mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
107             if (mDevice == null) {
108                 mAlwaysUse.setText(getString(R.string.always_use_accessory, appName,
109                         mAccessory.getDescription()));
110             } else {
111                 mAlwaysUse.setText(getString(R.string.always_use_device, appName,
112                         mDevice.getProductName()));
113             }
114             mAlwaysUse.setOnCheckedChangeListener(this);
115             mClearDefaultHint = (TextView) ap.mView.findViewById(
116                     com.android.internal.R.id.clearDefaultHint);
117             mClearDefaultHint.setVisibility(View.GONE);
118         }
119         setupAlert();
120 
121     }
122 
123     @Override
onDestroy()124     protected void onDestroy() {
125         if (mDisconnectedReceiver != null) {
126             unregisterReceiver(mDisconnectedReceiver);
127         }
128         super.onDestroy();
129     }
130 
onClick(DialogInterface dialog, int which)131     public void onClick(DialogInterface dialog, int which) {
132         if (which == AlertDialog.BUTTON_POSITIVE) {
133             try {
134                 IBinder b = ServiceManager.getService(USB_SERVICE);
135                 IUsbManager service = IUsbManager.Stub.asInterface(b);
136                 final int uid = mResolveInfo.activityInfo.applicationInfo.uid;
137                 final int userId = UserHandle.myUserId();
138                 boolean alwaysUse = mAlwaysUse != null ? mAlwaysUse.isChecked() : false;
139                 Intent intent = null;
140 
141                 if (mDevice != null) {
142                     intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);
143                     intent.putExtra(UsbManager.EXTRA_DEVICE, mDevice);
144 
145                     // grant permission for the device
146                     service.grantDevicePermission(mDevice, uid);
147                     // set or clear default setting
148                     if (alwaysUse) {
149                         service.setDevicePackage(
150                                 mDevice, mResolveInfo.activityInfo.packageName, userId);
151                     } else {
152                         service.setDevicePackage(mDevice, null, userId);
153                     }
154                 } else if (mAccessory != null) {
155                     intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
156                     intent.putExtra(UsbManager.EXTRA_ACCESSORY, mAccessory);
157 
158                     // grant permission for the accessory
159                     service.grantAccessoryPermission(mAccessory, uid);
160                     // set or clear default setting
161                     if (alwaysUse) {
162                         service.setAccessoryPackage(
163                                 mAccessory, mResolveInfo.activityInfo.packageName, userId);
164                     } else {
165                         service.setAccessoryPackage(mAccessory, null, userId);
166                     }
167                 }
168 
169                 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
170                 intent.setComponent(
171                     new ComponentName(mResolveInfo.activityInfo.packageName,
172                             mResolveInfo.activityInfo.name));
173                 startActivityAsUser(intent, new UserHandle(userId));
174             } catch (Exception e) {
175                 Log.e(TAG, "Unable to start activity", e);
176             }
177         }
178         finish();
179     }
180 
onCheckedChanged(CompoundButton buttonView, boolean isChecked)181     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
182         if (mClearDefaultHint == null) return;
183 
184         if(isChecked) {
185             mClearDefaultHint.setVisibility(View.VISIBLE);
186         } else {
187             mClearDefaultHint.setVisibility(View.GONE);
188         }
189     }
190 }
191