18f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown/*
28f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Copyright (C) 2013 The Android Open Source Project
38f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown *
48f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
58f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * you may not use this file except in compliance with the License.
68f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * You may obtain a copy of the License at
78f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown *
88f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
98f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown *
108f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * Unless required by applicable law or agreed to in writing, software
118f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
128f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * See the License for the specific language governing permissions and
148f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown * limitations under the License.
158f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown */
168f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
178f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownpackage com.android.accessorydisplay.source;
188f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
198f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport com.android.accessorydisplay.common.Logger;
208f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport com.android.accessorydisplay.source.presentation.DemoPresentation;
218f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
228f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.app.Activity;
238f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.app.PendingIntent;
248f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.content.BroadcastReceiver;
258f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.content.Context;
268f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.content.Intent;
278f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.content.IntentFilter;
288f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.hardware.usb.UsbAccessory;
298f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.hardware.usb.UsbManager;
308f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.os.Bundle;
318f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.os.ParcelFileDescriptor;
328f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.text.method.ScrollingMovementMethod;
338f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.util.Log;
348f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.view.Display;
358f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownimport android.widget.TextView;
368f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
378f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brownpublic class SourceActivity extends Activity {
388f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private static final String TAG = "SourceActivity";
398f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
408f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private static final String ACTION_USB_ACCESSORY_PERMISSION =
418f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            "com.android.accessorydisplay.source.ACTION_USB_ACCESSORY_PERMISSION";
428f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
438f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private static final String MANUFACTURER = "Android";
448f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private static final String MODEL = "Accessory Display";
458f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
468f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private UsbManager mUsbManager;
478f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private AccessoryReceiver mReceiver;
488f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private TextView mLogTextView;
498f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private Logger mLogger;
508f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private Presenter mPresenter;
518f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
528f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private boolean mConnected;
538f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private UsbAccessory mAccessory;
548f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private UsbAccessoryStreamTransport mTransport;
558f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
568f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private DisplaySourceService mDisplaySourceService;
578f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
588f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    @Override
598f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    protected void onCreate(Bundle savedInstanceState) {
608f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        super.onCreate(savedInstanceState);
618f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
628f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
638f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
648f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        setContentView(R.layout.source_activity);
658f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
6651efddbd3bb304de2dd47fa8cd1114ac555958bbAlan Viverette        mLogTextView = findViewById(R.id.logTextView);
678f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mLogTextView.setMovementMethod(ScrollingMovementMethod.getInstance());
688f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mLogger = new TextLogger();
698f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mPresenter = new Presenter();
708f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
718f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mLogger.log("Waiting for accessory display sink to be attached to USB...");
728f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
738f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        IntentFilter filter = new IntentFilter();
748f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
758f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
768f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        filter.addAction(ACTION_USB_ACCESSORY_PERMISSION);
778f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mReceiver = new AccessoryReceiver();
788f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        registerReceiver(mReceiver, filter);
798f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
808f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        Intent intent = getIntent();
818f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        if (intent.getAction().equals(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
828f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            UsbAccessory accessory =
838f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
848f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            if (accessory != null) {
858f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                onAccessoryAttached(accessory);
868f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            }
878f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        } else {
888f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            UsbAccessory[] accessories = mUsbManager.getAccessoryList();
898f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            if (accessories != null) {
908f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                for (UsbAccessory accessory : accessories) {
918f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    onAccessoryAttached(accessory);
928f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                }
938f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            }
948f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
958f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
968f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
978f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    @Override
988f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    protected void onDestroy() {
998f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        super.onDestroy();
1008f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1018f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        unregisterReceiver(mReceiver);
1028f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
1038f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1048f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    @Override
1058f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    protected void onResume() {
1068f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        super.onResume();
1078f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1088f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        //new DemoPresentation(this, getWindowManager().getDefaultDisplay()).show();
1098f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
1108f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1118f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    @Override
1128f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    protected void onPause() {
1138f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        super.onPause();
1148f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
1158f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1168f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private void onAccessoryAttached(UsbAccessory accessory) {
1178f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mLogger.log("USB accessory attached: " + accessory);
1188f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        if (!mConnected) {
1198f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            connect(accessory);
1208f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
1218f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
1228f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1238f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private void onAccessoryDetached(UsbAccessory accessory) {
1248f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mLogger.log("USB accessory detached: " + accessory);
1258f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        if (mConnected && accessory.equals(mAccessory)) {
1268f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            disconnect();
1278f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
1288f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
1298f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1308f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private void connect(UsbAccessory accessory) {
1318f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        if (!isSink(accessory)) {
1328f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mLogger.log("Not connecting to USB accessory because it is not an accessory display sink: "
1338f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    + accessory);
1348f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            return;
1358f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
1368f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1378f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        if (mConnected) {
1388f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            disconnect();
1398f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
1408f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1418f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        // Check whether we have permission to access the accessory.
1428f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        if (!mUsbManager.hasPermission(accessory)) {
1438f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mLogger.log("Prompting the user for access to the accessory.");
1448f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            Intent intent = new Intent(ACTION_USB_ACCESSORY_PERMISSION);
1458f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            intent.setPackage(getPackageName());
1468f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            PendingIntent pendingIntent = PendingIntent.getBroadcast(
1478f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
1488f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mUsbManager.requestPermission(accessory, pendingIntent);
1498f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            return;
1508f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
1518f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1528f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        // Open the accessory.
1538f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        ParcelFileDescriptor fd = mUsbManager.openAccessory(accessory);
1548f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        if (fd == null) {
1558f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mLogger.logError("Could not obtain accessory connection.");
1568f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            return;
1578f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
1588f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1598f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        // All set.
1608f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mLogger.log("Connected.");
1618f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mConnected = true;
1628f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mAccessory = accessory;
1638f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mTransport = new UsbAccessoryStreamTransport(mLogger, fd);
1648f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        startServices();
1658f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mTransport.startReading();
1668f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
1678f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1688f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private void disconnect() {
1698f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mLogger.log("Disconnecting from accessory: " + mAccessory);
1708f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        stopServices();
1718f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1728f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mLogger.log("Disconnected.");
1738f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mConnected = false;
1748f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mAccessory = null;
1758f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        if (mTransport != null) {
1768f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mTransport.close();
1778f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mTransport = null;
1788f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
1798f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
1808f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1818f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private void startServices() {
1828f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mDisplaySourceService = new DisplaySourceService(this, mTransport, mPresenter);
1838f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        mDisplaySourceService.start();
1848f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
1858f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1868f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private void stopServices() {
1878f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        if (mDisplaySourceService != null) {
1888f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mDisplaySourceService.stop();
1898f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mDisplaySourceService = null;
1908f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
1918f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
1928f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1938f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    private static boolean isSink(UsbAccessory accessory) {
1948f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        return MANUFACTURER.equals(accessory.getManufacturer())
1958f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                && MODEL.equals(accessory.getModel());
1968f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
1978f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
1988f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    class TextLogger extends Logger {
1998f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        @Override
2008f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        public void log(final String message) {
2018f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            Log.d(TAG, message);
2028f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
2038f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mLogTextView.post(new Runnable() {
2048f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                @Override
2058f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                public void run() {
2068f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    mLogTextView.append(message);
2078f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    mLogTextView.append("\n");
2088f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                }
2098f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            });
2108f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
2118f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
2128f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
2138f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    class AccessoryReceiver extends BroadcastReceiver {
2148f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        @Override
2158f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        public void onReceive(Context context, Intent intent) {
2168f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            UsbAccessory accessory = intent.<UsbAccessory>getParcelableExtra(
2178f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    UsbManager.EXTRA_ACCESSORY);
2188f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            if (accessory != null) {
2198f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                String action = intent.getAction();
2208f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                if (action.equals(UsbManager.ACTION_USB_ACCESSORY_ATTACHED)) {
2218f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    onAccessoryAttached(accessory);
2228f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                } else if (action.equals(UsbManager.ACTION_USB_ACCESSORY_DETACHED)) {
2238f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    onAccessoryDetached(accessory);
2248f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                } else if (action.equals(ACTION_USB_ACCESSORY_PERMISSION)) {
2258f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
2268f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                        mLogger.log("Accessory permission granted: " + accessory);
2278f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                        onAccessoryAttached(accessory);
2288f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    } else {
2298f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                        mLogger.logError("Accessory permission denied: " + accessory);
2308f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                    }
2318f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                }
2328f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            }
2338f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
2348f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
2358f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
2368f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    class Presenter implements DisplaySourceService.Callbacks {
2378f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        private DemoPresentation mPresentation;
2388f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
2398f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        @Override
2408f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        public void onDisplayAdded(Display display) {
2418f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mLogger.log("Accessory display added: " + display);
2428f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
2438f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mPresentation = new DemoPresentation(SourceActivity.this, display, mLogger);
2448f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mPresentation.show();
2458f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
2468f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
2478f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        @Override
2488f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        public void onDisplayRemoved(Display display) {
2498f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            mLogger.log("Accessory display removed: " + display);
2508f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown
2518f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            if (mPresentation != null) {
2528f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                mPresentation.dismiss();
2538f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown                mPresentation = null;
2548f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown            }
2558f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown        }
2568f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown    }
2578f3b1307678fcd1896c7fb8ba4cc20553dc032e8Jeff Brown}
258