1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.google.android.chre.test.chqts; 17 18 import android.hardware.location.ContextHubInfo; 19 import android.hardware.location.ContextHubManager; 20 import android.hardware.location.NanoAppBinary; 21 22 import java.nio.ByteBuffer; 23 import java.nio.ByteOrder; 24 import java.util.Timer; 25 import java.util.TimerTask; 26 27 /** 28 * Checks that chreGetTime() is reasonable. 29 * 30 * We check that it's monotonically increasing, and mostly in line with 31 * the application processor's notion of time passing. 32 * 33 * Protocol: 34 * Host: GET_TIME, no data 35 * Nanoapp: CONTINUE, 64-bit timestamp (little endian) 36 * [2.5 second pause] 37 * Host: CONTINUE, no data 38 * Nanoapp: CONTINUE, 64-bit timestamp (little endian) 39 * [Host declares pass] 40 */ 41 public class ContextHubGetTimeTestExecutor extends ContextHubGeneralTestExecutor { 42 private static final ContextHubTestConstants.TestNames TEST_NAME = 43 ContextHubTestConstants.TestNames.GET_TIME; 44 45 // Since the CHRE timestamps are in nanoseconds, we do most of our times 46 // in nanoseconds here (although the Timer.schedule() only works with 47 // milliseconds; we elect for the shorter naming for our more common unit). 48 49 // 2.5 seconds 50 private static final long SLEEP_DURATION_MILLISECONDS = 2500; 51 private static final long SLEEP_DURATION_NS = 52 SLEEP_DURATION_MILLISECONDS * 1000 * 1000; 53 54 // We expect some degree of inconsistency between our host/CHRE 55 // transaction overheads, so we allow a healthy amount of tolerance 56 // here. This isn't a precision check, but should hopefully make 57 // sure the CHRE is within the right ballpark. 58 // 0.5 seconds 59 private static final long TOLERANCE_NS = 500 * 1000 * 1000; 60 61 private int mContinueCount = 0; 62 private long mFirstTimestamp; 63 64 private Timer mTimer = new Timer(); 65 ContextHubGetTimeTestExecutor(ContextHubManager manager, ContextHubInfo info, NanoAppBinary binary)66 public ContextHubGetTimeTestExecutor(ContextHubManager manager, ContextHubInfo info, 67 NanoAppBinary binary) { 68 super(manager, info, 69 new GeneralTestNanoApp(binary, ContextHubTestConstants.TestNames.GET_TIME)); 70 } 71 72 @Override handleMessageFromNanoApp(long nanoAppId, ContextHubTestConstants.MessageType type, byte[] data)73 protected void handleMessageFromNanoApp(long nanoAppId, 74 ContextHubTestConstants.MessageType type, byte[] data) { 75 if (type != ContextHubTestConstants.MessageType.CONTINUE) { 76 fail("Unexpected message type " + type); 77 return; 78 } 79 80 assertEquals("Expected exactly 8 bytes with CONTINUE message.", 81 8, data.length); 82 long timestamp = ByteBuffer.wrap(data) 83 .order(ByteOrder.LITTLE_ENDIAN) 84 .getLong(); 85 86 mContinueCount++; 87 if (mContinueCount == 1) { 88 mFirstTimestamp = timestamp; 89 // We perform our delay before the next message in a separate 90 // thread, so we're not stalling the ContextHubManager/Service 91 // from servicing any other messages or events. 92 mTimer.schedule(new TimerTask() { 93 @Override 94 public void run() { 95 byte[] emptyData = new byte[0]; 96 sendMessageToNanoAppOrFail(nanoAppId, 97 ContextHubTestConstants.MessageType.CONTINUE.asInt(), 98 emptyData); 99 } 100 }, SLEEP_DURATION_MILLISECONDS); 101 // We got our first timestamp and started the (delayed) send 102 // message. Nothing more to do this time. 103 return; 104 } 105 // This is our second call. 106 long timeDifference = timestamp - mFirstTimestamp; 107 assertTrue("Subsequent timestamps did not monotonically increase", 108 timeDifference > 0); 109 assertTrue("Expected timestamp difference around " + SLEEP_DURATION_NS 110 + " nanoseconds, but got " + timeDifference, 111 ((timeDifference > (SLEEP_DURATION_NS - TOLERANCE_NS)) 112 && (timeDifference 113 < (SLEEP_DURATION_NS + TOLERANCE_NS)))); 114 115 // The CHRE gave us two reasonable timestamps. And the nanoapp didn't 116 // signal any issues with its testing. We're good. 117 pass(); 118 } 119 120 @Override deinit()121 public void deinit() { 122 // If our test aborted for another reason, we want to make sure 123 // we cancel any timer that we might have set, so we don't send 124 // a spurious message to the CHRE after this test has completed. 125 mTimer.cancel(); 126 127 super.deinit(); 128 } 129 } 130