Home | History | Annotate | Download | only in aoapdevicetest
      1 /*
      2  * Copyright (C) 2016 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 com.android.hardware.usb.aoapdevicetest;
     17 
     18 import android.app.Activity;
     19 import android.app.PendingIntent;
     20 import android.content.BroadcastReceiver;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentFilter;
     24 import android.hardware.usb.UsbAccessory;
     25 import android.hardware.usb.UsbManager;
     26 import android.os.Bundle;
     27 import android.os.ParcelFileDescriptor;
     28 import android.util.Log;
     29 
     30 import java.io.FileInputStream;
     31 import java.io.FileOutputStream;
     32 import java.io.IOException;
     33 
     34 import libcore.io.IoUtils;
     35 
     36 public class UsbAoapDeviceTestActivity extends Activity {
     37     private static final String TAG = UsbAoapDeviceTestActivity.class.getSimpleName();
     38     private static final boolean DBG = true;
     39 
     40     private static final String ACTION_USB_ACCESSORY_PERMISSION =
     41             "com.android.hardware.usb.aoapdevicetest.ACTION_USB_ACCESSORY_PERMISSION";
     42 
     43     private UsbManager mUsbManager;
     44     private AccessoryReceiver mReceiver;
     45     private ParcelFileDescriptor mFd;
     46     private ReaderThread mReaderThread;
     47     private UsbAccessory mAccessory;
     48 
     49     @Override
     50     protected void onCreate(Bundle savedInstanceState) {
     51         super.onCreate(savedInstanceState);
     52 
     53         setContentView(R.layout.device);
     54 
     55         mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
     56         IntentFilter filter = new IntentFilter();
     57         filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
     58         filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
     59         filter.addAction(ACTION_USB_ACCESSORY_PERMISSION);
     60         mReceiver = new AccessoryReceiver();
     61         registerReceiver(mReceiver, filter);
     62 
     63         Intent intent = getIntent();
     64         if (intent.getAction().equals(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
     65             UsbAccessory accessory =
     66                     (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
     67             if (accessory != null) {
     68                 onAccessoryAttached(accessory);
     69             } else {
     70                 throw new RuntimeException("USB accessory is null.");
     71             }
     72         } else {
     73             finish();
     74         }
     75     }
     76 
     77     @Override
     78     protected void onDestroy() {
     79         super.onDestroy();
     80         unregisterReceiver(mReceiver);
     81         IoUtils.closeQuietly(mFd);
     82         if (mReaderThread != null) {
     83             mReaderThread.requestToQuit();
     84             try {
     85                 mReaderThread.join(1000);
     86             } catch (InterruptedException e) {
     87             }
     88             if (mReaderThread.isAlive()) { // reader thread stuck
     89                 Log.w(TAG, "ReaderThread still alive");
     90             }
     91         }
     92     }
     93 
     94     private void onAccessoryAttached(UsbAccessory accessory) {
     95         Log.i(TAG, "Starting AOAP discovery protocol, accessory attached: " + accessory);
     96         // Check whether we have permission to access the accessory.
     97         if (!mUsbManager.hasPermission(accessory)) {
     98             Log.i(TAG, "Prompting the user for access to the accessory.");
     99             Intent intent = new Intent(ACTION_USB_ACCESSORY_PERMISSION);
    100             intent.setPackage(getPackageName());
    101             PendingIntent pendingIntent = PendingIntent.getBroadcast(
    102                     this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
    103             mUsbManager.requestPermission(accessory, pendingIntent);
    104             return;
    105         }
    106         mFd = mUsbManager.openAccessory(accessory);
    107         if (mFd == null) {
    108             Log.e(TAG, "UsbManager.openAccessory returned null");
    109             finish();
    110             return;
    111         }
    112         mAccessory = accessory;
    113         mReaderThread = new ReaderThread(mFd);
    114         mReaderThread.start();
    115     }
    116 
    117     private void onAccessoryDetached(UsbAccessory accessory) {
    118         Log.i(TAG, "Accessory detached: " + accessory);
    119         finish();
    120     }
    121 
    122     private class ReaderThread extends Thread {
    123         private boolean mShouldQuit = false;
    124         private final FileInputStream mInputStream;
    125         private final FileOutputStream mOutputStream;
    126         private final byte[] mBuffer = new byte[16384];
    127 
    128         private ReaderThread(ParcelFileDescriptor fd) {
    129             super("AOAP");
    130             mInputStream = new FileInputStream(fd.getFileDescriptor());
    131             mOutputStream = new FileOutputStream(fd.getFileDescriptor());
    132         }
    133 
    134         private synchronized void requestToQuit() {
    135             mShouldQuit = true;
    136         }
    137 
    138         private synchronized boolean shouldQuit() {
    139             return mShouldQuit;
    140         }
    141 
    142         @Override
    143         public void run() {
    144             while (!shouldQuit()) {
    145                 try {
    146                     int read = mInputStream.read(mBuffer);
    147                 } catch (IOException e) {
    148                     Log.i(TAG, "ReaderThread IOException", e);
    149                     // AOAP App should release FD when IOException happens.
    150                     // If FD is kept, device will not behave nicely on reset and multiple reset
    151                     // can be required.
    152                     finish();
    153                     return;
    154                 }
    155             }
    156         }
    157     }
    158 
    159     private class AccessoryReceiver extends BroadcastReceiver {
    160         @Override
    161         public void onReceive(Context context, Intent intent) {
    162             UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
    163             if (accessory != null) {
    164                 String action = intent.getAction();
    165                 if (action.equals(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
    166                     onAccessoryAttached(accessory);
    167                 } else if (action.equals(UsbManager.ACTION_USB_ACCESSORY_DETACHED)) {
    168                     if (mAccessory != null && mAccessory.equals(accessory)) {
    169                         onAccessoryDetached(accessory);
    170                     }
    171                 } else if (action.equals(ACTION_USB_ACCESSORY_PERMISSION)) {
    172                     if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
    173                         Log.i(TAG, "Accessory permission granted: " + accessory);
    174                         onAccessoryAttached(accessory);
    175                     } else {
    176                         Log.e(TAG, "Accessory permission denied: " + accessory);
    177                         finish();
    178                     }
    179                 }
    180             }
    181         }
    182     }
    183 }
    184