1 /* 2 * Copyright (C) 2019 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 package android.car.usb.handler; 17 18 import static android.content.Intent.ACTION_USER_SWITCHED; 19 20 import android.app.ActivityManager; 21 import android.app.Notification; 22 import android.app.NotificationChannel; 23 import android.app.NotificationManager; 24 import android.app.Service; 25 import android.content.BroadcastReceiver; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.IntentFilter; 29 import android.hardware.usb.UsbDevice; 30 import android.hardware.usb.UsbManager; 31 import android.os.Binder; 32 import android.os.UserHandle; 33 import android.util.Log; 34 35 import java.util.ArrayList; 36 37 /** 38 * Starts the {@link UsbHostManagementActivity} for each connected usb device when {@link 39 * #onStartCommand(Intent, int, int)} is called. This is meant to allow this activity to start for 40 * connected devices on start up, without holding up processing of the LOCKED_BOOT_COMPLETED intent. 41 */ 42 public class BootUsbService extends Service { 43 private static final String TAG = BootUsbService.class.getSimpleName(); 44 private static final int NOTIFICATION_ID = 1; 45 46 static final String USB_DEVICE_LIST_KEY = "usb_device_list"; 47 48 private ArrayList<UsbDevice> mDeviceList; 49 private boolean mReceiverRegistered = false; 50 private final BroadcastReceiver mUserSwitchBroadcastReceiver = new BroadcastReceiver() { 51 @Override 52 public void onReceive(Context context, Intent intent) { 53 processDevices(); 54 unregisterUserSwitchReceiver(); 55 } 56 }; 57 58 @Override onBind(Intent intent)59 public Binder onBind(Intent intent) { 60 return null; 61 } 62 63 @Override onCreate()64 public void onCreate() { 65 String notificationIdString = 66 getResources().getString(R.string.usb_boot_service_notification); 67 NotificationManager notificationManager = getSystemService(NotificationManager.class); 68 NotificationChannel notificationChannel = 69 new NotificationChannel( 70 notificationIdString, 71 "Car Usb Handler enumeration", 72 NotificationManager.IMPORTANCE_NONE); 73 notificationManager.createNotificationChannel(notificationChannel); 74 Notification notification = 75 new Notification.Builder( 76 this, notificationIdString).setSmallIcon(R.drawable.ic_launcher).build(); 77 // CarUsbHandler runs in the background, so startForeground must be explicitly called. 78 startForeground(NOTIFICATION_ID, notification); 79 } 80 81 @Override onStartCommand(Intent intent, int flags, int startId)82 public int onStartCommand(Intent intent, int flags, int startId) { 83 mDeviceList = intent.getParcelableArrayListExtra(USB_DEVICE_LIST_KEY); 84 // If the current user is still the system user, wait until the non system user becomes the 85 // current/foreground user. Otherwise, we can go ahead and start processing the USB devices 86 // immediately. 87 if (ActivityManager.getCurrentUser() == UserHandle.USER_SYSTEM) { 88 Log.d(TAG, "Current user is still the system user, waiting for user switch"); 89 registerUserSwitchReceiver(); 90 } else { 91 processDevices(); 92 } 93 94 return START_NOT_STICKY; 95 } 96 97 @Override onDestroy()98 public void onDestroy() { 99 unregisterUserSwitchReceiver(); 100 } 101 processDevices()102 private void processDevices() { 103 Log.d(TAG, "Processing connected USB devices and starting handlers"); 104 for (UsbDevice device : mDeviceList) { 105 handle(this, device); 106 } 107 stopSelf(); 108 } 109 handle(Context context, UsbDevice device)110 private void handle(Context context, UsbDevice device) { 111 Intent manageDevice = new Intent(context, UsbHostManagementActivity.class); 112 manageDevice.setAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); 113 manageDevice.putExtra(UsbManager.EXTRA_DEVICE, device); 114 manageDevice.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); 115 context.startActivityAsUser(manageDevice, UserHandle.CURRENT); 116 } 117 registerUserSwitchReceiver()118 private void registerUserSwitchReceiver() { 119 if (!mReceiverRegistered) { 120 registerReceiver(mUserSwitchBroadcastReceiver, new IntentFilter(ACTION_USER_SWITCHED)); 121 mReceiverRegistered = true; 122 } 123 } 124 unregisterUserSwitchReceiver()125 private void unregisterUserSwitchReceiver() { 126 if (mReceiverRegistered) { 127 unregisterReceiver(mUserSwitchBroadcastReceiver); 128 mReceiverRegistered = false; 129 } 130 } 131 } 132