1 /*
2  * Copyright (C) 2018 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 
17 package com.google.android.startop.iorap;
18 
19 import android.os.Parcelable;
20 import android.os.Parcel;
21 
22 import android.annotation.NonNull;
23 
24 /**
25  * Uniquely identify an {@link com.google.android.startop.iorap.IIorap} method invocation,
26  * used for asynchronous callbacks by the server. <br /><br />
27  *
28  * As all system server binder calls must be {@code oneway}, this means all invocations
29  * into {@link com.google.android.startop.iorap.IIorap} are non-blocking. The request ID
30  * exists to associate all calls with their respective callbacks in
31  * {@link com.google.android.startop.iorap.ITaskListener}.
32  *
33  * @see com.google.android.startop.iorap.IIorap
34  *
35  * @hide
36  */
37 public class RequestId implements Parcelable {
38 
39     public final long requestId;
40 
41     private static Object mLock = new Object();
42     private static long mNextRequestId = 0;
43 
44     /**
45      * Create a monotonically increasing request ID.<br /><br />
46      *
47      * It is invalid to re-use the same request ID for multiple method calls on
48      * {@link com.google.android.startop.iorap.IIorap}; a new request ID must be created
49      * each time.
50      */
nextValueForSequence()51     @NonNull public static RequestId nextValueForSequence() {
52         long currentRequestId;
53         synchronized (mLock) {
54             currentRequestId = mNextRequestId;
55             ++mNextRequestId;
56         }
57         return new RequestId(currentRequestId);
58     }
59 
RequestId(long requestId)60     private RequestId(long requestId) {
61         this.requestId = requestId;
62 
63         checkConstructorArguments();
64     }
65 
checkConstructorArguments()66     private void checkConstructorArguments() {
67         if (requestId < 0) {
68             throw new IllegalArgumentException("request id must be non-negative");
69         }
70     }
71 
72     @Override
toString()73     public String toString() {
74         return String.format("{requestId: %d}", requestId);
75     }
76 
77     @Override
equals(Object other)78     public boolean equals(Object other) {
79         if (this == other) {
80             return true;
81         } else if (other instanceof RequestId) {
82             return equals((RequestId) other);
83         }
84         return false;
85     }
86 
equals(RequestId other)87     private boolean equals(RequestId other) {
88         return requestId == other.requestId;
89     }
90 
91 
92     //<editor-fold desc="Binder boilerplate">
93     @Override
writeToParcel(Parcel out, int flags)94     public void writeToParcel(Parcel out, int flags) {
95         out.writeLong(requestId);
96     }
97 
RequestId(Parcel in)98     private RequestId(Parcel in) {
99         requestId = in.readLong();
100 
101         checkConstructorArguments();
102     }
103 
104     @Override
describeContents()105     public int describeContents() {
106         return 0;
107     }
108 
109     public static final Parcelable.Creator<RequestId> CREATOR
110             = new Parcelable.Creator<RequestId>() {
111         public RequestId createFromParcel(Parcel in) {
112             return new RequestId(in);
113         }
114 
115         public RequestId[] newArray(int size) {
116             return new RequestId[size];
117         }
118     };
119     //</editor-fold>
120 }
121