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 onCreate(Bundle savedInstanceState)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 = 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 onDestroy()98 protected void onDestroy() { 99 super.onDestroy(); 100 101 unregisterReceiver(mReceiver); 102 } 103 104 @Override onResume()105 protected void onResume() { 106 super.onResume(); 107 108 //new DemoPresentation(this, getWindowManager().getDefaultDisplay()).show(); 109 } 110 111 @Override onPause()112 protected void onPause() { 113 super.onPause(); 114 } 115 onAccessoryAttached(UsbAccessory accessory)116 private void onAccessoryAttached(UsbAccessory accessory) { 117 mLogger.log("USB accessory attached: " + accessory); 118 if (!mConnected) { 119 connect(accessory); 120 } 121 } 122 onAccessoryDetached(UsbAccessory accessory)123 private void onAccessoryDetached(UsbAccessory accessory) { 124 mLogger.log("USB accessory detached: " + accessory); 125 if (mConnected && accessory.equals(mAccessory)) { 126 disconnect(); 127 } 128 } 129 connect(UsbAccessory accessory)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 disconnect()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 startServices()181 private void startServices() { 182 mDisplaySourceService = new DisplaySourceService(this, mTransport, mPresenter); 183 mDisplaySourceService.start(); 184 } 185 stopServices()186 private void stopServices() { 187 if (mDisplaySourceService != null) { 188 mDisplaySourceService.stop(); 189 mDisplaySourceService = null; 190 } 191 } 192 isSink(UsbAccessory accessory)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 log(final String message)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 onReceive(Context context, Intent intent)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 onDisplayAdded(Display display)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 onDisplayRemoved(Display display)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