1 /* 2 * Copyright (C) 2016 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.search; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.SuppressLint; 22 import android.annotation.SystemApi; 23 import android.app.PendingIntent; 24 import android.content.Intent; 25 import android.graphics.drawable.Icon; 26 import android.os.Bundle; 27 import android.os.Parcel; 28 import android.os.Parcelable; 29 import android.os.UserHandle; 30 import android.text.TextUtils; 31 32 import java.util.Objects; 33 34 /** 35 * Represents a searchable action info that can be called from another process 36 * or within the client process. 37 * 38 * @hide 39 */ 40 @SystemApi 41 public final class SearchAction implements Parcelable { 42 43 private static final String TAG = "SearchAction"; 44 45 @NonNull 46 private String mId; 47 48 @Nullable 49 private final Icon mIcon; 50 51 @NonNull 52 private final CharSequence mTitle; 53 54 @Nullable 55 private final CharSequence mSubtitle; 56 57 @Nullable 58 private final CharSequence mContentDescription; 59 60 @Nullable 61 private final PendingIntent mPendingIntent; 62 63 @Nullable 64 private final Intent mIntent; 65 66 @Nullable 67 private final UserHandle mUserHandle; 68 69 @Nullable 70 private final Bundle mExtras; 71 SearchAction(Parcel in)72 SearchAction(Parcel in) { 73 mId = in.readString(); 74 mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 75 mIcon = in.readTypedObject(Icon.CREATOR); 76 mSubtitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 77 mContentDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 78 mPendingIntent = in.readTypedObject(PendingIntent.CREATOR); 79 mIntent = in.readTypedObject(Intent.CREATOR); 80 mUserHandle = in.readTypedObject(UserHandle.CREATOR); 81 mExtras = in.readTypedObject(Bundle.CREATOR); 82 } 83 SearchAction( @onNull String id, @NonNull CharSequence title, @Nullable Icon icon, @Nullable CharSequence subtitle, @Nullable CharSequence contentDescription, @Nullable PendingIntent pendingIntent, @Nullable Intent intent, @Nullable UserHandle userHandle, @Nullable Bundle extras)84 private SearchAction( 85 @NonNull String id, 86 @NonNull CharSequence title, 87 @Nullable Icon icon, 88 @Nullable CharSequence subtitle, 89 @Nullable CharSequence contentDescription, 90 @Nullable PendingIntent pendingIntent, 91 @Nullable Intent intent, 92 @Nullable UserHandle userHandle, 93 @Nullable Bundle extras) { 94 mId = Objects.requireNonNull(id); 95 mTitle = Objects.requireNonNull(title); 96 mIcon = icon; 97 mSubtitle = subtitle; 98 mContentDescription = contentDescription; 99 mPendingIntent = pendingIntent; 100 mIntent = intent; 101 mUserHandle = userHandle; 102 mExtras = extras != null ? extras : new Bundle(); 103 104 if (mPendingIntent == null && mIntent == null) { 105 throw new IllegalStateException("At least one type of intent should be available."); 106 } 107 if (mPendingIntent != null && mIntent != null) { 108 throw new IllegalStateException("Only one type of intent should be available."); 109 } 110 } 111 112 /** 113 * Returns the unique id of this object. 114 */ getId()115 public @NonNull String getId() { 116 return mId; 117 } 118 119 /** 120 * Returns an icon representing the action. 121 */ getIcon()122 public @Nullable Icon getIcon() { 123 return mIcon; 124 } 125 126 /** 127 * Returns a title representing the action. 128 */ getTitle()129 public @NonNull CharSequence getTitle() { 130 return mTitle; 131 } 132 133 /** 134 * Returns a subtitle representing the action. 135 */ getSubtitle()136 public @Nullable CharSequence getSubtitle() { 137 return mSubtitle; 138 } 139 140 /** 141 * Returns a content description representing the action. 142 */ getContentDescription()143 public @Nullable CharSequence getContentDescription() { 144 return mContentDescription; 145 } 146 147 /** 148 * Returns the action intent. 149 */ getPendingIntent()150 public @Nullable PendingIntent getPendingIntent() { 151 return mPendingIntent; 152 } 153 154 /** 155 * Returns the intent. 156 */ getIntent()157 public @Nullable Intent getIntent() { 158 return mIntent; 159 } 160 161 /** 162 * Returns the user handle. 163 */ getUserHandle()164 public @Nullable UserHandle getUserHandle() { 165 return mUserHandle; 166 } 167 168 /** 169 * Returns the extra bundle for this object. 170 */ 171 @SuppressLint("NullableCollection") getExtras()172 public @Nullable Bundle getExtras() { 173 return mExtras; 174 } 175 176 @Override equals(Object o)177 public boolean equals(Object o) { 178 if (this == o) return true; 179 if (!(o instanceof SearchAction)) return false; 180 SearchAction that = (SearchAction) o; 181 return mId.equals(that.mId) && mTitle.equals(that.mTitle); 182 } 183 184 @Override hashCode()185 public int hashCode() { 186 return Objects.hash(mId, mTitle); 187 } 188 189 @Override describeContents()190 public int describeContents() { 191 return 0; 192 } 193 194 @Override writeToParcel(@onNull Parcel out, int flags)195 public void writeToParcel(@NonNull Parcel out, int flags) { 196 out.writeString(mId); 197 TextUtils.writeToParcel(mTitle, out, flags); 198 out.writeTypedObject(mIcon, flags); 199 TextUtils.writeToParcel(mSubtitle, out, flags); 200 TextUtils.writeToParcel(mContentDescription, out, flags); 201 out.writeTypedObject(mPendingIntent, flags); 202 out.writeTypedObject(mIntent, flags); 203 out.writeTypedObject(mUserHandle, flags); 204 out.writeTypedObject(mExtras, flags); 205 } 206 207 @Override toString()208 public String toString() { 209 String str = "id=" + mId 210 + " title=" + mTitle 211 + " contentDescription=" + mContentDescription 212 + " subtitle=" + mSubtitle 213 + " icon=" + mIcon 214 + " pendingIntent=" + (mPendingIntent == null ? "" : mPendingIntent.getIntent()) 215 + " intent=" + mIntent 216 + " userHandle=" + mUserHandle; 217 return str; 218 } 219 220 public static final @android.annotation.NonNull Parcelable.Creator<SearchAction> CREATOR = 221 new Parcelable.Creator<SearchAction>() { 222 public SearchAction createFromParcel(Parcel in) { 223 return new SearchAction(in); 224 } 225 public SearchAction[] newArray(int size) { 226 return new SearchAction[size]; 227 } 228 }; 229 230 /** 231 * A builder for search action object. 232 * 233 * @hide 234 */ 235 @SystemApi 236 public static final class Builder { 237 @NonNull 238 private String mId; 239 240 @NonNull 241 private CharSequence mTitle; 242 243 @Nullable 244 private Icon mIcon; 245 246 @Nullable 247 private CharSequence mSubtitle; 248 249 @Nullable 250 private CharSequence mContentDescription; 251 252 @Nullable 253 private PendingIntent mPendingIntent; 254 255 @Nullable 256 private Intent mIntent; 257 258 @Nullable 259 private UserHandle mUserHandle; 260 261 @Nullable 262 private Bundle mExtras; 263 Builder(@onNull String id, @NonNull String title)264 public Builder(@NonNull String id, @NonNull String title) { 265 mId = Objects.requireNonNull(id); 266 mTitle = Objects.requireNonNull(title); 267 } 268 269 /** 270 * Sets the subtitle. 271 */ 272 @NonNull setIcon( @ullable Icon icon)273 public SearchAction.Builder setIcon( 274 @Nullable Icon icon) { 275 mIcon = icon; 276 return this; 277 } 278 279 /** 280 * Sets the subtitle. 281 */ 282 @NonNull setSubtitle( @ullable CharSequence subtitle)283 public SearchAction.Builder setSubtitle( 284 @Nullable CharSequence subtitle) { 285 mSubtitle = subtitle; 286 return this; 287 } 288 289 /** 290 * Sets the content description. 291 */ 292 @NonNull setContentDescription( @ullable CharSequence contentDescription)293 public SearchAction.Builder setContentDescription( 294 @Nullable CharSequence contentDescription) { 295 mContentDescription = contentDescription; 296 return this; 297 } 298 299 /** 300 * Sets the pending intent. 301 */ 302 @NonNull setPendingIntent(@ullable PendingIntent pendingIntent)303 public SearchAction.Builder setPendingIntent(@Nullable PendingIntent pendingIntent) { 304 mPendingIntent = pendingIntent; 305 return this; 306 } 307 308 /** 309 * Sets the user handle. 310 */ 311 @NonNull setUserHandle(@ullable UserHandle userHandle)312 public SearchAction.Builder setUserHandle(@Nullable UserHandle userHandle) { 313 mUserHandle = userHandle; 314 return this; 315 } 316 317 /** 318 * Sets the intent. 319 */ 320 @NonNull setIntent(@ullable Intent intent)321 public SearchAction.Builder setIntent(@Nullable Intent intent) { 322 mIntent = intent; 323 return this; 324 } 325 326 /** 327 * Sets the extra. 328 */ 329 @NonNull setExtras( @uppressLintR) @ullable Bundle extras)330 public SearchAction.Builder setExtras( 331 @SuppressLint("NullableCollection") @Nullable Bundle extras) { 332 mExtras = extras; 333 return this; 334 } 335 336 /** 337 * Builds a new SearchAction instance. 338 * 339 * @throws IllegalStateException if no target is set 340 */ 341 @NonNull build()342 public SearchAction build() { 343 return new SearchAction(mId, mTitle, mIcon, mSubtitle, mContentDescription, 344 mPendingIntent, mIntent, mUserHandle, mExtras); 345 } 346 } 347 } 348