1 /*
2  * Copyright (C) 2020 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.app.search;
17 
18 import android.annotation.IntDef;
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.SystemApi;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.util.ArrayList;
28 import java.util.List;
29 import java.util.Objects;
30 
31 /**
32  * A representation of an search target event.
33  *
34  * There are two types of events. First type of event correspends to the user interaction
35  * that happens on the search surface. (e.g., {@link #ACTION_TAP}. Second type of events
36  * correspends to the lifecycle event of the search surface {@link #ACTION_SURFACE_VISIBLE}.
37  *
38  * @hide
39  */
40 @SystemApi
41 public final class SearchTargetEvent implements Parcelable {
42 
43     /**
44      * @hide
45      */
46     @IntDef(prefix = {"ACTION_"}, value = {
47             ACTION_SURFACE_VISIBLE,
48             ACTION_TAP,
49             ACTION_LONGPRESS,
50             ACTION_LAUNCH_TOUCH,
51             ACTION_LAUNCH_KEYBOARD_FOCUS,
52             ACTION_DRAGNDROP,
53             ACTION_SURFACE_INVISIBLE,
54             ACTION_DELETE,
55             ACTION_DISMISS
56     })
57     @Retention(RetentionPolicy.SOURCE)
58     public @interface ActionType {}
59 
60     /**
61      * @hide
62      */
63     @IntDef(prefix = {"FLAG_"}, value = {
64             FLAG_IME_SHOWN
65     })
66     @Retention(RetentionPolicy.SOURCE)
67     public @interface FlagType {}
68 
69     @NonNull
70     private final List<String> mTargetIds;
71     @Nullable
72     private final String mLocation;
73     @ActionType
74     private final int mAction;
75     @FlagType
76     private int mFlags;
77 
78     /**
79      * IME was shown when event happened.
80      */
81     public static final int FLAG_IME_SHOWN = 1 << 0;
82 
83 
84     /**
85      * Search container was opened.
86      */
87     public static final int ACTION_SURFACE_VISIBLE = 1;
88 
89     /**
90      * Constants that define tapping without closing the search surface.
91      */
92     public static final int ACTION_TAP = 3;
93 
94     /**
95      * Constants that define long pressing without closing the search surface.
96      */
97     public static final int ACTION_LONGPRESS = 4;
98 
99     /**
100      * Constants that define tapping on the touch target to launch.
101      */
102     public static final int ACTION_LAUNCH_TOUCH = 5;
103 
104     /**
105      * Constants that define tapping on the soft keyboard confirm or search to launch.
106      */
107     public static final int ACTION_LAUNCH_KEYBOARD_FOCUS = 6;
108 
109     /**
110      * Searcheable item was draged and dropped to another surface.
111      */
112     public static final int ACTION_DRAGNDROP = 7;
113 
114     /**
115      * Search container was closed.
116      */
117     public static final int ACTION_SURFACE_INVISIBLE = 8;
118 
119      /**
120      * Constant that defines user deleted a target.
121      */
122     public static final int ACTION_DELETE = 9;
123 
124     /**
125      * Constant that defines user dismissed a target.
126      */
127     public static final int ACTION_DISMISS = 10;
128 
SearchTargetEvent(@onNull List<String> targetIds, @Nullable String location, @ActionType int actionType, @FlagType int flags)129     private SearchTargetEvent(@NonNull List<String> targetIds,
130             @Nullable String location,
131             @ActionType int actionType,
132             @FlagType int flags) {
133         mTargetIds = Objects.requireNonNull(targetIds);
134         mLocation = location;
135         mAction = actionType;
136         mFlags = flags;
137     }
138 
SearchTargetEvent(Parcel parcel)139     private SearchTargetEvent(Parcel parcel) {
140         mTargetIds = new ArrayList<>();
141         parcel.readStringList(mTargetIds);
142         mLocation = parcel.readString();
143         mAction = parcel.readInt();
144         mFlags = parcel.readInt();
145     }
146 
147     /**
148      * Returns the primary search target with interaction.
149      */
150     @NonNull
getTargetId()151     public String getTargetId() {
152         return mTargetIds.get(0);
153     }
154 
155     /**
156      * Returns the list of search targets with visualization change.
157      */
158     @NonNull
getTargetIds()159     public List<String> getTargetIds() {
160         return mTargetIds;
161     }
162 
163     /**
164      * Returns the launch location.
165      */
166     @Nullable
getLaunchLocation()167     public String getLaunchLocation() {
168         return mLocation;
169     }
170 
171     /**
172      * Returns the action type.
173      */
174     @ActionType
getAction()175     public int getAction() {
176         return mAction;
177     }
178 
getFlags()179     public int getFlags() {
180         return mFlags;
181     }
182 
183     @Override
hashCode()184     public int hashCode() {
185         return mTargetIds.get(0).hashCode() + mAction;
186     }
187 
188     @Override
equals(@ullable Object o)189     public boolean equals(@Nullable Object o) {
190         if (!getClass().equals(o != null ? o.getClass() : null)) return false;
191 
192         SearchTargetEvent other = (SearchTargetEvent) o;
193         return mTargetIds.equals(other.mTargetIds)
194                 && mAction == other.mAction
195                 && mFlags == other.mFlags
196                 && mLocation == null ? other.mLocation == null : mLocation.equals(other.mLocation);
197     }
198 
199     @Override
describeContents()200     public int describeContents() {
201         return 0;
202     }
203 
204     @Override
writeToParcel(@onNull Parcel dest, int flags)205     public void writeToParcel(@NonNull Parcel dest, int flags) {
206         dest.writeStringList(mTargetIds);
207         dest.writeString(mLocation);
208         dest.writeInt(mAction);
209         dest.writeInt(mFlags);
210     }
211 
212     public static final @NonNull Creator<SearchTargetEvent> CREATOR =
213             new Creator<SearchTargetEvent>() {
214                 public SearchTargetEvent createFromParcel(Parcel parcel) {
215                     return new SearchTargetEvent(parcel);
216                 }
217 
218                 public SearchTargetEvent[] newArray(int size) {
219                     return new SearchTargetEvent[size];
220                 }
221             };
222 
223     /**
224      * A builder for search target events.
225      *
226      * @hide
227      */
228     @SystemApi
229     public static final class Builder {
230         @NonNull
231         private List<String> mTargetIds;
232         @Nullable
233         private String mLocation;
234         @ActionType
235         private int mAction;
236         private int mFlags;
237 
238         /**
239          * @param id The target id that is associated with this event.
240          * @param actionType The event type
241          */
Builder(@onNull String id, @ActionType int actionType)242         public Builder(@NonNull String id, @ActionType int actionType) {
243             mTargetIds = new ArrayList<>();
244             mTargetIds.add(id);
245             mAction = actionType;
246         }
247 
248         /**
249          * @param ids The target ids that is associated with this event.
250          * @param actionType The event type
251          */
Builder(@onNull List<String> ids, @ActionType int actionType)252         public Builder(@NonNull List<String> ids, @ActionType int actionType) {
253             mTargetIds = ids;
254             mAction = actionType;
255         }
256 
257         /**
258          * Sets the launch location.
259          */
260         @NonNull
setLaunchLocation(@ullable String location)261         public Builder setLaunchLocation(@Nullable String location) {
262             mLocation = location;
263             return this;
264         }
265 
266         /**
267          * Sets the launch location.
268          */
269         @NonNull
setFlags(int flags)270         public Builder setFlags(int flags) {
271             mFlags = flags;
272             return this;
273         }
274 
275         /**
276          * Builds a new event instance.
277          */
278         @NonNull
build()279         public SearchTargetEvent build() {
280             return new SearchTargetEvent(mTargetIds, mLocation, mAction, mFlags);
281         }
282     }
283 }
284