| /* |
| * Copyright (C) 2013 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 com.android.accessorydisplay.source; |
| |
| import com.android.accessorydisplay.common.Logger; |
| import com.android.accessorydisplay.source.presentation.DemoPresentation; |
| |
| import android.app.Activity; |
| import android.app.PendingIntent; |
| import android.content.BroadcastReceiver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.hardware.usb.UsbAccessory; |
| import android.hardware.usb.UsbManager; |
| import android.os.Bundle; |
| import android.os.ParcelFileDescriptor; |
| import android.text.method.ScrollingMovementMethod; |
| import android.util.Log; |
| import android.view.Display; |
| import android.widget.TextView; |
| |
| public class SourceActivity extends Activity { |
| private static final String TAG = "SourceActivity"; |
| |
| private static final String ACTION_USB_ACCESSORY_PERMISSION = |
| "com.android.accessorydisplay.source.ACTION_USB_ACCESSORY_PERMISSION"; |
| |
| private static final String MANUFACTURER = "Android"; |
| private static final String MODEL = "Accessory Display"; |
| |
| private UsbManager mUsbManager; |
| private AccessoryReceiver mReceiver; |
| private TextView mLogTextView; |
| private Logger mLogger; |
| private Presenter mPresenter; |
| |
| private boolean mConnected; |
| private UsbAccessory mAccessory; |
| private UsbAccessoryStreamTransport mTransport; |
| |
| private DisplaySourceService mDisplaySourceService; |
| |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| |
| mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE); |
| |
| setContentView(R.layout.source_activity); |
| |
| mLogTextView = (TextView) findViewById(R.id.logTextView); |
| mLogTextView.setMovementMethod(ScrollingMovementMethod.getInstance()); |
| mLogger = new TextLogger(); |
| mPresenter = new Presenter(); |
| |
| mLogger.log("Waiting for accessory display sink to be attached to USB..."); |
| |
| IntentFilter filter = new IntentFilter(); |
| filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED); |
| filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED); |
| filter.addAction(ACTION_USB_ACCESSORY_PERMISSION); |
| mReceiver = new AccessoryReceiver(); |
| registerReceiver(mReceiver, filter); |
| |
| Intent intent = getIntent(); |
| if (intent.getAction().equals(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) { |
| UsbAccessory accessory = |
| (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); |
| if (accessory != null) { |
| onAccessoryAttached(accessory); |
| } |
| } else { |
| UsbAccessory[] accessories = mUsbManager.getAccessoryList(); |
| if (accessories != null) { |
| for (UsbAccessory accessory : accessories) { |
| onAccessoryAttached(accessory); |
| } |
| } |
| } |
| } |
| |
| @Override |
| protected void onDestroy() { |
| super.onDestroy(); |
| |
| unregisterReceiver(mReceiver); |
| } |
| |
| @Override |
| protected void onResume() { |
| super.onResume(); |
| |
| //new DemoPresentation(this, getWindowManager().getDefaultDisplay()).show(); |
| } |
| |
| @Override |
| protected void onPause() { |
| super.onPause(); |
| } |
| |
| private void onAccessoryAttached(UsbAccessory accessory) { |
| mLogger.log("USB accessory attached: " + accessory); |
| if (!mConnected) { |
| connect(accessory); |
| } |
| } |
| |
| private void onAccessoryDetached(UsbAccessory accessory) { |
| mLogger.log("USB accessory detached: " + accessory); |
| if (mConnected && accessory.equals(mAccessory)) { |
| disconnect(); |
| } |
| } |
| |
| private void connect(UsbAccessory accessory) { |
| if (!isSink(accessory)) { |
| mLogger.log("Not connecting to USB accessory because it is not an accessory display sink: " |
| + accessory); |
| return; |
| } |
| |
| if (mConnected) { |
| disconnect(); |
| } |
| |
| // Check whether we have permission to access the accessory. |
| if (!mUsbManager.hasPermission(accessory)) { |
| mLogger.log("Prompting the user for access to the accessory."); |
| Intent intent = new Intent(ACTION_USB_ACCESSORY_PERMISSION); |
| intent.setPackage(getPackageName()); |
| PendingIntent pendingIntent = PendingIntent.getBroadcast( |
| this, 0, intent, PendingIntent.FLAG_ONE_SHOT); |
| mUsbManager.requestPermission(accessory, pendingIntent); |
| return; |
| } |
| |
| // Open the accessory. |
| ParcelFileDescriptor fd = mUsbManager.openAccessory(accessory); |
| if (fd == null) { |
| mLogger.logError("Could not obtain accessory connection."); |
| return; |
| } |
| |
| // All set. |
| mLogger.log("Connected."); |
| mConnected = true; |
| mAccessory = accessory; |
| mTransport = new UsbAccessoryStreamTransport(mLogger, fd); |
| startServices(); |
| mTransport.startReading(); |
| } |
| |
| private void disconnect() { |
| mLogger.log("Disconnecting from accessory: " + mAccessory); |
| stopServices(); |
| |
| mLogger.log("Disconnected."); |
| mConnected = false; |
| mAccessory = null; |
| if (mTransport != null) { |
| mTransport.close(); |
| mTransport = null; |
| } |
| } |
| |
| private void startServices() { |
| mDisplaySourceService = new DisplaySourceService(this, mTransport, mPresenter); |
| mDisplaySourceService.start(); |
| } |
| |
| private void stopServices() { |
| if (mDisplaySourceService != null) { |
| mDisplaySourceService.stop(); |
| mDisplaySourceService = null; |
| } |
| } |
| |
| private static boolean isSink(UsbAccessory accessory) { |
| return MANUFACTURER.equals(accessory.getManufacturer()) |
| && MODEL.equals(accessory.getModel()); |
| } |
| |
| class TextLogger extends Logger { |
| @Override |
| public void log(final String message) { |
| Log.d(TAG, message); |
| |
| mLogTextView.post(new Runnable() { |
| @Override |
| public void run() { |
| mLogTextView.append(message); |
| mLogTextView.append("\n"); |
| } |
| }); |
| } |
| } |
| |
| class AccessoryReceiver extends BroadcastReceiver { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| UsbAccessory accessory = intent.<UsbAccessory>getParcelableExtra( |
| UsbManager.EXTRA_ACCESSORY); |
| if (accessory != null) { |
| String action = intent.getAction(); |
| if (action.equals(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) { |
| onAccessoryAttached(accessory); |
| } else if (action.equals(UsbManager.ACTION_USB_ACCESSORY_DETACHED)) { |
| onAccessoryDetached(accessory); |
| } else if (action.equals(ACTION_USB_ACCESSORY_PERMISSION)) { |
| if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { |
| mLogger.log("Accessory permission granted: " + accessory); |
| onAccessoryAttached(accessory); |
| } else { |
| mLogger.logError("Accessory permission denied: " + accessory); |
| } |
| } |
| } |
| } |
| } |
| |
| class Presenter implements DisplaySourceService.Callbacks { |
| private DemoPresentation mPresentation; |
| |
| @Override |
| public void onDisplayAdded(Display display) { |
| mLogger.log("Accessory display added: " + display); |
| |
| mPresentation = new DemoPresentation(SourceActivity.this, display, mLogger); |
| mPresentation.show(); |
| } |
| |
| @Override |
| public void onDisplayRemoved(Display display) { |
| mLogger.log("Accessory display removed: " + display); |
| |
| if (mPresentation != null) { |
| mPresentation.dismiss(); |
| mPresentation = null; |
| } |
| } |
| } |
| } |