1 /*
2  * Copyright (C) 2021 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.smartspace.uitemplatedata;
18 
19 
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.annotation.SuppressLint;
23 import android.annotation.SystemApi;
24 import android.app.PendingIntent;
25 import android.app.smartspace.SmartspaceUtils;
26 import android.content.Intent;
27 import android.os.Bundle;
28 import android.os.Parcel;
29 import android.os.Parcelable;
30 import android.os.UserHandle;
31 import android.text.TextUtils;
32 
33 import java.util.Objects;
34 
35 /**
36  * A {@link TapAction} represents an action which can be taken by a user by tapping on
37  * either the title, the subtitle or on the icon. Supported instances are Intents and
38  * PendingIntents. These actions can be called from another process or within the client process.
39  *
40  * Clients can also receive ShorcutInfos in the extras bundle.
41  *
42  * @hide
43  */
44 @SystemApi
45 public final class TapAction implements Parcelable {
46 
47     /** A unique Id of this {@link TapAction}. */
48     @Nullable
49     private final CharSequence mId;
50 
51     @Nullable
52     private final Intent mIntent;
53 
54     @Nullable
55     private final PendingIntent mPendingIntent;
56 
57     @Nullable
58     private final UserHandle mUserHandle;
59 
60     @Nullable
61     private final Bundle mExtras;
62 
63     /**
64      * Whether the tap action's result should be shown on the lockscreen (e.g. turn off the
65      * flashlight can be done on LS bypassing the keyguard). Default value is false.
66      */
67     private final boolean mShouldShowOnLockscreen;
68 
TapAction(@onNull Parcel in)69     TapAction(@NonNull Parcel in) {
70         mId = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
71         mIntent = in.readTypedObject(Intent.CREATOR);
72         mPendingIntent = in.readTypedObject(PendingIntent.CREATOR);
73         mUserHandle = in.readTypedObject(UserHandle.CREATOR);
74         mExtras = in.readBundle();
75         mShouldShowOnLockscreen = in.readBoolean();
76     }
77 
TapAction(@ullable CharSequence id, @Nullable Intent intent, @Nullable PendingIntent pendingIntent, @Nullable UserHandle userHandle, @Nullable Bundle extras, boolean shouldShowOnLockscreen)78     private TapAction(@Nullable CharSequence id, @Nullable Intent intent,
79             @Nullable PendingIntent pendingIntent, @Nullable UserHandle userHandle,
80             @Nullable Bundle extras, boolean shouldShowOnLockscreen) {
81         mId = id;
82         mIntent = intent;
83         mPendingIntent = pendingIntent;
84         mUserHandle = userHandle;
85         mExtras = extras;
86         mShouldShowOnLockscreen = shouldShowOnLockscreen;
87     }
88 
89     /** Returns the unique id of the tap action. */
90     @Nullable
getId()91     public CharSequence getId() {
92         return mId;
93     }
94 
95     /** Returns the intent of the tap action. */
96     @SuppressLint("IntentBuilderName")
97     @Nullable
getIntent()98     public Intent getIntent() {
99         return mIntent;
100     }
101 
102     /** Returns the pending intent of the tap action. */
103     @Nullable
getPendingIntent()104     public PendingIntent getPendingIntent() {
105         return mPendingIntent;
106     }
107 
108     /** Returns the user handle of the tap action. */
109     @Nullable
getUserHandle()110     public UserHandle getUserHandle() {
111         return mUserHandle;
112     }
113 
114     /** Returns the extras bundle of the tap action. */
115     @Nullable
116     @SuppressLint("NullableCollection")
getExtras()117     public Bundle getExtras() {
118         return mExtras;
119     }
120 
121     /**
122      * Whether the tap action's result should be shown on the lockscreen. If true, the tap action's
123      * handling should bypass the keyguard. Default value is false.
124      */
shouldShowOnLockscreen()125     public boolean shouldShowOnLockscreen() {
126         return mShouldShowOnLockscreen;
127     }
128 
129     @Override
writeToParcel(@onNull Parcel out, int flags)130     public void writeToParcel(@NonNull Parcel out, int flags) {
131         TextUtils.writeToParcel(mId, out, flags);
132         out.writeTypedObject(mIntent, flags);
133         out.writeTypedObject(mPendingIntent, flags);
134         out.writeTypedObject(mUserHandle, flags);
135         out.writeBundle(mExtras);
136         out.writeBoolean(mShouldShowOnLockscreen);
137     }
138 
139     @Override
describeContents()140     public int describeContents() {
141         return 0;
142     }
143 
144     @NonNull
145     public static final Creator<TapAction> CREATOR = new Creator<TapAction>() {
146         @Override
147         public TapAction createFromParcel(Parcel in) {
148             return new TapAction(in);
149         }
150 
151         @Override
152         public TapAction[] newArray(int size) {
153             return new TapAction[size];
154         }
155     };
156 
157     @Override
equals(Object o)158     public boolean equals(Object o) {
159         if (this == o) return true;
160         if (!(o instanceof TapAction)) return false;
161         TapAction that = (TapAction) o;
162         return SmartspaceUtils.isEqual(mId, that.mId);
163     }
164 
165     @Override
hashCode()166     public int hashCode() {
167         return Objects.hash(mId);
168     }
169 
170     @Override
toString()171     public String toString() {
172         return "SmartspaceTapAction{"
173                 + "mId=" + mId
174                 + "mIntent=" + mIntent
175                 + ", mPendingIntent=" + mPendingIntent
176                 + ", mUserHandle=" + mUserHandle
177                 + ", mExtras=" + mExtras
178                 + ", mShouldShowOnLockscreen=" + mShouldShowOnLockscreen
179                 + '}';
180     }
181 
182     /**
183      * A builder for {@link TapAction} object.
184      *
185      * @hide
186      */
187     @SystemApi
188     public static final class Builder {
189 
190         private CharSequence mId;
191         private Intent mIntent;
192         private PendingIntent mPendingIntent;
193         private UserHandle mUserHandle;
194         private Bundle mExtras;
195         private boolean mShouldShowOnLockScreen;
196 
197         /**
198          * A builder for {@link TapAction}. By default sets should_show_on_lockscreen to false.
199          *
200          * @param id A unique Id of this {@link TapAction}.
201          */
Builder(@onNull CharSequence id)202         public Builder(@NonNull CharSequence id) {
203             mId = Objects.requireNonNull(id);
204             mShouldShowOnLockScreen = false;
205         }
206 
207         /**
208          * Sets the action intent.
209          */
210         @NonNull
setIntent(@onNull Intent intent)211         public Builder setIntent(@NonNull Intent intent) {
212             mIntent = intent;
213             return this;
214         }
215 
216         /**
217          * Sets the pending intent.
218          */
219         @NonNull
setPendingIntent(@onNull PendingIntent pendingIntent)220         public Builder setPendingIntent(@NonNull PendingIntent pendingIntent) {
221             mPendingIntent = pendingIntent;
222             return this;
223         }
224 
225         /**
226          * Sets the user handle.
227          */
228         @NonNull
229         @SuppressLint("UserHandleName")
setUserHandle(@ullable UserHandle userHandle)230         public Builder setUserHandle(@Nullable UserHandle userHandle) {
231             mUserHandle = userHandle;
232             return this;
233         }
234 
235         /**
236          * Sets the extras.
237          */
238         @NonNull
setExtras(@onNull Bundle extras)239         public Builder setExtras(@NonNull Bundle extras) {
240             mExtras = extras;
241             return this;
242         }
243 
244         /**
245          * Sets whether the tap action's result should be shown on the lockscreen, to bypass the
246          * keyguard when the tap action is triggered.
247          */
248         @NonNull
setShouldShowOnLockscreen(@onNull boolean shouldShowOnLockScreen)249         public Builder setShouldShowOnLockscreen(@NonNull boolean shouldShowOnLockScreen) {
250             mShouldShowOnLockScreen = shouldShowOnLockScreen;
251             return this;
252         }
253 
254         /**
255          * Builds a new SmartspaceTapAction instance.
256          *
257          * @throws IllegalStateException if the tap action is empty.
258          */
259         @NonNull
build()260         public TapAction build() {
261             if (mIntent == null && mPendingIntent == null && mExtras == null) {
262                 throw new IllegalStateException("Please assign at least 1 valid tap field");
263             }
264             return new TapAction(mId, mIntent, mPendingIntent, mUserHandle, mExtras,
265                     mShouldShowOnLockScreen);
266         }
267     }
268 }
269