Home | History | Annotate | Download | only in source
      1 /*
      2  * Copyright (C) 2013 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.accessorydisplay.source;
     18 
     19 import com.android.accessorydisplay.common.Logger;
     20 import com.android.accessorydisplay.source.presentation.DemoPresentation;
     21 
     22 import android.app.Activity;
     23 import android.app.PendingIntent;
     24 import android.content.BroadcastReceiver;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.IntentFilter;
     28 import android.hardware.usb.UsbAccessory;
     29 import android.hardware.usb.UsbManager;
     30 import android.os.Bundle;
     31 import android.os.ParcelFileDescriptor;
     32 import android.text.method.ScrollingMovementMethod;
     33 import android.util.Log;
     34 import android.view.Display;
     35 import android.widget.TextView;
     36 
     37 public class SourceActivity extends Activity {
     38     private static final String TAG = "SourceActivity";
     39 
     40     private static final String ACTION_USB_ACCESSORY_PERMISSION =
     41             "com.android.accessorydisplay.source.ACTION_USB_ACCESSORY_PERMISSION";
     42 
     43     private static final String MANUFACTURER = "Android";
     44     private static final String MODEL = "Accessory Display";
     45 
     46     private UsbManager mUsbManager;
     47     private AccessoryReceiver mReceiver;
     48     private TextView mLogTextView;
     49     private Logger mLogger;
     50     private Presenter mPresenter;
     51 
     52     private boolean mConnected;
     53     private UsbAccessory mAccessory;
     54     private UsbAccessoryStreamTransport mTransport;
     55 
     56     private DisplaySourceService mDisplaySourceService;
     57 
     58     @Override
     59     protected void onCreate(Bundle savedInstanceState) {
     60         super.onCreate(savedInstanceState);
     61 
     62         mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
     63 
     64         setContentView(R.layout.source_activity);
     65 
     66         mLogTextView = (TextView) findViewById(R.id.logTextView);
     67         mLogTextView.setMovementMethod(ScrollingMovementMethod.getInstance());
     68         mLogger = new TextLogger();
     69         mPresenter = new Presenter();
     70 
     71         mLogger.log("Waiting for accessory display sink to be attached to USB...");
     72 
     73         IntentFilter filter = new IntentFilter();
     74         filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
     75         filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
     76         filter.addAction(ACTION_USB_ACCESSORY_PERMISSION);
     77         mReceiver = new AccessoryReceiver();
     78         registerReceiver(mReceiver, filter);
     79 
     80         Intent intent = getIntent();
     81         if (intent.getAction().equals(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
     82             UsbAccessory accessory =
     83                     (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
     84             if (accessory != null) {
     85                 onAccessoryAttached(accessory);
     86             }
     87         } else {
     88             UsbAccessory[] accessories = mUsbManager.getAccessoryList();
     89             if (accessories != null) {
     90                 for (UsbAccessory accessory : accessories) {
     91                     onAccessoryAttached(accessory);
     92                 }
     93             }
     94         }
     95     }
     96 
     97     @Override
     98     protected void onDestroy() {
     99         super.onDestroy();
    100 
    101         unregisterReceiver(mReceiver);
    102     }
    103 
    104     @Override
    105     protected void onResume() {
    106         super.onResume();
    107 
    108         //new DemoPresentation(this, getWindowManager().getDefaultDisplay()).show();
    109     }
    110 
    111     @Override
    112     protected void onPause() {
    113         super.onPause();
    114     }
    115 
    116     private void onAccessoryAttached(UsbAccessory accessory) {
    117         mLogger.log("USB accessory attached: " + accessory);
    118         if (!mConnected) {
    119             connect(accessory);
    120         }
    121     }
    122 
    123     private void onAccessoryDetached(UsbAccessory accessory) {
    124         mLogger.log("USB accessory detached: " + accessory);
    125         if (mConnected && accessory.equals(mAccessory)) {
    126             disconnect();
    127         }
    128     }
    129 
    130     private void connect(UsbAccessory accessory) {
    131         if (!isSink(accessory)) {
    132             mLogger.log("Not connecting to USB accessory because it is not an accessory display sink: "
    133                     + accessory);
    134             return;
    135         }
    136 
    137         if (mConnected) {
    138             disconnect();
    139         }
    140 
    141         // Check whether we have permission to access the accessory.
    142         if (!mUsbManager.hasPermission(accessory)) {
    143             mLogger.log("Prompting the user for access to the accessory.");
    144             Intent intent = new Intent(ACTION_USB_ACCESSORY_PERMISSION);
    145             intent.setPackage(getPackageName());
    146             PendingIntent pendingIntent = PendingIntent.getBroadcast(
    147                     this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
    148             mUsbManager.requestPermission(accessory, pendingIntent);
    149             return;
    150         }
    151 
    152         // Open the accessory.
    153         ParcelFileDescriptor fd = mUsbManager.openAccessory(accessory);
    154         if (fd == null) {
    155             mLogger.logError("Could not obtain accessory connection.");
    156             return;
    157         }
    158 
    159         // All set.
    160         mLogger.log("Connected.");
    161         mConnected = true;
    162         mAccessory = accessory;
    163         mTransport = new UsbAccessoryStreamTransport(mLogger, fd);
    164         startServices();
    165         mTransport.startReading();
    166     }
    167 
    168     private void disconnect() {
    169         mLogger.log("Disconnecting from accessory: " + mAccessory);
    170         stopServices();
    171 
    172         mLogger.log("Disconnected.");
    173         mConnected = false;
    174         mAccessory = null;
    175         if (mTransport != null) {
    176             mTransport.close();
    177             mTransport = null;
    178         }
    179     }
    180 
    181     private void startServices() {
    182         mDisplaySourceService = new DisplaySourceService(this, mTransport, mPresenter);
    183         mDisplaySourceService.start();
    184     }
    185 
    186     private void stopServices() {
    187         if (mDisplaySourceService != null) {
    188             mDisplaySourceService.stop();
    189             mDisplaySourceService = null;
    190         }
    191     }
    192 
    193     private static boolean isSink(UsbAccessory accessory) {
    194         return MANUFACTURER.equals(accessory.getManufacturer())
    195                 && MODEL.equals(accessory.getModel());
    196     }
    197 
    198     class TextLogger extends Logger {
    199         @Override
    200         public void log(final String message) {
    201             Log.d(TAG, message);
    202 
    203             mLogTextView.post(new Runnable() {
    204                 @Override
    205                 public void run() {
    206                     mLogTextView.append(message);
    207                     mLogTextView.append("\n");
    208                 }
    209             });
    210         }
    211     }
    212 
    213     class AccessoryReceiver extends BroadcastReceiver {
    214         @Override
    215         public void onReceive(Context context, Intent intent) {
    216             UsbAccessory accessory = intent.<UsbAccessory>getParcelableExtra(
    217                     UsbManager.EXTRA_ACCESSORY);
    218             if (accessory != null) {
    219                 String action = intent.getAction();
    220                 if (action.equals(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
    221                     onAccessoryAttached(accessory);
    222                 } else if (action.equals(UsbManager.ACTION_USB_ACCESSORY_DETACHED)) {
    223                     onAccessoryDetached(accessory);
    224                 } else if (action.equals(ACTION_USB_ACCESSORY_PERMISSION)) {
    225                     if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
    226                         mLogger.log("Accessory permission granted: " + accessory);
    227                         onAccessoryAttached(accessory);
    228                     } else {
    229                         mLogger.logError("Accessory permission denied: " + accessory);
    230                     }
    231                 }
    232             }
    233         }
    234     }
    235 
    236     class Presenter implements DisplaySourceService.Callbacks {
    237         private DemoPresentation mPresentation;
    238 
    239         @Override
    240         public void onDisplayAdded(Display display) {
    241             mLogger.log("Accessory display added: " + display);
    242 
    243             mPresentation = new DemoPresentation(SourceActivity.this, display, mLogger);
    244             mPresentation.show();
    245         }
    246 
    247         @Override
    248         public void onDisplayRemoved(Display display) {
    249             mLogger.log("Accessory display removed: " + display);
    250 
    251             if (mPresentation != null) {
    252                 mPresentation.dismiss();
    253                 mPresentation = null;
    254             }
    255         }
    256     }
    257 }
    258