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 static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE; 20 21 import android.content.ActivityNotFoundException; 22 import android.content.ComponentName; 23 import android.content.Intent; 24 import android.content.pm.ResolveInfo; 25 import android.hardware.usb.IUsbManager; 26 import android.hardware.usb.UsbAccessory; 27 import android.hardware.usb.UsbDevice; 28 import android.hardware.usb.UsbManager; 29 import android.os.Bundle; 30 import android.os.IBinder; 31 import android.os.Parcelable; 32 import android.os.RemoteException; 33 import android.os.ServiceManager; 34 import android.os.UserHandle; 35 import android.util.Log; 36 import android.view.WindowManager; 37 import android.widget.CheckBox; 38 39 import com.android.internal.app.ResolverActivity; 40 import com.android.internal.app.chooser.TargetInfo; 41 import com.android.systemui.res.R; 42 43 import java.util.ArrayList; 44 import java.util.Iterator; 45 46 /* Activity for choosing an application for a USB device or accessory */ 47 public class UsbResolverActivity extends ResolverActivity { 48 public static final String TAG = "UsbResolverActivity"; 49 public static final String EXTRA_RESOLVE_INFOS = "rlist"; 50 public static final String EXTRA_RESOLVE_INFO = "rinfo"; 51 52 private UsbDevice mDevice; 53 private UsbAccessory mAccessory; 54 private UsbDisconnectedReceiver mDisconnectedReceiver; 55 56 /** Resolve info that switches user profiles */ 57 private ResolveInfo mForwardResolveInfo; 58 59 /** The intent that should be started when the profile is switched */ 60 private Intent mOtherProfileIntent; 61 62 @Override onCreate(Bundle savedInstanceState)63 protected void onCreate(Bundle savedInstanceState) { 64 getWindow().addSystemFlags( 65 WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); 66 Intent intent = getIntent(); 67 Parcelable targetParcelable = intent.getParcelableExtra(Intent.EXTRA_INTENT); 68 if (!(targetParcelable instanceof Intent)) { 69 super_onCreate(savedInstanceState); 70 Log.w("UsbResolverActivity", "Target is not an intent: " + targetParcelable); 71 finish(); 72 return; 73 } 74 Intent target = (Intent)targetParcelable; 75 ArrayList<ResolveInfo> rList = new ArrayList<>( 76 intent.getParcelableArrayListExtra(EXTRA_RESOLVE_INFOS)); 77 78 // The rList contains the apps for all profiles of this users. Separate those. We currently 79 // only support two profiles, i.e. one forward resolve info. 80 ArrayList<ResolveInfo> rListOtherProfile = new ArrayList<>(); 81 mForwardResolveInfo = null; 82 for (Iterator<ResolveInfo> iterator = rList.iterator(); iterator.hasNext();) { 83 ResolveInfo ri = iterator.next(); 84 85 if (ri.getComponentInfo().name.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) { 86 mForwardResolveInfo = ri; 87 } else if (UserHandle.getUserId(ri.activityInfo.applicationInfo.uid) 88 != UserHandle.myUserId()) { 89 iterator.remove(); 90 rListOtherProfile.add(ri); 91 } 92 } 93 94 mDevice = (UsbDevice)target.getParcelableExtra(UsbManager.EXTRA_DEVICE); 95 boolean hasAudioCapture = false; 96 if (mDevice != null) { 97 mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice); 98 hasAudioCapture = mDevice.getHasAudioCapture(); 99 } else { 100 mAccessory = (UsbAccessory)target.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); 101 if (mAccessory == null) { 102 super_onCreate(savedInstanceState); 103 Log.e(TAG, "no device or accessory"); 104 finish(); 105 return; 106 } 107 mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory); 108 } 109 110 // Create intent that will be used when switching to other profile. Emulate the behavior of 111 // UsbProfileGroupSettingsManager#resolveActivity 112 if (mForwardResolveInfo != null) { 113 if (rListOtherProfile.size() > 1) { 114 mOtherProfileIntent = new Intent(intent); 115 mOtherProfileIntent.putParcelableArrayListExtra(EXTRA_RESOLVE_INFOS, 116 rListOtherProfile); 117 } else { 118 mOtherProfileIntent = new Intent(); 119 mOtherProfileIntent.setComponent(ComponentName.unflattenFromString( 120 this.getResources().getString( 121 com.android.internal.R.string.config_usbConfirmActivity))); 122 mOtherProfileIntent.putExtra(EXTRA_RESOLVE_INFO, rListOtherProfile.get(0)); 123 124 if (mDevice != null) { 125 mOtherProfileIntent.putExtra(UsbManager.EXTRA_DEVICE, mDevice); 126 } 127 128 if (mAccessory != null) { 129 mOtherProfileIntent.putExtra(UsbManager.EXTRA_ACCESSORY, mAccessory); 130 } 131 } 132 } 133 getIntent().putExtra( 134 ResolverActivity.EXTRA_IS_AUDIO_CAPTURE_DEVICE, hasAudioCapture); 135 136 CharSequence title = getResources().getText(com.android.internal.R.string.chooseUsbActivity); 137 super.onCreate(savedInstanceState, target, title, null, rList, true); 138 139 CheckBox alwaysUse = (CheckBox)findViewById(com.android.internal.R.id.alwaysUse); 140 if (alwaysUse != null) { 141 if (mDevice == null) { 142 alwaysUse.setText(R.string.always_use_accessory); 143 } else { 144 alwaysUse.setText(R.string.always_use_device); 145 } 146 } 147 } 148 149 @Override onDestroy()150 protected void onDestroy() { 151 if (mDisconnectedReceiver != null) { 152 unregisterReceiver(mDisconnectedReceiver); 153 } 154 super.onDestroy(); 155 } 156 157 @Override onTargetSelected(TargetInfo target, boolean alwaysCheck)158 protected boolean onTargetSelected(TargetInfo target, boolean alwaysCheck) { 159 final ResolveInfo ri = target.getResolveInfo(); 160 if (ri == mForwardResolveInfo) { 161 startActivityAsUser(mOtherProfileIntent, null, 162 UserHandle.of(mForwardResolveInfo.targetUserId)); 163 return true; 164 } 165 166 try { 167 IBinder b = ServiceManager.getService(USB_SERVICE); 168 IUsbManager service = IUsbManager.Stub.asInterface(b); 169 final int uid = ri.activityInfo.applicationInfo.uid; 170 final int userId = UserHandle.myUserId(); 171 172 if (mDevice != null) { 173 // grant permission for the device 174 service.grantDevicePermission(mDevice, uid); 175 // set or clear default setting 176 if (alwaysCheck) { 177 service.setDevicePackage(mDevice, ri.activityInfo.packageName, userId); 178 } else { 179 service.setDevicePackage(mDevice, null, userId); 180 } 181 } else if (mAccessory != null) { 182 // grant permission for the accessory 183 service.grantAccessoryPermission(mAccessory, uid); 184 // set or clear default setting 185 if (alwaysCheck) { 186 service.setAccessoryPackage(mAccessory, ri.activityInfo.packageName, userId); 187 } else { 188 service.setAccessoryPackage(mAccessory, null, userId); 189 } 190 } 191 192 try { 193 target.startAsUser(this, null, UserHandle.of(userId)); 194 } catch (ActivityNotFoundException e) { 195 Log.e(TAG, "startActivity failed", e); 196 } 197 } catch (RemoteException e) { 198 Log.e(TAG, "onIntentSelected failed", e); 199 } 200 return true; 201 } 202 203 @Override shouldShowTabs()204 protected boolean shouldShowTabs() { 205 return false; 206 } 207 } 208