/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.car.usb.handler; import static android.content.Intent.ACTION_USER_UNLOCKED; import android.annotation.Nullable; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbManager; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import java.util.List; /** * Activity to handle USB device attached. *

* When user plugs in USB device: a) Device was used before and user selected handler for it. In * this case handler will be launched. b) Device has not handler assigned. In this case supported * handlers will be captured, and user will be presented with choice to assign default handler. * After that handler will be launched. */ public class UsbHostManagementActivity extends Activity { private static final String TAG = UsbHostManagementActivity.class.getSimpleName(); private HandlersAdapter mListAdapter; private ListView mHandlersList; private TextView mHandlerTitle; private LinearLayout mUsbHandlersDialog; private UsbHostController mController; private PackageManager mPackageManager; private final ResolveBroadcastReceiver mResolveBroadcastReceiver = new ResolveBroadcastReceiver(); private boolean mReceiverRegistered = false; private void unregisterResolveBroadcastReceiver() { if (mReceiverRegistered) { unregisterReceiver(mResolveBroadcastReceiver); mReceiverRegistered = false; } } private void processDevice() { UsbDevice connectedDevice = getDevice(); if (connectedDevice != null) { mController.processDevice(connectedDevice); } else { finish(); } } private class ResolveBroadcastReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { // We could have been unregistered after receiving the intent but before processing it, // so make sure we are still registered. if (mReceiverRegistered) { unregisterResolveBroadcastReceiver(); processDevice(); } } } private final AdapterView.OnItemClickListener mHandlerClickListener = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, final View view, int position, long id) { UsbDeviceSettings settings = (UsbDeviceSettings) parent.getItemAtPosition(position); settings.setDefaultHandler(true); mController.applyDeviceSettings(settings); } }; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.usb_host); mUsbHandlersDialog = findViewById(R.id.usb_handlers_dialog); mHandlersList = findViewById(R.id.usb_handlers_list); mHandlerTitle = findViewById(R.id.usb_handler_heading); mListAdapter = new HandlersAdapter(this); mHandlersList.setAdapter(mListAdapter); mHandlersList.setOnItemClickListener(mHandlerClickListener); mController = new UsbHostController(this, new UsbCallbacks()); mPackageManager = getPackageManager(); } @Override public void onDestroy() { super.onDestroy(); mController.release(); } @Override public void onPause() { super.onPause(); unregisterResolveBroadcastReceiver(); } @Override public void onResume() { super.onResume(); UserManager userManager = getSystemService(UserManager.class); if (userManager.isUserUnlocked() || getUserId() == UserHandle.USER_SYSTEM) { processDevice(); } else { mReceiverRegistered = true; registerReceiver(mResolveBroadcastReceiver, new IntentFilter(ACTION_USER_UNLOCKED)); // in case the car was unlocked while the receiver was being registered if (userManager.isUserUnlocked()) { mResolveBroadcastReceiver.onReceive(this, new Intent(ACTION_USER_UNLOCKED)); } } } class UsbCallbacks implements UsbHostController.UsbHostControllerCallbacks { private boolean mProcessing = false; @Override public void shutdown() { runOnUiThread(new Runnable() { @Override public void run() { finish(); } }); } @Override public void processingStarted() { mProcessing = true; runOnUiThread(new Runnable() { @Override public void run() { if (mProcessing && !mListAdapter.isEmpty()) { mUsbHandlersDialog.setVisibility(View.VISIBLE); } } }); } @Override public void titleChanged(final String title) { runOnUiThread(() -> mHandlerTitle.setText(title)); } @Override public void optionsUpdated(final List options) { if (options != null && !options.isEmpty()) { runOnUiThread(new Runnable() { @Override public void run() { if (mProcessing) { mUsbHandlersDialog.setVisibility(View.VISIBLE); } mListAdapter.clear(); mListAdapter.addAll(options); } }); } } } @Override public void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); } @Nullable private UsbDevice getDevice() { if (!UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(getIntent().getAction())) { return null; } return (UsbDevice) getIntent().getParcelableExtra(UsbManager.EXTRA_DEVICE); } private class HandlersAdapter extends ArrayAdapter { class HandlerHolder { public TextView mAppName; public ImageView mAppIcon; } HandlersAdapter(Context context) { super(context, R.layout.usb_handler_row); } @Override public View getView(int position, View convertView, ViewGroup parent) { View rowView = convertView; if (rowView == null) { rowView = getLayoutInflater().inflate(R.layout.usb_handler_row, null); HandlerHolder holder = new HandlerHolder(); holder.mAppName = (TextView) rowView.findViewById(R.id.usb_handler_title); holder.mAppIcon = (ImageView) rowView.findViewById(R.id.usb_handler_icon); rowView.setTag(holder); } HandlerHolder holder = (HandlerHolder) rowView.getTag(); ComponentName handler = getItem(position).getHandler(); try { ApplicationInfo appInfo = mPackageManager.getApplicationInfo(handler.getPackageName(), 0); holder.mAppName.setText(appInfo.loadLabel(mPackageManager)); holder.mAppIcon.setImageDrawable(appInfo.loadIcon(mPackageManager)); } catch (NameNotFoundException e) { Log.e(TAG, "Handling package not found: " + handler.getPackageName()); holder.mAppName.setText(handler.flattenToShortString()); holder.mAppIcon.setImageResource(android.R.color.transparent); } return rowView; } } }