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.BufferUnderflowException;
23 import java.nio.ByteBuffer;
24 import java.nio.ByteOrder;
25 
26 /**
27  * Verify sending a CHRE event between two nanoapps.
28  *
29  * We also check that we get the correct nanoApp IDs and sane nanoApp instance IDs.
30  *
31  * Protocol:
32  * There are two nanoapps here, so we'll talk in term of app0 and app1.
33  * All data involving the host is sent little endian.
34  *
35  * Host to app0:  EVENT_BETWEEN_APPS0, no data
36  * Host to app1:  EVENT_BETWEEN_APPS1, no data
37  * app0 to host:  CONTINUE, 64-bit app ID, 32-bit instance ID
38  * app1 to host:  CONTINUE, 64-bit app ID, 32-bit instance ID
39  * Host to app1:  CONTINUE, app0's 32-bit instance ID
40  * Host to app0:  CONTINUE, app1's 32-bit instance ID
41  * [app0 sends message to app1]
42  * app1 to host:  SUCCESS
43  */
44 public class ContextHubEventBetweenAppsTestExecutor extends ContextHubGeneralTestExecutor {
45     /**
46      * A container class to store information supplied by the nanoapps.
47      */
48     private class AppInfo {
49         public long appId;
50         public int instanceId;
51         public boolean haveInfo = false;
52     }
53 
54     private final long mNanoAppId0;
55     private final long mNanoAppId1;
56     private AppInfo[] mAppInfo = new AppInfo[]{new AppInfo(), new AppInfo()};
57 
ContextHubEventBetweenAppsTestExecutor(ContextHubManager manager, ContextHubInfo info, NanoAppBinary binary0, NanoAppBinary binary1)58     public ContextHubEventBetweenAppsTestExecutor(ContextHubManager manager, ContextHubInfo info,
59             NanoAppBinary binary0, NanoAppBinary binary1) {
60         super(manager, info, new GeneralTestNanoApp(binary0,
61                         ContextHubTestConstants.TestNames.EVENT_BETWEEN_APPS0),
62                 new GeneralTestNanoApp(binary1,
63                         ContextHubTestConstants.TestNames.EVENT_BETWEEN_APPS1));
64         mNanoAppId0 = binary0.getNanoAppId();
65         mNanoAppId1 = binary1.getNanoAppId();
66     }
67 
68     @Override
handleMessageFromNanoApp(long nanoAppId, ContextHubTestConstants.MessageType type, byte[] data)69     protected void handleMessageFromNanoApp(long nanoAppId,
70             ContextHubTestConstants.MessageType type, byte[] data) {
71         if (type != ContextHubTestConstants.MessageType.CONTINUE) {
72             fail("Unexpected message type " + type);
73             return;
74         }
75 
76         int index = (nanoAppId == mNanoAppId0) ? 0 : 1;
77         assertFalse("Multiple CONTINUE messages from app 0x" + Long.toHexString(nanoAppId),
78                 mAppInfo[index].haveInfo);
79 
80         ByteBuffer buffer = ByteBuffer.wrap(data)
81                 .order(ByteOrder.LITTLE_ENDIAN);
82         try {
83             mAppInfo[index].appId = buffer.getLong();
84             mAppInfo[index].instanceId = buffer.getInt();
85             mAppInfo[index].haveInfo = true;
86         } catch (BufferUnderflowException e) {
87             fail("Not enough data provided in CONTINUE message from 0x" + Long.toHexString(
88                     nanoAppId));
89         }
90         assertFalse(
91                 "Too much data provided in CONTINUE message from 0x" + Long.toHexString(nanoAppId),
92                 buffer.hasRemaining());
93 
94         int otherIndex = 1 - index;
95         if (!mAppInfo[otherIndex].haveInfo) {
96             // We need to wait to get the info from the other app.
97             return;
98         }
99 
100         assertEquals("Incorrect app ID given for 0x" + Long.toHexString(mNanoAppId0),
101                 mNanoAppId0,
102                 mAppInfo[0].appId);
103         assertEquals("Incorrect app ID given for 0x" + Long.toHexString(mNanoAppId1),
104                 mNanoAppId1,
105                 mAppInfo[1].appId);
106         assertTrue("Both nanoapps given identical instance IDs",
107                 mAppInfo[0].instanceId != mAppInfo[1].instanceId);
108 
109         // Consistency checks pass.  We'll send the data down.
110         buffer = ByteBuffer.allocate(4)
111                 .order(ByteOrder.LITTLE_ENDIAN)
112                 .putInt(mAppInfo[0].instanceId);
113         sendMessageToNanoAppOrFail(mNanoAppId1,
114                 ContextHubTestConstants.MessageType.CONTINUE.asInt(), buffer.array());
115 
116         buffer.clear();
117         buffer.putInt(mAppInfo[1].instanceId);
118         sendMessageToNanoAppOrFail(mNanoAppId0,
119                 ContextHubTestConstants.MessageType.CONTINUE.asInt(), buffer.array());
120     }
121 }
122