• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.app.PendingIntent;
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.ApplicationInfo;
26 import android.content.pm.PackageManager;
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.RemoteException;
34 import android.os.ServiceManager;
35 import android.os.UserHandle;
36 import android.util.Log;
37 import android.view.LayoutInflater;
38 import android.view.View;
39 import android.widget.CheckBox;
40 import android.widget.CompoundButton;
41 import android.widget.TextView;
42 
43 import com.android.internal.app.AlertActivity;
44 import com.android.internal.app.AlertController;
45 import com.android.systemui.R;
46 
47 public class UsbPermissionActivity extends AlertActivity
48         implements DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener {
49 
50     private static final String TAG = "UsbPermissionActivity";
51 
52     private CheckBox mAlwaysUse;
53     private TextView mClearDefaultHint;
54     private UsbDevice mDevice;
55     private UsbAccessory mAccessory;
56     private PendingIntent mPendingIntent;
57     private String mPackageName;
58     private int mUid;
59     private boolean mPermissionGranted;
60     private UsbDisconnectedReceiver mDisconnectedReceiver;
61 
62     @Override
onCreate(Bundle icicle)63     public void onCreate(Bundle icicle) {
64         super.onCreate(icicle);
65 
66         Intent intent = getIntent();
67         mDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
68         mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
69         mPendingIntent = (PendingIntent)intent.getParcelableExtra(Intent.EXTRA_INTENT);
70         mUid = intent.getIntExtra(Intent.EXTRA_UID, -1);
71         mPackageName = intent.getStringExtra(UsbManager.EXTRA_PACKAGE);
72         boolean canBeDefault = intent.getBooleanExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, false);
73 
74         PackageManager packageManager = getPackageManager();
75         ApplicationInfo aInfo;
76         try {
77             aInfo = packageManager.getApplicationInfo(mPackageName, 0);
78         } catch (PackageManager.NameNotFoundException e) {
79             Log.e(TAG, "unable to look up package name", e);
80             finish();
81             return;
82         }
83         String appName = aInfo.loadLabel(packageManager).toString();
84 
85         final AlertController.AlertParams ap = mAlertParams;
86         ap.mTitle = appName;
87         boolean useRecordWarning = false;
88         if (mDevice == null) {
89             // Accessory Case
90 
91             ap.mMessage = getString(R.string.usb_accessory_permission_prompt, appName,
92                     mAccessory.getDescription());
93             mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory);
94         } else {
95             boolean hasRecordPermission =
96                     PermissionChecker.checkPermissionForPreflight(
97                             this, android.Manifest.permission.RECORD_AUDIO, -1, aInfo.uid,
98                             mPackageName)
99                             == android.content.pm.PackageManager.PERMISSION_GRANTED;
100             boolean isAudioCaptureDevice = mDevice.getHasAudioCapture();
101             useRecordWarning = isAudioCaptureDevice && !hasRecordPermission;
102 
103             int strID = useRecordWarning
104                     ? R.string.usb_device_permission_prompt_warn
105                     : R.string.usb_device_permission_prompt;
106             ap.mMessage = getString(strID, appName, mDevice.getProductName());
107             mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice);
108 
109         }
110 
111         ap.mPositiveButtonText = getString(android.R.string.ok);
112         ap.mNegativeButtonText = getString(android.R.string.cancel);
113         ap.mPositiveButtonListener = this;
114         ap.mNegativeButtonListener = this;
115 
116         // Don't show the "always use" checkbox if the USB/Record warning is in effect
117         if (!useRecordWarning && canBeDefault && (mDevice != null || mAccessory != null)) {
118             // add "open when" checkbox
119             LayoutInflater inflater = (LayoutInflater) getSystemService(
120                     Context.LAYOUT_INFLATER_SERVICE);
121             ap.mView = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
122             mAlwaysUse = (CheckBox) ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
123             if (mDevice == null) {
124                 mAlwaysUse.setText(getString(R.string.always_use_accessory, appName,
125                         mAccessory.getDescription()));
126             } else {
127                 mAlwaysUse.setText(getString(R.string.always_use_device, appName,
128                         mDevice.getProductName()));
129             }
130             mAlwaysUse.setOnCheckedChangeListener(this);
131 
132             mClearDefaultHint = (TextView)ap.mView.findViewById(
133                     com.android.internal.R.id.clearDefaultHint);
134             mClearDefaultHint.setVisibility(View.GONE);
135         }
136 
137         setupAlert();
138     }
139 
140     @Override
onDestroy()141     public void onDestroy() {
142         IBinder b = ServiceManager.getService(USB_SERVICE);
143         IUsbManager service = IUsbManager.Stub.asInterface(b);
144 
145         // send response via pending intent
146         Intent intent = new Intent();
147         try {
148             if (mDevice != null) {
149                 intent.putExtra(UsbManager.EXTRA_DEVICE, mDevice);
150                 if (mPermissionGranted) {
151                     service.grantDevicePermission(mDevice, mUid);
152                     if (mAlwaysUse != null && mAlwaysUse.isChecked()) {
153                         final int userId = UserHandle.getUserId(mUid);
154                         service.setDevicePackage(mDevice, mPackageName, userId);
155                     }
156                 }
157             }
158             if (mAccessory != null) {
159                 intent.putExtra(UsbManager.EXTRA_ACCESSORY, mAccessory);
160                 if (mPermissionGranted) {
161                     service.grantAccessoryPermission(mAccessory, mUid);
162                     if (mAlwaysUse != null && mAlwaysUse.isChecked()) {
163                         final int userId = UserHandle.getUserId(mUid);
164                         service.setAccessoryPackage(mAccessory, mPackageName, userId);
165                     }
166                 }
167             }
168             intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, mPermissionGranted);
169             mPendingIntent.send(this, 0, intent);
170         } catch (PendingIntent.CanceledException e) {
171             Log.w(TAG, "PendingIntent was cancelled");
172         } catch (RemoteException e) {
173             Log.e(TAG, "IUsbService connection failed", e);
174         }
175 
176         if (mDisconnectedReceiver != null) {
177             unregisterReceiver(mDisconnectedReceiver);
178         }
179         super.onDestroy();
180     }
181 
onClick(DialogInterface dialog, int which)182     public void onClick(DialogInterface dialog, int which) {
183         if (which == AlertDialog.BUTTON_POSITIVE) {
184             mPermissionGranted = true;
185         }
186         finish();
187     }
188 
onCheckedChanged(CompoundButton buttonView, boolean isChecked)189     public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
190         if (mClearDefaultHint == null) return;
191 
192         if(isChecked) {
193             mClearDefaultHint.setVisibility(View.VISIBLE);
194         } else {
195             mClearDefaultHint.setVisibility(View.GONE);
196         }
197     }
198 }
199