1 /*
2  * Copyright (C) 2022 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 android.service.ambientcontext;
18 
19 import android.annotation.NonNull;
20 import android.annotation.SuppressLint;
21 import android.annotation.SystemApi;
22 import android.app.ambientcontext.AmbientContextEvent;
23 import android.os.Parcelable;
24 
25 import com.android.internal.util.AnnotationValidations;
26 
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.Objects;
30 
31 /**
32  * Represents a {@code AmbientContextEvent} detection result reported by the detection service.
33  *
34  * @hide
35  */
36 @SystemApi
37 public final class AmbientContextDetectionResult implements Parcelable {
38 
39     /**
40      * The bundle key for this class of object, used in {@code RemoteCallback#sendResult}.
41      *
42      * @hide
43      */
44     public static final String RESULT_RESPONSE_BUNDLE_KEY =
45             "android.app.ambientcontext.AmbientContextDetectionResultBundleKey";
46     @NonNull private final List<AmbientContextEvent> mEvents;
47     @NonNull private final String mPackageName;
48 
AmbientContextDetectionResult( @onNull List<AmbientContextEvent> events, @NonNull String packageName)49     AmbientContextDetectionResult(
50             @NonNull List<AmbientContextEvent> events,
51             @NonNull String packageName) {
52         this.mEvents = events;
53         AnnotationValidations.validate(NonNull.class, null, mEvents);
54         this.mPackageName = packageName;
55         AnnotationValidations.validate(NonNull.class, null, mPackageName);
56     }
57 
58     /**
59      * A list of detected event.
60      */
61     @SuppressLint("ConcreteCollection")
getEvents()62     public @NonNull List<AmbientContextEvent> getEvents() {
63         return mEvents;
64     }
65 
66     /**
67      * The package to deliver the response to.
68      */
getPackageName()69     public @NonNull String getPackageName() {
70         return mPackageName;
71     }
72 
73     @Override
toString()74     public String toString() {
75         return "AmbientContextEventResponse { "
76                 + "events = " + mEvents + ", " + "packageName = " + mPackageName + " }";
77     }
78 
79     @Override
writeToParcel(@onNull android.os.Parcel dest, int flags)80     public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
81         byte flg = 0;
82         dest.writeByte(flg);
83         dest.writeParcelableList(mEvents, flags);
84         dest.writeString(mPackageName);
85     }
86 
87     @Override
describeContents()88     public int describeContents() {
89         return 0;
90     }
91 
92     /** @hide */
93     @SuppressWarnings({"unchecked", "RedundantCast"})
AmbientContextDetectionResult(@onNull android.os.Parcel in)94     AmbientContextDetectionResult(@NonNull android.os.Parcel in) {
95         byte flg = in.readByte();
96         ArrayList<AmbientContextEvent> events = new ArrayList<>();
97         in.readParcelableList(events, AmbientContextEvent.class.getClassLoader(),
98                 AmbientContextEvent.class);
99         String packageName = in.readString();
100 
101         this.mEvents = events;
102         AnnotationValidations.validate(
103                 NonNull.class, null, mEvents);
104         this.mPackageName = packageName;
105         AnnotationValidations.validate(
106                 NonNull.class, null, mPackageName);
107     }
108 
109     public static final @NonNull Creator<AmbientContextDetectionResult> CREATOR =
110             new Creator<AmbientContextDetectionResult>() {
111         @Override
112         public AmbientContextDetectionResult[] newArray(int size) {
113             return new AmbientContextDetectionResult[size];
114         }
115 
116         @Override
117         public AmbientContextDetectionResult createFromParcel(@NonNull android.os.Parcel in) {
118             return new AmbientContextDetectionResult(in);
119         }
120     };
121 
122     /**
123      * A builder for {@link AmbientContextDetectionResult}
124      */
125     @SuppressWarnings("WeakerAccess")
126     public static final class Builder {
127         private @NonNull ArrayList<AmbientContextEvent> mEvents;
128         private @NonNull String mPackageName;
129         private long mBuilderFieldsSet = 0L;
130 
Builder(@onNull String packageName)131         public Builder(@NonNull String packageName) {
132             Objects.requireNonNull(packageName);
133             mPackageName = packageName;
134         }
135 
136         /**
137          * Adds an event to the builder.
138          */
addEvent(@onNull AmbientContextEvent value)139         public @NonNull Builder addEvent(@NonNull AmbientContextEvent value) {
140             checkNotUsed();
141             if (mEvents == null) {
142                 mBuilderFieldsSet |= 0x1;
143                 mEvents = new ArrayList<>();
144             }
145             mEvents.add(value);
146             return this;
147         }
148 
149         /**
150          * Adds a list of events to the builder.
151          */
addEvents(@onNull List<AmbientContextEvent> values)152         public @NonNull Builder addEvents(@NonNull List<AmbientContextEvent> values) {
153             checkNotUsed();
154             if (mEvents == null) {
155                 mBuilderFieldsSet |= 0x1;
156                 mEvents = new ArrayList<>();
157             }
158             mEvents.addAll(values);
159             return this;
160         }
161 
162         /**
163          * Clears all events from the builder.
164          */
clearEvents()165         public @NonNull Builder clearEvents() {
166             checkNotUsed();
167             if (mEvents != null) {
168                 mEvents.clear();
169             }
170             return this;
171         }
172 
173         /** Builds the instance. This builder should not be touched after calling this! */
build()174         public @NonNull AmbientContextDetectionResult build() {
175             checkNotUsed();
176             mBuilderFieldsSet |= 0x2; // Mark builder used
177 
178             if ((mBuilderFieldsSet & 0x1) == 0) {
179                 mEvents = new ArrayList<>();
180             }
181             AmbientContextDetectionResult o = new AmbientContextDetectionResult(
182                     mEvents,
183                     mPackageName);
184             return o;
185         }
186 
checkNotUsed()187         private void checkNotUsed() {
188             if ((mBuilderFieldsSet & 0x2) != 0) {
189                 throw new IllegalStateException(
190                         "This Builder should not be reused. Use a new Builder instance instead");
191             }
192         }
193     }
194 }
195