1 /* 2 * Copyright 2017 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 android.hardware.location; 17 18 import android.annotation.NonNull; 19 import android.annotation.Nullable; 20 import android.annotation.SystemApi; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 24 import libcore.util.HexEncoding; 25 26 import java.util.Arrays; 27 28 /** 29 * A class describing messages send to or from nanoapps through the Context Hub Service. 30 * 31 * The basis of the class is in the IContextHub.hal ContextHubMsg definition. 32 * 33 * @hide 34 */ 35 @SystemApi 36 public final class NanoAppMessage implements Parcelable { 37 private static final int DEBUG_LOG_NUM_BYTES = 16; 38 private long mNanoAppId; 39 private int mMessageType; 40 private byte[] mMessageBody; 41 private boolean mIsBroadcasted; 42 NanoAppMessage( long nanoAppId, int messageType, byte[] messageBody, boolean broadcasted)43 private NanoAppMessage( 44 long nanoAppId, int messageType, byte[] messageBody, boolean broadcasted) { 45 mNanoAppId = nanoAppId; 46 mMessageType = messageType; 47 mMessageBody = messageBody; 48 mIsBroadcasted = broadcasted; 49 } 50 51 /** 52 * Creates a NanoAppMessage object to send to a nanoapp. 53 * 54 * This factory method can be used to generate a NanoAppMessage object to be used in 55 * the ContextHubClient.sendMessageToNanoApp API. 56 * 57 * @param targetNanoAppId the ID of the nanoapp to send the message to 58 * @param messageType the nanoapp-dependent message type 59 * @param messageBody the byte array message contents 60 * 61 * @return the NanoAppMessage object 62 */ createMessageToNanoApp( long targetNanoAppId, int messageType, byte[] messageBody)63 public static NanoAppMessage createMessageToNanoApp( 64 long targetNanoAppId, int messageType, byte[] messageBody) { 65 return new NanoAppMessage( 66 targetNanoAppId, messageType, messageBody, false /* broadcasted */); 67 } 68 69 /** 70 * Creates a NanoAppMessage object sent from a nanoapp. 71 * 72 * This factory method is intended only to be used by the Context Hub Service when delivering 73 * messages from a nanoapp to clients. 74 * 75 * @param sourceNanoAppId the ID of the nanoapp that the message was sent from 76 * @param messageType the nanoapp-dependent message type 77 * @param messageBody the byte array message contents 78 * @param broadcasted {@code true} if the message was broadcasted, {@code false} otherwise 79 * 80 * @return the NanoAppMessage object 81 */ createMessageFromNanoApp( long sourceNanoAppId, int messageType, byte[] messageBody, boolean broadcasted)82 public static NanoAppMessage createMessageFromNanoApp( 83 long sourceNanoAppId, int messageType, byte[] messageBody, boolean broadcasted) { 84 return new NanoAppMessage(sourceNanoAppId, messageType, messageBody, broadcasted); 85 } 86 87 /** 88 * @return the ID of the source or destination nanoapp 89 */ getNanoAppId()90 public long getNanoAppId() { 91 return mNanoAppId; 92 } 93 94 /** 95 * @return the type of the message that is nanoapp-dependent 96 */ getMessageType()97 public int getMessageType() { 98 return mMessageType; 99 } 100 101 /** 102 * @return the byte array contents of the message 103 */ getMessageBody()104 public byte[] getMessageBody() { 105 return mMessageBody; 106 } 107 108 /** 109 * @return {@code true} if the message is broadcasted, {@code false} otherwise 110 */ isBroadcastMessage()111 public boolean isBroadcastMessage() { 112 return mIsBroadcasted; 113 } 114 NanoAppMessage(Parcel in)115 private NanoAppMessage(Parcel in) { 116 mNanoAppId = in.readLong(); 117 mIsBroadcasted = (in.readInt() == 1); 118 mMessageType = in.readInt(); 119 120 int msgSize = in.readInt(); 121 mMessageBody = new byte[msgSize]; 122 in.readByteArray(mMessageBody); 123 } 124 125 @Override describeContents()126 public int describeContents() { 127 return 0; 128 } 129 130 @Override writeToParcel(Parcel out, int flags)131 public void writeToParcel(Parcel out, int flags) { 132 out.writeLong(mNanoAppId); 133 out.writeInt(mIsBroadcasted ? 1 : 0); 134 out.writeInt(mMessageType); 135 136 out.writeInt(mMessageBody.length); 137 out.writeByteArray(mMessageBody); 138 } 139 140 public static final @NonNull Creator<NanoAppMessage> CREATOR = 141 new Creator<NanoAppMessage>() { 142 @Override 143 public NanoAppMessage createFromParcel(Parcel in) { 144 return new NanoAppMessage(in); 145 } 146 147 @Override 148 public NanoAppMessage[] newArray(int size) { 149 return new NanoAppMessage[size]; 150 } 151 }; 152 153 @NonNull 154 @Override toString()155 public String toString() { 156 int length = mMessageBody.length; 157 158 String ret = "NanoAppMessage[type = " + mMessageType + ", length = " + mMessageBody.length 159 + " bytes, " + (mIsBroadcasted ? "broadcast" : "unicast") + ", nanoapp = 0x" 160 + Long.toHexString(mNanoAppId) + "]("; 161 if (length > 0) { 162 ret += "data = 0x"; 163 } 164 for (int i = 0; i < Math.min(length, DEBUG_LOG_NUM_BYTES); i++) { 165 ret += HexEncoding.encodeToString(mMessageBody[i], true /* upperCase */); 166 167 if ((i + 1) % 4 == 0) { 168 ret += " "; 169 } 170 } 171 if (length > DEBUG_LOG_NUM_BYTES) { 172 ret += "..."; 173 } 174 ret += ")"; 175 176 return ret; 177 } 178 179 @Override equals(@ullable Object object)180 public boolean equals(@Nullable Object object) { 181 if (object == this) { 182 return true; 183 } 184 185 boolean isEqual = false; 186 if (object instanceof NanoAppMessage) { 187 NanoAppMessage other = (NanoAppMessage) object; 188 isEqual = (other.getNanoAppId() == mNanoAppId) 189 && (other.getMessageType() == mMessageType) 190 && (other.isBroadcastMessage() == mIsBroadcasted) 191 && Arrays.equals(other.getMessageBody(), mMessageBody); 192 } 193 194 return isEqual; 195 } 196 } 197