• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.FlaggedApi;
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.chre.flags.Flags;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 
26 import libcore.util.HexEncoding;
27 
28 import java.util.Arrays;
29 import java.util.Objects;
30 
31 /**
32  * A class describing messages send to or from nanoapps through the Context Hub Service.
33  *
34  * The basis of the class is in the IContextHub.hal ContextHubMsg definition.
35  *
36  * @hide
37  */
38 @SystemApi
39 public final class NanoAppMessage implements Parcelable {
40     private static final int DEBUG_LOG_NUM_BYTES = 16;
41     private long mNanoAppId;
42     private int mMessageType;
43     private byte[] mMessageBody;
44     private boolean mIsBroadcasted;
45     private boolean mIsReliable;
46     private int mMessageSequenceNumber;
47 
NanoAppMessage(long nanoAppId, int messageType, byte[] messageBody, boolean broadcasted, boolean isReliable, int messageSequenceNumber)48     private NanoAppMessage(long nanoAppId, int messageType, byte[] messageBody,
49             boolean broadcasted, boolean isReliable, int messageSequenceNumber) {
50         mNanoAppId = nanoAppId;
51         mMessageType = messageType;
52         mMessageBody = messageBody;
53         mIsBroadcasted = broadcasted;
54         mIsReliable = isReliable;
55         mMessageSequenceNumber = messageSequenceNumber;
56     }
57 
58     /**
59      * Creates a NanoAppMessage object to send to a nanoapp.
60      *
61      * This factory method can be used to generate a NanoAppMessage object to be used in
62      * the ContextHubClient.sendMessageToNanoApp API.
63      *
64      * @param targetNanoAppId the ID of the nanoapp to send the message to
65      * @param messageType the nanoapp-dependent message type
66      *                    the value CHRE_MESSAGE_TYPE_RPC (0x7FFFFFF5) is reserved by the
67      *                    framework for RPC messages
68      * @param messageBody the byte array message contents
69      *
70      * @return the NanoAppMessage object
71      */
createMessageToNanoApp(long targetNanoAppId, int messageType, byte[] messageBody)72     public static NanoAppMessage createMessageToNanoApp(long targetNanoAppId, int messageType,
73             byte[] messageBody) {
74         return new NanoAppMessage(targetNanoAppId, messageType, messageBody,
75                 false /* broadcasted */, false /* isReliable */, 0 /* messageSequenceNumber */);
76     }
77 
78     /**
79      * Creates a NanoAppMessage object sent from a nanoapp.
80      *
81      * This factory method is intended only to be used by the Context Hub Service when delivering
82      * messages from a nanoapp to clients.
83      *
84      * @param sourceNanoAppId the ID of the nanoapp that the message was sent from
85      * @param messageType the nanoapp-dependent message type
86      * @param messageBody the byte array message contents
87      * @param broadcasted {@code true} if the message was broadcasted, {@code false} otherwise
88      *
89      * @return the NanoAppMessage object
90      */
createMessageFromNanoApp(long sourceNanoAppId, int messageType, byte[] messageBody, boolean broadcasted)91     public static NanoAppMessage createMessageFromNanoApp(long sourceNanoAppId, int messageType,
92             byte[] messageBody, boolean broadcasted) {
93         return new NanoAppMessage(sourceNanoAppId, messageType, messageBody, broadcasted,
94                 false /* isReliable */, 0 /* messageSequenceNumber */);
95     }
96 
97     /**
98      * Creates a NanoAppMessage object sent from a nanoapp.
99      *
100      * <p>This factory method is intended only to be used by the Context Hub Service when delivering
101      * messages from a nanoapp to clients.
102      *
103      * @param sourceNanoAppId the ID of the nanoapp that the message was sent from
104      * @param messageType the nanoapp-dependent message type
105      * @param messageBody the byte array message contents
106      * @param broadcasted {@code true} if the message was broadcasted, {@code false} otherwise
107      * @param isReliable if the NanoAppMessage is reliable
108      * @param messageSequenceNumber the message sequence number of the NanoAppMessage
109      * @return the NanoAppMessage object
110      */
createMessageFromNanoApp( long sourceNanoAppId, int messageType, @NonNull byte[] messageBody, boolean broadcasted, boolean isReliable, int messageSequenceNumber)111     public static @NonNull NanoAppMessage createMessageFromNanoApp(
112             long sourceNanoAppId,
113             int messageType,
114             @NonNull byte[] messageBody,
115             boolean broadcasted,
116             boolean isReliable,
117             int messageSequenceNumber) {
118         return new NanoAppMessage(sourceNanoAppId, messageType, messageBody, broadcasted,
119                 isReliable, messageSequenceNumber);
120     }
121 
122     /**
123      * @return the ID of the source or destination nanoapp
124      */
getNanoAppId()125     public long getNanoAppId() {
126         return mNanoAppId;
127     }
128 
129     /**
130      * @return the type of the message that is nanoapp-dependent
131      */
getMessageType()132     public int getMessageType() {
133         return mMessageType;
134     }
135 
136     /**
137      * @return the byte array contents of the message
138      */
getMessageBody()139     public byte[] getMessageBody() {
140         return mMessageBody;
141     }
142 
143     /**
144      * @return {@code true} if the message is broadcasted, {@code false} otherwise
145      */
isBroadcastMessage()146     public boolean isBroadcastMessage() {
147         return mIsBroadcasted;
148     }
149 
150     /**
151      * Returns if the message is reliable. The default value is {@code false}
152      *
153      * @return {@code true} if the message is reliable, {@code false} otherwise
154      */
isReliable()155     public boolean isReliable() {
156         return mIsReliable;
157     }
158 
159     /**
160      * Returns the message sequence number. The default value is 0
161      *
162      * @return the message sequence number of the message
163      */
getMessageSequenceNumber()164     public int getMessageSequenceNumber() {
165         return mMessageSequenceNumber;
166     }
167 
168     /**
169      * Sets the isReliable field of the message
170      *
171      * @hide
172      */
setIsReliable(boolean isReliable)173     public void setIsReliable(boolean isReliable) {
174         mIsReliable = isReliable;
175     }
176 
177     /**
178      * Sets the message sequence number of the message
179      *
180      * @hide
181      */
setMessageSequenceNumber(int messageSequenceNumber)182     public void setMessageSequenceNumber(int messageSequenceNumber) {
183         mMessageSequenceNumber = messageSequenceNumber;
184     }
185 
NanoAppMessage(Parcel in)186     private NanoAppMessage(Parcel in) {
187         mNanoAppId = in.readLong();
188         mIsBroadcasted = (in.readInt() == 1);
189         mMessageType = in.readInt();
190 
191         int msgSize = in.readInt();
192         mMessageBody = new byte[msgSize];
193         in.readByteArray(mMessageBody);
194 
195         mIsReliable = (in.readInt() == 1);
196         mMessageSequenceNumber = in.readInt();
197     }
198 
199     @Override
describeContents()200     public int describeContents() {
201         return 0;
202     }
203 
204     @Override
writeToParcel(Parcel out, int flags)205     public void writeToParcel(Parcel out, int flags) {
206         out.writeLong(mNanoAppId);
207         out.writeInt(mIsBroadcasted ? 1 : 0);
208         out.writeInt(mMessageType);
209 
210         out.writeInt(mMessageBody.length);
211         out.writeByteArray(mMessageBody);
212 
213         out.writeInt(mIsReliable ? 1 : 0);
214         out.writeInt(mMessageSequenceNumber);
215     }
216 
217     public static final @NonNull Creator<NanoAppMessage> CREATOR =
218             new Creator<NanoAppMessage>() {
219                 @Override
220                 public NanoAppMessage createFromParcel(Parcel in) {
221                     return new NanoAppMessage(in);
222                 }
223 
224                 @Override
225                 public NanoAppMessage[] newArray(int size) {
226                     return new NanoAppMessage[size];
227                 }
228             };
229 
230     @NonNull
231     @Override
toString()232     public String toString() {
233         int length = mMessageBody.length;
234 
235         StringBuilder out = new StringBuilder();
236         out.append( "NanoAppMessage[type = ");
237         out.append(mMessageType);
238         out.append(", length = ");
239         out.append(mMessageBody.length);
240         out.append(" bytes, ");
241         out.append(mIsBroadcasted ? "broadcast" : "unicast");
242         out.append(", nanoapp = 0x");
243         out.append(Long.toHexString(mNanoAppId));
244         out.append(", isReliable = ");
245         out.append(mIsReliable ? "true" : "false");
246         out.append(", messageSequenceNumber = ");
247         out.append(mMessageSequenceNumber);
248         out.append("](");
249 
250         if (length > 0) {
251             out.append("data = 0x");
252         }
253         for (int i = 0; i < Math.min(length, DEBUG_LOG_NUM_BYTES); i++) {
254             out.append(HexEncoding.encodeToString(mMessageBody[i],
255                                                   true /* upperCase */));
256 
257             if ((i + 1) % 4 == 0) {
258                 out.append(" ");
259             }
260         }
261         if (length > DEBUG_LOG_NUM_BYTES) {
262             out.append("...");
263         }
264         out.append(")");
265 
266         return out.toString();
267     }
268 
269     @Override
equals(@ullable Object object)270     public boolean equals(@Nullable Object object) {
271         if (object == this) {
272             return true;
273         }
274 
275         boolean isEqual = false;
276         if (object instanceof NanoAppMessage) {
277             NanoAppMessage other = (NanoAppMessage) object;
278             isEqual = (other.getNanoAppId() == mNanoAppId)
279                     && (other.getMessageType() == mMessageType)
280                     && (other.isBroadcastMessage() == mIsBroadcasted)
281                     && Arrays.equals(other.getMessageBody(), mMessageBody)
282                     && (!Flags.reliableMessage()
283                             || (other.isReliable() == mIsReliable))
284                     && (!Flags.reliableMessage()
285                             || (other.getMessageSequenceNumber() == mMessageSequenceNumber));
286         }
287 
288         return isEqual;
289     }
290 
291     @Override
hashCode()292     public int hashCode() {
293         if (!Flags.fixApiCheck()) {
294             return super.hashCode();
295         }
296 
297         return Objects.hash(mNanoAppId, mMessageType, mIsBroadcasted,
298                 Arrays.hashCode(mMessageBody), mIsReliable,
299                 mMessageSequenceNumber);
300     }
301 }
302