Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8f3b1307 authored by Jeff Brown's avatar Jeff Brown
Browse files

Add test for streaming display contents to an accessory.

There are two applications: a source and a sink.
They should be installed on two separate Android devices.
Then connect the source device to the sink device using
a USB OTG cable.

Bug: 9192512
Change-Id: I99b552026684abbfd69cb13ab324e72fa16c36ab
parent a506a6ec
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
# 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.

LOCAL_PATH := $(call my-dir)

include $(call all-makefiles-under,$(LOCAL_PATH))
+50 −0
Original line number Diff line number Diff line
This directory contains sample code to test the use of virtual
displays created over an Android Open Accessories Protocol link.

--- DESCRIPTION ---

There are two applications with two distinct roles: a sink
and a source.

1. Sink Application

The role of the sink is to emulate an external display that happens
to be connected using the USB accessory protocol.  Think of it as
a monitor or video dock that the user will want to plug a phone into.

The sink application uses the UsbDevice APIs to receive connections
from the source device over USB.  The sink acts as a USB host
in this arrangement and will provide power to the source.

The sink application decodes encoded video from the source and
displays it in a SurfaceView.  The sink also injects passes touch
events to the source over USB HID.

2. Source Application

The role of the source is to present some content onto an external
display that happens to be attached over USB.  This is the typical
role that a phone or tablet might have when the user is trying to
play content to an external monitor.

The source application uses the UsbAccessory APIs to connect
to the sink device over USB.  The source acts as a USB peripheral
in this arrangement and will receive power from the sink.

The source application uses the DisplayManager APIs to create
a private virtual display which passes the framebuffer through
an encoder and streams the output to the sink over USB.  Then
the application opens a Presentation on the new virtual display
and shows a silly cube animation.

--- USAGE ---

These applications should be installed on two separate Android
devices which are then connected using a USB OTG cable.
Remember that the sink device is functioning as the USB host
so the USB OTG cable should be plugged directly into it.

When connected, the applications should automatically launch
on each device.  The source will then begin to project display
contents to the sink.
+23 −0
Original line number Diff line number Diff line
# 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.

LOCAL_PATH := $(call my-dir)

# Build the application.
include $(CLEAR_VARS)
LOCAL_MODULE := AccessoryDisplayCommon
LOCAL_MODULE_TAGS := tests
LOCAL_SDK_VERSION := current
LOCAL_SRC_FILES := $(call all-java-files-under, src)
include $(BUILD_STATIC_JAVA_LIBRARY)
+92 −0
Original line number Diff line number Diff line
/*
 * 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.common;

import java.nio.ByteBuffer;

/**
 * Maintains a bounded pool of buffers.  Attempts to acquire buffers beyond the maximum
 * count will block until other buffers are released.
 */
final class BufferPool {
    private final int mInitialBufferSize;
    private final int mMaxBufferSize;
    private final ByteBuffer[] mBuffers;
    private int mAllocated;
    private int mAvailable;

    public BufferPool(int initialBufferSize, int maxBufferSize, int maxBuffers) {
        mInitialBufferSize = initialBufferSize;
        mMaxBufferSize = maxBufferSize;
        mBuffers = new ByteBuffer[maxBuffers];
    }

    public ByteBuffer acquire(int needed) {
        synchronized (this) {
            for (;;) {
                if (mAvailable != 0) {
                    mAvailable -= 1;
                    return grow(mBuffers[mAvailable], needed);
                }

                if (mAllocated < mBuffers.length) {
                    mAllocated += 1;
                    return ByteBuffer.allocate(chooseCapacity(mInitialBufferSize, needed));
                }

                try {
                    wait();
                } catch (InterruptedException ex) {
                }
            }
        }
    }

    public void release(ByteBuffer buffer) {
        synchronized (this) {
            buffer.clear();
            mBuffers[mAvailable++] = buffer;
            notifyAll();
        }
    }

    public ByteBuffer grow(ByteBuffer buffer, int needed) {
        int capacity = buffer.capacity();
        if (capacity < needed) {
            final ByteBuffer oldBuffer = buffer;
            capacity = chooseCapacity(capacity, needed);
            buffer = ByteBuffer.allocate(capacity);
            oldBuffer.flip();
            buffer.put(oldBuffer);
        }
        return buffer;
    }

    private int chooseCapacity(int capacity, int needed) {
        while (capacity < needed) {
            capacity *= 2;
        }
        if (capacity > mMaxBufferSize) {
            if (needed > mMaxBufferSize) {
                throw new IllegalArgumentException("Requested size " + needed
                        + " is larger than maximum buffer size " + mMaxBufferSize + ".");
            }
            capacity = mMaxBufferSize;
        }
        return capacity;
    }
}
+25 −0
Original line number Diff line number Diff line
/*
 * 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.common;

public abstract class Logger {
    public abstract void log(String message);

    public void logError(String message) {
        log("ERROR: " + message);
    }
}
Loading