blob: 9cf6ee7c91d5baa283f9ad974e48e3ed5f7b2794 [file] [log] [blame]
/*
* Copyright (C) 2018 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.frameworks.perftests.am.util;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
* TimeReceiver will listen for any messages containing a timestamp by starting a BroadcastReceiver
* which listens for Intents with the SendTime.ACTION_SEND_TIME action.
*/
public class TimeReceiver {
private static final String TAG = TimeReceiver.class.getSimpleName();
private static final long DEFAULT_RECEIVE_TIME_TIMEOUT_MILLIS = 10000L;
private BlockingQueue<ReceivedMessage> mQueue = new LinkedBlockingQueue<>();
private static class ReceivedMessage {
private final String mReceivedMessageType;
private final long mReceivedTimeNs;
public ReceivedMessage(String receivedMessageType, long receivedTimeNs) {
mReceivedMessageType = receivedMessageType;
mReceivedTimeNs = receivedTimeNs;
}
}
public Bundle createReceiveTimeExtraBinder() {
Bundle extras = new Bundle();
extras.putBinder(Constants.EXTRA_RECEIVER_CALLBACK, new ITimeReceiverCallback.Stub() {
@Override
public void sendTime(String type, long timeNs) throws RemoteException {
if (type == null) {
throw new RuntimeException("receivedType is null");
}
if (timeNs < 0) {
throw new RuntimeException(
"receivedTime is negative/non-existant: " + timeNs);
}
Log.i(TAG, type + " " + timeNs);
mQueue.add(new ReceivedMessage(type, timeNs));
}
});
return extras;
}
public long getReceivedTimeNs(String type) {
return getReceivedTimeNs(type, DEFAULT_RECEIVE_TIME_TIMEOUT_MILLIS);
}
/**
* Returns a received timestamp with the given type tag. Will throw away any messages with a
* different type tag. If it times out, a RuntimeException is thrown.
*/
public long getReceivedTimeNs(String type, long timeoutMs) {
ReceivedMessage message;
long endTimeNs = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(timeoutMs);
do {
long curTimeNs = System.nanoTime();
if (curTimeNs > endTimeNs) {
throw new RuntimeException("Timed out when listening for a time: " + type);
}
try {
Log.i(TAG, "waiting for message " + type);
message = mQueue.poll(endTimeNs - curTimeNs, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
if (message == null) {
throw new RuntimeException("Timed out when listening for a time: " + type);
}
Log.i(TAG, "got message " + message.mReceivedMessageType);
if (!type.equals(message.mReceivedMessageType)) {
Log.i(TAG, String.format("Expected type \"%s\", got \"%s\" (%d), skipping", type,
message.mReceivedMessageType, message.mReceivedTimeNs));
}
} while (!type.equals(message.mReceivedMessageType));
return message.mReceivedTimeNs;
}
/**
* Clears the message queue.
*/
public void clear() {
mQueue.clear();
}
}