Merge "Several changes to VDM Demo apps" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
a12aab843d
@@ -18,6 +18,7 @@
|
|||||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
|
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
android:screenOrientation="portrait"
|
||||||
android:exported="true">
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import android.os.Handler;
|
|||||||
import android.os.HandlerThread;
|
import android.os.HandlerThread;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.GuardedBy;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext;
|
import dagger.hilt.android.qualifiers.ApplicationContext;
|
||||||
@@ -48,7 +49,6 @@ import java.net.Inet6Address;
|
|||||||
import java.net.ServerSocket;
|
import java.net.ServerSocket;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
@@ -68,6 +68,9 @@ public class ConnectionManager {
|
|||||||
@ApplicationContext private final Context mContext;
|
@ApplicationContext private final Context mContext;
|
||||||
private final ConnectivityManager mConnectivityManager;
|
private final ConnectivityManager mConnectivityManager;
|
||||||
private final Handler mBackgroundHandler;
|
private final Handler mBackgroundHandler;
|
||||||
|
private final Object mSessionLock = new Object();
|
||||||
|
|
||||||
|
@GuardedBy("mSessionLock")
|
||||||
private DiscoverySession mDiscoverySession;
|
private DiscoverySession mDiscoverySession;
|
||||||
|
|
||||||
/** Simple data structure to allow clients to query the current status. */
|
/** Simple data structure to allow clients to query the current status. */
|
||||||
@@ -76,6 +79,7 @@ public class ConnectionManager {
|
|||||||
public boolean connected = false;
|
public boolean connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GuardedBy("mSessionLock")
|
||||||
private final ConnectionStatus mConnectionStatus = new ConnectionStatus();
|
private final ConnectionStatus mConnectionStatus = new ConnectionStatus();
|
||||||
|
|
||||||
/** Simple callback to notify connection and disconnection events. */
|
/** Simple callback to notify connection and disconnection events. */
|
||||||
@@ -93,8 +97,8 @@ public class ConnectionManager {
|
|||||||
default void onError(String message) {}
|
default void onError(String message) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<ConnectionCallback> mConnectionCallbacks =
|
@GuardedBy("mConnectionCallbacks")
|
||||||
Collections.synchronizedList(new ArrayList<>());
|
private final List<ConnectionCallback> mConnectionCallbacks = new ArrayList<>();
|
||||||
|
|
||||||
private final RemoteIo.StreamClosedCallback mStreamClosedCallback = this::disconnect;
|
private final RemoteIo.StreamClosedCallback mStreamClosedCallback = this::disconnect;
|
||||||
|
|
||||||
@@ -115,22 +119,28 @@ public class ConnectionManager {
|
|||||||
|
|
||||||
/** Registers a listener for connection events. */
|
/** Registers a listener for connection events. */
|
||||||
public void addConnectionCallback(ConnectionCallback callback) {
|
public void addConnectionCallback(ConnectionCallback callback) {
|
||||||
|
synchronized (mConnectionCallbacks) {
|
||||||
mConnectionCallbacks.add(callback);
|
mConnectionCallbacks.add(callback);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Registers a listener for connection events. */
|
/** Registers a listener for connection events. */
|
||||||
public void removeConnectionCallback(ConnectionCallback callback) {
|
public void removeConnectionCallback(ConnectionCallback callback) {
|
||||||
|
synchronized (mConnectionCallbacks) {
|
||||||
mConnectionCallbacks.remove(callback);
|
mConnectionCallbacks.remove(callback);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns the current connection status. */
|
/** Returns the current connection status. */
|
||||||
public ConnectionStatus getConnectionStatus() {
|
public ConnectionStatus getConnectionStatus() {
|
||||||
|
synchronized (mSessionLock) {
|
||||||
return mConnectionStatus;
|
return mConnectionStatus;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Publish a local service so remote devices can discover this device. */
|
/** Publish a local service so remote devices can discover this device. */
|
||||||
public void startHostSession() {
|
public void startHostSession() {
|
||||||
if (mConnectionStatus.connected) {
|
if (isConnected()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var unused = createSession().thenAccept(wifiAwareSession -> wifiAwareSession.publish(
|
var unused = createSession().thenAccept(wifiAwareSession -> wifiAwareSession.publish(
|
||||||
@@ -141,7 +151,7 @@ public class ConnectionManager {
|
|||||||
|
|
||||||
/** Looks for published services from remote devices and subscribes to them. */
|
/** Looks for published services from remote devices and subscribes to them. */
|
||||||
public void startClientSession() {
|
public void startClientSession() {
|
||||||
if (mConnectionStatus.connected) {
|
if (isConnected()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var unused = createSession().thenAccept(wifiAwareSession -> wifiAwareSession.subscribe(
|
var unused = createSession().thenAccept(wifiAwareSession -> wifiAwareSession.subscribe(
|
||||||
@@ -150,6 +160,12 @@ public class ConnectionManager {
|
|||||||
mBackgroundHandler));
|
mBackgroundHandler));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isConnected() {
|
||||||
|
synchronized (mSessionLock) {
|
||||||
|
return mConnectionStatus.connected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private CompletableFuture<WifiAwareSession> createSession() {
|
private CompletableFuture<WifiAwareSession> createSession() {
|
||||||
CompletableFuture<WifiAwareSession> wifiAwareSessionFuture = new CompletableFuture<>();
|
CompletableFuture<WifiAwareSession> wifiAwareSessionFuture = new CompletableFuture<>();
|
||||||
WifiAwareManager wifiAwareManager = mContext.getSystemService(WifiAwareManager.class);
|
WifiAwareManager wifiAwareManager = mContext.getSystemService(WifiAwareManager.class);
|
||||||
@@ -184,55 +200,75 @@ public class ConnectionManager {
|
|||||||
|
|
||||||
/** Explicitly terminate any existing connection. */
|
/** Explicitly terminate any existing connection. */
|
||||||
public void disconnect() {
|
public void disconnect() {
|
||||||
|
synchronized (mSessionLock) {
|
||||||
if (mDiscoverySession != null) {
|
if (mDiscoverySession != null) {
|
||||||
mDiscoverySession.close();
|
mDiscoverySession.close();
|
||||||
mDiscoverySession = null;
|
mDiscoverySession = null;
|
||||||
}
|
}
|
||||||
mConnectionStatus.remoteDeviceName = null;
|
mConnectionStatus.remoteDeviceName = null;
|
||||||
mConnectionStatus.connected = false;
|
mConnectionStatus.connected = false;
|
||||||
|
synchronized (mConnectionCallbacks) {
|
||||||
for (ConnectionCallback callback : mConnectionCallbacks) {
|
for (ConnectionCallback callback : mConnectionCallbacks) {
|
||||||
callback.onDisconnected();
|
callback.onDisconnected();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onSocketAvailable(Socket socket) throws IOException {
|
private void onSocketAvailable(Socket socket) throws IOException {
|
||||||
mRemoteIo.initialize(socket.getInputStream(), mStreamClosedCallback);
|
mRemoteIo.initialize(socket.getInputStream(), mStreamClosedCallback);
|
||||||
mRemoteIo.initialize(socket.getOutputStream(), mStreamClosedCallback);
|
mRemoteIo.initialize(socket.getOutputStream(), mStreamClosedCallback);
|
||||||
|
synchronized (mSessionLock) {
|
||||||
mConnectionStatus.connected = true;
|
mConnectionStatus.connected = true;
|
||||||
|
synchronized (mConnectionCallbacks) {
|
||||||
for (ConnectionCallback callback : mConnectionCallbacks) {
|
for (ConnectionCallback callback : mConnectionCallbacks) {
|
||||||
callback.onConnected(mConnectionStatus.remoteDeviceName);
|
callback.onConnected(mConnectionStatus.remoteDeviceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void onError(String message) {
|
private void onError(String message) {
|
||||||
Log.e(TAG, "Error: " + message);
|
Log.e(TAG, "Error: " + message);
|
||||||
|
synchronized (mConnectionCallbacks) {
|
||||||
for (ConnectionCallback callback : mConnectionCallbacks) {
|
for (ConnectionCallback callback : mConnectionCallbacks) {
|
||||||
callback.onError(message);
|
callback.onError(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class VdmDiscoverySessionCallback extends DiscoverySessionCallback {
|
private class VdmDiscoverySessionCallback extends DiscoverySessionCallback {
|
||||||
|
|
||||||
|
@GuardedBy("mSessionLock")
|
||||||
private NetworkCallback mNetworkCallback;
|
private NetworkCallback mNetworkCallback;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSessionTerminated() {
|
public void onSessionTerminated() {
|
||||||
disconnect();
|
disconnect();
|
||||||
|
synchronized (mSessionLock) {
|
||||||
if (mNetworkCallback != null) {
|
if (mNetworkCallback != null) {
|
||||||
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
|
mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sendLocalEndpointId(PeerHandle peerHandle) {
|
void sendLocalEndpointId(PeerHandle peerHandle) {
|
||||||
|
synchronized (mSessionLock) {
|
||||||
mDiscoverySession.sendMessage(peerHandle, 0, getLocalEndpointId().getBytes());
|
mDiscoverySession.sendMessage(peerHandle, 0, getLocalEndpointId().getBytes());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void onConnecting(byte[] remoteDeviceName) {
|
void onConnecting(byte[] remoteDeviceName) {
|
||||||
|
synchronized (mSessionLock) {
|
||||||
mConnectionStatus.remoteDeviceName = new String(remoteDeviceName);
|
mConnectionStatus.remoteDeviceName = new String(remoteDeviceName);
|
||||||
Log.e(TAG, "Connecting to " + mConnectionStatus.remoteDeviceName);
|
Log.e(TAG, "Connecting to " + mConnectionStatus.remoteDeviceName);
|
||||||
|
synchronized (mConnectionCallbacks) {
|
||||||
for (ConnectionCallback callback : mConnectionCallbacks) {
|
for (ConnectionCallback callback : mConnectionCallbacks) {
|
||||||
callback.onConnecting(mConnectionStatus.remoteDeviceName);
|
callback.onConnecting(mConnectionStatus.remoteDeviceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void requestNetwork(
|
void requestNetwork(
|
||||||
PeerHandle peerHandle, Optional<Integer> port, NetworkCallback networkCallback) {
|
PeerHandle peerHandle, Optional<Integer> port, NetworkCallback networkCallback) {
|
||||||
@@ -246,8 +282,10 @@ public class ConnectionManager {
|
|||||||
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
|
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE)
|
||||||
.setNetworkSpecifier(networkSpecifierBuilder.build())
|
.setNetworkSpecifier(networkSpecifierBuilder.build())
|
||||||
.build();
|
.build();
|
||||||
|
synchronized (mSessionLock) {
|
||||||
mNetworkCallback = networkCallback;
|
mNetworkCallback = networkCallback;
|
||||||
mConnectivityManager.requestNetwork(networkRequest, networkCallback);
|
mConnectivityManager.requestNetwork(networkRequest, mNetworkCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,12 +293,14 @@ public class ConnectionManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPublishStarted(@NonNull PublishDiscoverySession session) {
|
public void onPublishStarted(@NonNull PublishDiscoverySession session) {
|
||||||
|
synchronized (mSessionLock) {
|
||||||
mDiscoverySession = session;
|
mDiscoverySession = session;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
|
public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
|
||||||
if (mConnectionStatus.connected) {
|
if (isConnected()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,8 +324,10 @@ public class ConnectionManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSubscribeStarted(@NonNull SubscribeDiscoverySession session) {
|
public void onSubscribeStarted(@NonNull SubscribeDiscoverySession session) {
|
||||||
|
synchronized (mSessionLock) {
|
||||||
mDiscoverySession = session;
|
mDiscoverySession = session;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onServiceDiscovered(
|
public void onServiceDiscovered(
|
||||||
@@ -295,7 +337,7 @@ public class ConnectionManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
|
public void onMessageReceived(PeerHandle peerHandle, byte[] message) {
|
||||||
if (mConnectionStatus.connected) {
|
if (isConnected()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
onConnecting(message);
|
onConnecting(message);
|
||||||
@@ -316,7 +358,7 @@ public class ConnectionManager {
|
|||||||
@Override
|
@Override
|
||||||
public void onCapabilitiesChanged(@NonNull Network network,
|
public void onCapabilitiesChanged(@NonNull Network network,
|
||||||
@NonNull NetworkCapabilities networkCapabilities) {
|
@NonNull NetworkCapabilities networkCapabilities) {
|
||||||
if (mConnectionStatus.connected) {
|
if (isConnected()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,12 +21,13 @@ import android.os.HandlerThread;
|
|||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.annotation.GuardedBy;
|
||||||
|
|
||||||
import com.example.android.vdmdemo.common.RemoteEventProto.RemoteEvent;
|
import com.example.android.vdmdemo.common.RemoteEventProto.RemoteEvent;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
@@ -44,12 +45,16 @@ public class RemoteIo {
|
|||||||
void onStreamClosed();
|
void onStreamClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final Object mLock = new Object();
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
private OutputStream mOutputStream = null;
|
private OutputStream mOutputStream = null;
|
||||||
|
|
||||||
private StreamClosedCallback mOutputStreamClosedCallback = null;
|
private StreamClosedCallback mOutputStreamClosedCallback = null;
|
||||||
private final Handler mSendMessageHandler;
|
private final Handler mSendMessageHandler;
|
||||||
|
|
||||||
private final Map<Object, MessageConsumer> mMessageConsumers =
|
@GuardedBy("mMessageConsumers")
|
||||||
Collections.synchronizedMap(new ArrayMap<>());
|
private final Map<Object, MessageConsumer> mMessageConsumers = new ArrayMap<>();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
RemoteIo() {
|
RemoteIo() {
|
||||||
@@ -60,50 +65,45 @@ public class RemoteIo {
|
|||||||
|
|
||||||
@SuppressWarnings("ThreadPriorityCheck")
|
@SuppressWarnings("ThreadPriorityCheck")
|
||||||
void initialize(InputStream inputStream, StreamClosedCallback inputStreamClosedCallback) {
|
void initialize(InputStream inputStream, StreamClosedCallback inputStreamClosedCallback) {
|
||||||
Thread t = new Thread(() -> {
|
Thread t = new Thread(new ReceiverRunnable(inputStream, inputStreamClosedCallback));
|
||||||
try {
|
|
||||||
while (true) {
|
|
||||||
RemoteEvent event = RemoteEvent.parseDelimitedFrom(inputStream);
|
|
||||||
if (event == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mMessageConsumers.values().forEach(consumer -> {
|
|
||||||
if (consumer != null) {
|
|
||||||
consumer.accept(event);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(TAG, "Failed to obtain event: " + e);
|
|
||||||
}
|
|
||||||
inputStreamClosedCallback.onStreamClosed();
|
|
||||||
});
|
|
||||||
t.setPriority(Thread.MAX_PRIORITY);
|
t.setPriority(Thread.MAX_PRIORITY);
|
||||||
t.start();
|
t.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized void initialize(
|
void initialize(
|
||||||
OutputStream outputStream, StreamClosedCallback outputStreamClosedCallback) {
|
OutputStream outputStream, StreamClosedCallback outputStreamClosedCallback) {
|
||||||
|
synchronized (mLock) {
|
||||||
mOutputStream = outputStream;
|
mOutputStream = outputStream;
|
||||||
mOutputStreamClosedCallback = outputStreamClosedCallback;
|
mOutputStreamClosedCallback = outputStreamClosedCallback;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Registers a consumer for processing events coming from the remote device. */
|
/** Registers a consumer for processing events coming from the remote device. */
|
||||||
public void addMessageConsumer(Consumer<RemoteEvent> consumer) {
|
public void addMessageConsumer(Consumer<RemoteEvent> consumer) {
|
||||||
|
synchronized (mMessageConsumers) {
|
||||||
mMessageConsumers.put(consumer, new MessageConsumer(consumer));
|
mMessageConsumers.put(consumer, new MessageConsumer(consumer));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Unregisters a previously registered message consumer. */
|
/** Unregisters a previously registered message consumer. */
|
||||||
public void removeMessageConsumer(Consumer<RemoteEvent> consumer) {
|
public void removeMessageConsumer(Consumer<RemoteEvent> consumer) {
|
||||||
|
synchronized (mMessageConsumers) {
|
||||||
if (mMessageConsumers.remove(consumer) == null) {
|
if (mMessageConsumers.remove(consumer) == null) {
|
||||||
Log.w(TAG, "Failed to remove message consumer.");
|
Log.w(TAG, "Failed to remove message consumer.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Sends an event to the remote device. */
|
/** Sends an event to the remote device. */
|
||||||
public synchronized void sendMessage(RemoteEvent event) {
|
public void sendMessage(RemoteEvent event) {
|
||||||
if (mOutputStream != null) {
|
synchronized (mLock) {
|
||||||
|
if (mOutputStream == null) {
|
||||||
|
Log.e(TAG, "Failed to send event, RemoteIO not initialized.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
mSendMessageHandler.post(() -> {
|
mSendMessageHandler.post(() -> {
|
||||||
|
synchronized (mLock) {
|
||||||
try {
|
try {
|
||||||
event.writeDelimitedTo(mOutputStream);
|
event.writeDelimitedTo(mOutputStream);
|
||||||
mOutputStream.flush();
|
mOutputStream.flush();
|
||||||
@@ -111,9 +111,36 @@ public class RemoteIo {
|
|||||||
mOutputStream = null;
|
mOutputStream = null;
|
||||||
mOutputStreamClosedCallback.onStreamClosed();
|
mOutputStreamClosedCallback.onStreamClosed();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
}
|
||||||
Log.e(TAG, "Failed to send event, RemoteIO not initialized.");
|
|
||||||
|
private class ReceiverRunnable implements Runnable {
|
||||||
|
|
||||||
|
private final InputStream mInputStream;
|
||||||
|
private final StreamClosedCallback mInputStreamClosedCallback;
|
||||||
|
|
||||||
|
ReceiverRunnable(InputStream inputStream, StreamClosedCallback inputStreamClosedCallback) {
|
||||||
|
mInputStream = inputStream;
|
||||||
|
mInputStreamClosedCallback = inputStreamClosedCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
RemoteEvent event = RemoteEvent.parseDelimitedFrom(mInputStream);
|
||||||
|
if (event == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
synchronized (mMessageConsumers) {
|
||||||
|
mMessageConsumers.values().forEach(consumer -> consumer.accept(event));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Failed to obtain event: " + e);
|
||||||
|
}
|
||||||
|
mInputStreamClosedCallback.onStreamClosed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ function die() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function run_cmd_or_die() {
|
function run_cmd_or_die() {
|
||||||
"${@}" > /dev/null 2>&1 || die "Command failed: ${*}"
|
"${@}" > /dev/null || die "Command failed: ${*}"
|
||||||
}
|
}
|
||||||
|
|
||||||
function select_device() {
|
function select_device() {
|
||||||
@@ -30,6 +30,13 @@ function select_device() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function install_app() {
|
||||||
|
if ! adb -s "${1}" install -r -d -g "${2}" > /dev/null 2>&1; then
|
||||||
|
adb -s "${1}" uninstall "com.example.android.vdmdemo.${3}" > /dev/null 2>&1
|
||||||
|
run_cmd_or_die adb -s "${1}" install -r -d -g "${2}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
[[ -f build/make/envsetup.sh ]] || die "Run this script from the root of the tree."
|
[[ -f build/make/envsetup.sh ]] || die "Run this script from the root of the tree."
|
||||||
|
|
||||||
DEVICE_COUNT=$(adb devices -l | tail -n +2 | head -n -1 | wc -l)
|
DEVICE_COUNT=$(adb devices -l | tail -n +2 | head -n -1 | wc -l)
|
||||||
@@ -41,36 +48,16 @@ HOST_SERIAL=""
|
|||||||
CLIENT_SERIAL=""
|
CLIENT_SERIAL=""
|
||||||
|
|
||||||
echo
|
echo
|
||||||
if ((DEVICE_COUNT > 1)); then
|
echo "Available devices:"
|
||||||
echo "Multiple devices found:"
|
for i in "${!DEVICE_SERIALS[@]}"; do
|
||||||
for i in "${!DEVICE_SERIALS[@]}"; do
|
|
||||||
echo -e "${i}: ${DEVICE_SERIALS[${i}]}\t${DEVICE_NAMES[${i}]}"
|
echo -e "${i}: ${DEVICE_SERIALS[${i}]}\t${DEVICE_NAMES[${i}]}"
|
||||||
done
|
done
|
||||||
echo "${DEVICE_COUNT}: Do not install this app"
|
echo "${DEVICE_COUNT}: Do not install this app"
|
||||||
echo
|
echo
|
||||||
select_device "VDM Host"
|
select_device "VDM Host"
|
||||||
HOST_INDEX=$?
|
HOST_INDEX=$?
|
||||||
select_device "VDM Client"
|
select_device "VDM Client"
|
||||||
CLIENT_INDEX=$?
|
CLIENT_INDEX=$?
|
||||||
else
|
|
||||||
DEVICE_SERIAL=${DEVICE_SERIALS[0]}
|
|
||||||
DEVICE_NAME="${DEVICE_SERIAL} ${DEVICE_NAMES[0]}"
|
|
||||||
cat << EOF
|
|
||||||
0: VDM Host app
|
|
||||||
1: VDM Client app
|
|
||||||
2: All
|
|
||||||
3: None
|
|
||||||
|
|
||||||
EOF
|
|
||||||
while :; do
|
|
||||||
read -r -p "Select apps to install to ${DEVICE_NAME} (0-3): " INDEX
|
|
||||||
( [[ "${INDEX}" =~ ^[0-9]+$ ]] && ((INDEX >= 0 && INDEX <= 3)) ) || continue;
|
|
||||||
((INDEX == 3)) && exit 0
|
|
||||||
((INDEX != 0 && INDEX != 2)) && HOST_INDEX=DEVICE_COUNT
|
|
||||||
((INDEX != 1 && INDEX != 2)) && CLIENT_INDEX=DEVICE_COUNT
|
|
||||||
break
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
echo
|
echo
|
||||||
|
|
||||||
if ((HOST_INDEX == DEVICE_COUNT)); then
|
if ((HOST_INDEX == DEVICE_COUNT)); then
|
||||||
@@ -103,15 +90,13 @@ UNBUNDLED_BUILD_SDKS_FROM_SOURCE=true m -j "${APKS_TO_BUILD}" || die "Build fail
|
|||||||
if [[ -n "${CLIENT_SERIAL}" ]]; then
|
if [[ -n "${CLIENT_SERIAL}" ]]; then
|
||||||
echo
|
echo
|
||||||
echo "Installing VdmClient.apk to ${CLIENT_NAME}..."
|
echo "Installing VdmClient.apk to ${CLIENT_NAME}..."
|
||||||
adb -s "${CLIENT_SERIAL}" uninstall com.example.android.vdmdemo.client > /dev/null 2>&1
|
install_app "${CLIENT_SERIAL}" "${OUT}/system/app/VdmClient/VdmClient.apk" client
|
||||||
run_cmd_or_die adb -s "${CLIENT_SERIAL}" install -r -d -g "${OUT}/system/app/VdmClient/VdmClient.apk"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -n "${HOST_SERIAL}" ]]; then
|
if [[ -n "${HOST_SERIAL}" ]]; then
|
||||||
echo
|
echo
|
||||||
echo "Installing VdmDemos.apk to ${HOST_NAME}..."
|
echo "Installing VdmDemos.apk to ${HOST_NAME}..."
|
||||||
adb -s "${HOST_SERIAL}" uninstall com.example.android.vdmdemo.demos > /dev/null 2>&1
|
install_app "${CLIENT_SERIAL}" "${OUT}/system/app/VdmDemos/VdmDemos.apk" demos
|
||||||
run_cmd_or_die adb -s "${HOST_SERIAL}" install -r -d -g "${OUT}/system/app/VdmDemos/VdmDemos.apk"
|
|
||||||
echo
|
echo
|
||||||
|
|
||||||
readonly PERM_BASENAME=com.example.android.vdmdemo.host.xml
|
readonly PERM_BASENAME=com.example.android.vdmdemo.host.xml
|
||||||
|
|||||||
Reference in New Issue
Block a user