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