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.app.ambientcontext; 18 19 import android.annotation.NonNull; 20 import android.annotation.SystemApi; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.os.PersistableBundle; 24 import android.util.ArraySet; 25 26 import com.android.internal.util.AnnotationValidations; 27 import com.android.internal.util.Preconditions; 28 29 import java.util.HashSet; 30 import java.util.Set; 31 32 /** 33 * Represents the request for ambient event detection. 34 * 35 * @hide 36 */ 37 @SystemApi 38 public final class AmbientContextEventRequest implements Parcelable { 39 @NonNull private final Set<Integer> mEventTypes; 40 @NonNull private final PersistableBundle mOptions; 41 AmbientContextEventRequest( @onNull Set<Integer> eventTypes, @NonNull PersistableBundle options)42 private AmbientContextEventRequest( 43 @NonNull Set<Integer> eventTypes, 44 @NonNull PersistableBundle options) { 45 this.mEventTypes = eventTypes; 46 AnnotationValidations.validate(NonNull.class, null, mEventTypes); 47 Preconditions.checkArgument(!eventTypes.isEmpty(), "eventTypes cannot be empty"); 48 for (int eventType : eventTypes) { 49 AnnotationValidations.validate(AmbientContextEvent.EventCode.class, null, eventType); 50 } 51 this.mOptions = options; 52 AnnotationValidations.validate(NonNull.class, null, mOptions); 53 } 54 55 /** 56 * The event types to detect. 57 */ getEventTypes()58 public @NonNull Set<Integer> getEventTypes() { 59 return mEventTypes; 60 } 61 62 /** 63 * Optional detection options. 64 */ getOptions()65 public @NonNull PersistableBundle getOptions() { 66 return mOptions; 67 } 68 69 @Override toString()70 public String toString() { 71 return "AmbientContextEventRequest { " + "eventTypes = " + mEventTypes + ", " 72 + "options = " + mOptions + " }"; 73 } 74 75 @Override writeToParcel(@onNull Parcel dest, int flags)76 public void writeToParcel(@NonNull Parcel dest, int flags) { 77 dest.writeArraySet(new ArraySet<>(mEventTypes)); 78 dest.writeTypedObject(mOptions, flags); 79 } 80 81 @Override describeContents()82 public int describeContents() { 83 return 0; 84 } 85 86 /** @hide */ 87 @SuppressWarnings({"unchecked", "RedundantCast"}) AmbientContextEventRequest(@onNull Parcel in)88 private AmbientContextEventRequest(@NonNull Parcel in) { 89 Set<Integer> eventTypes = (Set<Integer>) in.readArraySet(Integer.class.getClassLoader()); 90 PersistableBundle options = (PersistableBundle) in.readTypedObject( 91 PersistableBundle.CREATOR); 92 93 this.mEventTypes = eventTypes; 94 AnnotationValidations.validate( 95 NonNull.class, null, mEventTypes); 96 Preconditions.checkArgument(!eventTypes.isEmpty(), "eventTypes cannot be empty"); 97 for (int eventType : eventTypes) { 98 AnnotationValidations.validate(AmbientContextEvent.EventCode.class, null, eventType); 99 } 100 this.mOptions = options; 101 AnnotationValidations.validate( 102 NonNull.class, null, mOptions); 103 } 104 105 public static final @NonNull Parcelable.Creator<AmbientContextEventRequest> CREATOR = 106 new Parcelable.Creator<AmbientContextEventRequest>() { 107 @Override 108 public AmbientContextEventRequest[] newArray(int size) { 109 return new AmbientContextEventRequest[size]; 110 } 111 112 @Override 113 public AmbientContextEventRequest createFromParcel(@NonNull Parcel in) { 114 return new AmbientContextEventRequest(in); 115 } 116 }; 117 118 /** 119 * A builder for {@link AmbientContextEventRequest} 120 */ 121 @SuppressWarnings("WeakerAccess") 122 public static final class Builder { 123 private @NonNull Set<Integer> mEventTypes; 124 private @NonNull PersistableBundle mOptions; 125 126 private long mBuilderFieldsSet = 0L; 127 Builder()128 public Builder() { 129 } 130 131 /** 132 * Add an event type to detect. 133 */ addEventType(@mbientContextEvent.EventCode int value)134 public @NonNull Builder addEventType(@AmbientContextEvent.EventCode int value) { 135 checkNotUsed(); 136 if (mEventTypes == null) { 137 mBuilderFieldsSet |= 0x1; 138 mEventTypes = new HashSet<>(); 139 } 140 mEventTypes.add(value); 141 return this; 142 } 143 144 /** 145 * Optional detection options. 146 */ setOptions(@onNull PersistableBundle value)147 public @NonNull Builder setOptions(@NonNull PersistableBundle value) { 148 checkNotUsed(); 149 mBuilderFieldsSet |= 0x2; 150 mOptions = value; 151 return this; 152 } 153 154 /** Builds the instance. This builder should not be touched after calling this! */ build()155 public @NonNull AmbientContextEventRequest build() { 156 checkNotUsed(); 157 mBuilderFieldsSet |= 0x4; // Mark builder used 158 159 if ((mBuilderFieldsSet & 0x1) == 0) { 160 mEventTypes = new HashSet<>(); 161 } 162 if ((mBuilderFieldsSet & 0x2) == 0) { 163 mOptions = new PersistableBundle(); 164 } 165 AmbientContextEventRequest o = new AmbientContextEventRequest( 166 mEventTypes, 167 mOptions); 168 return o; 169 } 170 checkNotUsed()171 private void checkNotUsed() { 172 if ((mBuilderFieldsSet & 0x4) != 0) { 173 throw new IllegalStateException( 174 "This Builder should not be reused. Use a new Builder instance instead"); 175 } 176 } 177 } 178 } 179