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 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.annotation.SuppressLint; 22 import android.annotation.SystemApi; 23 import android.app.smartspace.SmartspaceTarget.FeatureType; 24 import android.app.smartspace.SmartspaceTarget.UiTemplateType; 25 import android.app.smartspace.SmartspaceUtils; 26 import android.os.Parcel; 27 import android.os.Parcelable; 28 import android.text.TextUtils; 29 30 import java.util.Objects; 31 32 /** 33 * Holds all the relevant data needed to render a Smartspace card with the default Ui Template. 34 * <ul> 35 * <li> title_text (may contain a start drawable) </li> 36 * <li> subtitle_text (may contain a start drawable) . supplemental_subtitle_text (may 37 * contain a start drawable) </li> 38 * 39 * <li> supplemental_text (contain a start drawable) . do_not_disturb_view </li> 40 * Or 41 * <li> next_alarm_text (contain a start drawable) + supplemental_alarm_text . 42 * do_not_disturb_view </li> 43 * </ul> 44 * 45 * @hide 46 */ 47 @SystemApi 48 @SuppressLint("ParcelNotFinal") 49 public class BaseTemplateData implements Parcelable { 50 51 /** 52 * {@link UiTemplateType} indicating the template type of this template data. 53 * 54 * @see UiTemplateType 55 */ 56 @UiTemplateType 57 private final int mTemplateType; 58 59 /** 60 * Title text and title icon are shown at the first row. When both are absent, the date view 61 * will be used, which has its own tap action applied to the title area. 62 * 63 * Primary tap action for the entire card, including the blank spaces, except: 1. When title is 64 * absent, the date view's default tap action is used; 2. Subtitle/Supplemental subtitle uses 65 * its own tap action if being set; 3. Secondary card uses its own tap action if being set. 66 */ 67 @Nullable 68 private final SubItemInfo mPrimaryItem; 69 70 71 /** Subtitle text and icon are shown at the second row. */ 72 @Nullable 73 private final SubItemInfo mSubtitleItem; 74 75 /** 76 * Supplemental subtitle text and icon are shown at the second row following the subtitle text. 77 * Mainly used for weather info on non-weather card. 78 */ 79 @Nullable 80 private final SubItemInfo mSubtitleSupplementalItem; 81 82 /** 83 * Supplemental line is shown at the third row. 84 */ 85 @Nullable 86 private final SubItemInfo mSupplementalLineItem; 87 88 /** 89 * Supplemental alarm item is specifically used for holiday alarm, which is appended to "next 90 * alarm". This is also shown at the third row, but won't be shown the same time with 91 * mSupplementalLineItem. 92 */ 93 @Nullable 94 private final SubItemInfo mSupplementalAlarmItem; 95 96 /** 97 * The layout weight info for the card, which indicates how much space it should occupy on the 98 * screen. Default weight is 0. 99 */ 100 private final int mLayoutWeight; 101 BaseTemplateData(@onNull Parcel in)102 BaseTemplateData(@NonNull Parcel in) { 103 mTemplateType = in.readInt(); 104 mPrimaryItem = in.readTypedObject(SubItemInfo.CREATOR); 105 mSubtitleItem = in.readTypedObject(SubItemInfo.CREATOR); 106 mSubtitleSupplementalItem = in.readTypedObject(SubItemInfo.CREATOR); 107 mSupplementalLineItem = in.readTypedObject(SubItemInfo.CREATOR); 108 mSupplementalAlarmItem = in.readTypedObject(SubItemInfo.CREATOR); 109 mLayoutWeight = in.readInt(); 110 } 111 112 /** 113 * Should ONLY used by subclasses. For the general instance creation, please use 114 * SmartspaceDefaultUiTemplateData.Builder. 115 */ BaseTemplateData(@iTemplateType int templateType, @Nullable SubItemInfo primaryItem, @Nullable SubItemInfo subtitleItem, @Nullable SubItemInfo subtitleSupplementalItem, @Nullable SubItemInfo supplementalLineItem, @Nullable SubItemInfo supplementalAlarmItem, int layoutWeight)116 BaseTemplateData(@UiTemplateType int templateType, 117 @Nullable SubItemInfo primaryItem, 118 @Nullable SubItemInfo subtitleItem, 119 @Nullable SubItemInfo subtitleSupplementalItem, 120 @Nullable SubItemInfo supplementalLineItem, 121 @Nullable SubItemInfo supplementalAlarmItem, 122 int layoutWeight) { 123 mTemplateType = templateType; 124 mPrimaryItem = primaryItem; 125 mSubtitleItem = subtitleItem; 126 mSubtitleSupplementalItem = subtitleSupplementalItem; 127 mSupplementalLineItem = supplementalLineItem; 128 mSupplementalAlarmItem = supplementalAlarmItem; 129 mLayoutWeight = layoutWeight; 130 } 131 132 /** Returns the template type. By default is UNDEFINED. */ 133 @UiTemplateType getTemplateType()134 public int getTemplateType() { 135 return mTemplateType; 136 } 137 138 /** Returns the primary item (the first line). */ 139 @Nullable getPrimaryItem()140 public SubItemInfo getPrimaryItem() { 141 return mPrimaryItem; 142 } 143 144 /** Returns the subtitle item (the second line). */ 145 @Nullable getSubtitleItem()146 public SubItemInfo getSubtitleItem() { 147 return mSubtitleItem; 148 } 149 150 /** Returns the subtitle's supplemental item (the second line following the subtitle). */ 151 @Nullable getSubtitleSupplementalItem()152 public SubItemInfo getSubtitleSupplementalItem() { 153 return mSubtitleSupplementalItem; 154 } 155 156 /** Returns the supplemental line item (the 3rd line). */ 157 @Nullable getSupplementalLineItem()158 public SubItemInfo getSupplementalLineItem() { 159 return mSupplementalLineItem; 160 } 161 162 /** Returns the supplemental alarm item (the 3rd line). */ 163 @Nullable getSupplementalAlarmItem()164 public SubItemInfo getSupplementalAlarmItem() { 165 return mSupplementalAlarmItem; 166 } 167 168 /** Returns the card layout weight info. Default weight is 0. */ getLayoutWeight()169 public int getLayoutWeight() { 170 return mLayoutWeight; 171 } 172 173 /** 174 * @see Parcelable.Creator 175 */ 176 @NonNull 177 public static final Creator<BaseTemplateData> CREATOR = 178 new Creator<BaseTemplateData>() { 179 @Override 180 public BaseTemplateData createFromParcel(Parcel in) { 181 return new BaseTemplateData(in); 182 } 183 184 @Override 185 public BaseTemplateData[] newArray(int size) { 186 return new BaseTemplateData[size]; 187 } 188 }; 189 190 @Override describeContents()191 public int describeContents() { 192 return 0; 193 } 194 195 @Override writeToParcel(@onNull Parcel out, int flags)196 public void writeToParcel(@NonNull Parcel out, int flags) { 197 out.writeInt(mTemplateType); 198 out.writeTypedObject(mPrimaryItem, flags); 199 out.writeTypedObject(mSubtitleItem, flags); 200 out.writeTypedObject(mSubtitleSupplementalItem, flags); 201 out.writeTypedObject(mSupplementalLineItem, flags); 202 out.writeTypedObject(mSupplementalAlarmItem, flags); 203 out.writeInt(mLayoutWeight); 204 } 205 206 @Override equals(Object o)207 public boolean equals(Object o) { 208 if (this == o) return true; 209 if (!(o instanceof BaseTemplateData)) return false; 210 BaseTemplateData that = (BaseTemplateData) o; 211 return mTemplateType == that.mTemplateType && mLayoutWeight == that.mLayoutWeight 212 && Objects.equals(mPrimaryItem, that.mPrimaryItem) 213 && Objects.equals(mSubtitleItem, that.mSubtitleItem) 214 && Objects.equals(mSubtitleSupplementalItem, that.mSubtitleSupplementalItem) 215 && Objects.equals(mSupplementalLineItem, that.mSupplementalLineItem) 216 && Objects.equals(mSupplementalAlarmItem, that.mSupplementalAlarmItem); 217 } 218 219 @Override hashCode()220 public int hashCode() { 221 return Objects.hash(mTemplateType, mPrimaryItem, mSubtitleItem, mSubtitleSupplementalItem, 222 mSupplementalLineItem, mSupplementalAlarmItem, mLayoutWeight); 223 } 224 225 @Override toString()226 public String toString() { 227 return "BaseTemplateData{" 228 + "mTemplateType=" + mTemplateType 229 + ", mPrimaryItem=" + mPrimaryItem 230 + ", mSubtitleItem=" + mSubtitleItem 231 + ", mSubtitleSupplementalItem=" + mSubtitleSupplementalItem 232 + ", mSupplementalLineItem=" + mSupplementalLineItem 233 + ", mSupplementalAlarmItem=" + mSupplementalAlarmItem 234 + ", mLayoutWeight=" + mLayoutWeight 235 + '}'; 236 } 237 238 /** 239 * A builder for {@link BaseTemplateData} object. 240 * 241 * @hide 242 */ 243 @SystemApi 244 @SuppressLint("StaticFinalBuilder") 245 public static class Builder { 246 @UiTemplateType 247 private final int mTemplateType; 248 249 private SubItemInfo mPrimaryItem; 250 private SubItemInfo mSubtitleItem; 251 private SubItemInfo mSubtitleSupplementalItem; 252 private SubItemInfo mSupplementalLineItem; 253 private SubItemInfo mSupplementalAlarmItem; 254 private int mLayoutWeight; 255 256 /** 257 * A builder for {@link BaseTemplateData}. By default sets the layout weight to be 0. 258 * 259 * @param templateType the {@link UiTemplateType} of this template data. 260 */ Builder(@iTemplateType int templateType)261 public Builder(@UiTemplateType int templateType) { 262 mTemplateType = templateType; 263 mLayoutWeight = 0; 264 } 265 266 /** Should ONLY be used by the subclasses */ 267 @UiTemplateType 268 @SuppressLint("GetterOnBuilder") getTemplateType()269 int getTemplateType() { 270 return mTemplateType; 271 } 272 273 /** Should ONLY be used by the subclasses */ 274 @Nullable 275 @SuppressLint("GetterOnBuilder") getPrimaryItem()276 SubItemInfo getPrimaryItem() { 277 return mPrimaryItem; 278 } 279 280 /** Should ONLY be used by the subclasses */ 281 @Nullable 282 @SuppressLint("GetterOnBuilder") getSubtitleItem()283 SubItemInfo getSubtitleItem() { 284 return mSubtitleItem; 285 } 286 287 /** Should ONLY be used by the subclasses */ 288 @Nullable 289 @SuppressLint("GetterOnBuilder") getSubtitleSupplemtnalItem()290 SubItemInfo getSubtitleSupplemtnalItem() { 291 return mSubtitleSupplementalItem; 292 } 293 294 /** Should ONLY be used by the subclasses */ 295 @Nullable 296 @SuppressLint("GetterOnBuilder") getSupplementalLineItem()297 SubItemInfo getSupplementalLineItem() { 298 return mSupplementalLineItem; 299 } 300 301 /** Should ONLY be used by the subclasses */ 302 @Nullable 303 @SuppressLint("GetterOnBuilder") getSupplementalAlarmItem()304 SubItemInfo getSupplementalAlarmItem() { 305 return mSupplementalAlarmItem; 306 } 307 308 /** Should ONLY be used by the subclasses */ 309 @SuppressLint("GetterOnBuilder") getLayoutWeight()310 int getLayoutWeight() { 311 return mLayoutWeight; 312 } 313 314 /** 315 * Sets the card primary item. 316 */ 317 @NonNull setPrimaryItem(@onNull SubItemInfo primaryItem)318 public Builder setPrimaryItem(@NonNull SubItemInfo primaryItem) { 319 mPrimaryItem = primaryItem; 320 return this; 321 } 322 323 /** 324 * Sets the card subtitle item. 325 */ 326 @NonNull setSubtitleItem(@onNull SubItemInfo subtitleItem)327 public Builder setSubtitleItem(@NonNull SubItemInfo subtitleItem) { 328 mSubtitleItem = subtitleItem; 329 return this; 330 } 331 332 /** 333 * Sets the card subtitle's supplemental item. 334 */ 335 @NonNull setSubtitleSupplementalItem(@onNull SubItemInfo subtitleSupplementalItem)336 public Builder setSubtitleSupplementalItem(@NonNull SubItemInfo subtitleSupplementalItem) { 337 mSubtitleSupplementalItem = subtitleSupplementalItem; 338 return this; 339 } 340 341 /** 342 * Sets the card supplemental line item. 343 */ 344 @NonNull setSupplementalLineItem(@onNull SubItemInfo supplementalLineItem)345 public Builder setSupplementalLineItem(@NonNull SubItemInfo supplementalLineItem) { 346 mSupplementalLineItem = supplementalLineItem; 347 return this; 348 } 349 350 /** 351 * Sets the card supplemental alarm item. 352 */ 353 @NonNull setSupplementalAlarmItem(@onNull SubItemInfo supplementalAlarmItem)354 public Builder setSupplementalAlarmItem(@NonNull SubItemInfo supplementalAlarmItem) { 355 mSupplementalAlarmItem = supplementalAlarmItem; 356 return this; 357 } 358 359 /** 360 * Sets the layout weight. 361 */ 362 @NonNull setLayoutWeight(int layoutWeight)363 public Builder setLayoutWeight(int layoutWeight) { 364 mLayoutWeight = layoutWeight; 365 return this; 366 } 367 368 /** 369 * Builds a new SmartspaceDefaultUiTemplateData instance. 370 */ 371 @NonNull build()372 public BaseTemplateData build() { 373 return new BaseTemplateData( 374 mTemplateType, 375 mPrimaryItem, 376 mSubtitleItem, 377 mSubtitleSupplementalItem, 378 mSupplementalLineItem, 379 mSupplementalAlarmItem, 380 mLayoutWeight); 381 } 382 } 383 384 /** 385 * Holds all the rendering and logging info needed for a sub item within the base card. 386 */ 387 public static final class SubItemInfo implements Parcelable { 388 389 /** The text information for the subitem, which will be rendered as it's text content. */ 390 @Nullable 391 private final Text mText; 392 393 /** The icon for the subitem, which will be rendered as a drawable in front of the text. */ 394 @Nullable 395 private final Icon mIcon; 396 397 /** The tap action for the subitem. */ 398 @Nullable 399 private final TapAction mTapAction; 400 401 /** The logging info for the subitem. */ 402 @Nullable 403 private final SubItemLoggingInfo mLoggingInfo; 404 SubItemInfo(@onNull Parcel in)405 SubItemInfo(@NonNull Parcel in) { 406 mText = in.readTypedObject(Text.CREATOR); 407 mIcon = in.readTypedObject(Icon.CREATOR); 408 mTapAction = in.readTypedObject(TapAction.CREATOR); 409 mLoggingInfo = in.readTypedObject(SubItemLoggingInfo.CREATOR); 410 } 411 SubItemInfo(@ullable Text text, @Nullable Icon icon, @Nullable TapAction tapAction, @Nullable SubItemLoggingInfo loggingInfo)412 private SubItemInfo(@Nullable Text text, 413 @Nullable Icon icon, 414 @Nullable TapAction tapAction, 415 @Nullable SubItemLoggingInfo loggingInfo) { 416 mText = text; 417 mIcon = icon; 418 mTapAction = tapAction; 419 mLoggingInfo = loggingInfo; 420 } 421 422 /** Returns the subitem's text. */ 423 @Nullable getText()424 public Text getText() { 425 return mText; 426 } 427 428 /** Returns the subitem's icon. */ 429 @Nullable getIcon()430 public Icon getIcon() { 431 return mIcon; 432 } 433 434 /** Returns the subitem's tap action. */ 435 @Nullable getTapAction()436 public TapAction getTapAction() { 437 return mTapAction; 438 } 439 440 /** Returns the subitem's logging info. */ 441 @Nullable getLoggingInfo()442 public SubItemLoggingInfo getLoggingInfo() { 443 return mLoggingInfo; 444 } 445 446 /** 447 * @see Parcelable.Creator 448 */ 449 @NonNull 450 public static final Creator<SubItemInfo> CREATOR = 451 new Creator<SubItemInfo>() { 452 @Override 453 public SubItemInfo createFromParcel(Parcel in) { 454 return new SubItemInfo(in); 455 } 456 457 @Override 458 public SubItemInfo[] newArray(int size) { 459 return new SubItemInfo[size]; 460 } 461 }; 462 463 @Override describeContents()464 public int describeContents() { 465 return 0; 466 } 467 468 @Override writeToParcel(@onNull Parcel out, int flags)469 public void writeToParcel(@NonNull Parcel out, int flags) { 470 out.writeTypedObject(mText, flags); 471 out.writeTypedObject(mIcon, flags); 472 out.writeTypedObject(mTapAction, flags); 473 out.writeTypedObject(mLoggingInfo, flags); 474 } 475 476 @Override equals(Object o)477 public boolean equals(Object o) { 478 if (this == o) return true; 479 if (!(o instanceof SubItemInfo)) return false; 480 SubItemInfo that = (SubItemInfo) o; 481 return SmartspaceUtils.isEqual(mText, that.mText) && Objects.equals(mIcon, 482 that.mIcon) && Objects.equals(mTapAction, that.mTapAction) 483 && Objects.equals(mLoggingInfo, that.mLoggingInfo); 484 } 485 486 @Override hashCode()487 public int hashCode() { 488 return Objects.hash(mText, mIcon, mTapAction, mLoggingInfo); 489 } 490 491 @Override toString()492 public String toString() { 493 return "SubItemInfo{" 494 + "mText=" + mText 495 + ", mIcon=" + mIcon 496 + ", mTapAction=" + mTapAction 497 + ", mLoggingInfo=" + mLoggingInfo 498 + '}'; 499 } 500 501 /** 502 * A builder for {@link SubItemInfo} object. 503 * 504 * @hide 505 */ 506 @SystemApi 507 public static final class Builder { 508 509 private Text mText; 510 private Icon mIcon; 511 private TapAction mTapAction; 512 private SubItemLoggingInfo mLoggingInfo; 513 514 /** 515 * Sets the sub item's text. 516 */ 517 @NonNull setText(@onNull Text text)518 public Builder setText(@NonNull Text text) { 519 mText = text; 520 return this; 521 } 522 523 /** 524 * Sets the sub item's icon. 525 */ 526 @NonNull setIcon(@onNull Icon icon)527 public Builder setIcon(@NonNull Icon icon) { 528 mIcon = icon; 529 return this; 530 } 531 532 /** 533 * Sets the sub item's tap action. 534 */ 535 @NonNull setTapAction(@onNull TapAction tapAction)536 public Builder setTapAction(@NonNull TapAction tapAction) { 537 mTapAction = tapAction; 538 return this; 539 } 540 541 /** 542 * Sets the sub item's logging info. 543 */ 544 @NonNull setLoggingInfo(@onNull SubItemLoggingInfo loggingInfo)545 public Builder setLoggingInfo(@NonNull SubItemLoggingInfo loggingInfo) { 546 mLoggingInfo = loggingInfo; 547 return this; 548 } 549 550 /** 551 * Builds a new {@link SubItemInfo} instance. 552 * 553 * @throws IllegalStateException if all the data field is empty. 554 */ 555 @NonNull build()556 public SubItemInfo build() { 557 if (SmartspaceUtils.isEmpty(mText) && mIcon == null && mTapAction == null 558 && mLoggingInfo == null) { 559 throw new IllegalStateException("SubItem data is empty"); 560 } 561 562 return new SubItemInfo(mText, mIcon, mTapAction, mLoggingInfo); 563 } 564 } 565 } 566 567 /** 568 * Holds all the logging info needed for a sub item within the base card. For example, the 569 * supplemental-subtitle part should have its own logging info. 570 */ 571 public static final class SubItemLoggingInfo implements Parcelable { 572 573 /** A unique instance id for the sub item. */ 574 private final int mInstanceId; 575 576 /** 577 * {@link FeatureType} indicating the feature type of this subitem. 578 * 579 * @see FeatureType 580 */ 581 @FeatureType 582 private final int mFeatureType; 583 584 /** The data source's package name for this sub item. */ 585 @Nullable 586 private final CharSequence mPackageName; 587 SubItemLoggingInfo(@onNull Parcel in)588 SubItemLoggingInfo(@NonNull Parcel in) { 589 mInstanceId = in.readInt(); 590 mFeatureType = in.readInt(); 591 mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); 592 } 593 SubItemLoggingInfo(int instanceId, @FeatureType int featureType, @Nullable CharSequence packageName)594 private SubItemLoggingInfo(int instanceId, @FeatureType int featureType, 595 @Nullable CharSequence packageName) { 596 mInstanceId = instanceId; 597 mFeatureType = featureType; 598 mPackageName = packageName; 599 } 600 getInstanceId()601 public int getInstanceId() { 602 return mInstanceId; 603 } 604 605 @FeatureType getFeatureType()606 public int getFeatureType() { 607 return mFeatureType; 608 } 609 610 @Nullable getPackageName()611 public CharSequence getPackageName() { 612 return mPackageName; 613 } 614 615 /** 616 * @see Parcelable.Creator 617 */ 618 @NonNull 619 public static final Creator<SubItemLoggingInfo> CREATOR = 620 new Creator<SubItemLoggingInfo>() { 621 @Override 622 public SubItemLoggingInfo createFromParcel(Parcel in) { 623 return new SubItemLoggingInfo(in); 624 } 625 626 @Override 627 public SubItemLoggingInfo[] newArray(int size) { 628 return new SubItemLoggingInfo[size]; 629 } 630 }; 631 632 @Override describeContents()633 public int describeContents() { 634 return 0; 635 } 636 637 @Override writeToParcel(@onNull Parcel out, int flags)638 public void writeToParcel(@NonNull Parcel out, int flags) { 639 out.writeInt(mInstanceId); 640 out.writeInt(mFeatureType); 641 TextUtils.writeToParcel(mPackageName, out, flags); 642 } 643 644 @Override equals(Object o)645 public boolean equals(Object o) { 646 if (this == o) return true; 647 if (!(o instanceof SubItemLoggingInfo)) return false; 648 SubItemLoggingInfo that = (SubItemLoggingInfo) o; 649 return mInstanceId == that.mInstanceId && mFeatureType == that.mFeatureType 650 && SmartspaceUtils.isEqual(mPackageName, that.mPackageName); 651 } 652 653 @Override hashCode()654 public int hashCode() { 655 return Objects.hash(mInstanceId, mFeatureType, mPackageName); 656 } 657 658 @Override toString()659 public String toString() { 660 return "SubItemLoggingInfo{" 661 + "mInstanceId=" + mInstanceId 662 + ", mFeatureType=" + mFeatureType 663 + ", mPackageName=" + mPackageName 664 + '}'; 665 } 666 667 /** 668 * A builder for {@link SubItemLoggingInfo} object. 669 * 670 * @hide 671 */ 672 @SystemApi 673 public static final class Builder { 674 675 private final int mInstanceId; 676 private final int mFeatureType; 677 private CharSequence mPackageName; 678 679 /** 680 * A builder for {@link SubItemLoggingInfo}. 681 * 682 * @param instanceId A unique instance id for the sub item 683 * @param featureType The feature type id for this sub item 684 */ Builder(int instanceId, @FeatureType int featureType)685 public Builder(int instanceId, @FeatureType int featureType) { 686 mInstanceId = instanceId; 687 mFeatureType = featureType; 688 } 689 690 /** 691 * Sets the sub item's data source package name. 692 */ 693 @NonNull setPackageName(@onNull CharSequence packageName)694 public Builder setPackageName(@NonNull CharSequence packageName) { 695 mPackageName = packageName; 696 return this; 697 } 698 699 /** Builds a new {@link SubItemLoggingInfo} instance. */ 700 @NonNull build()701 public SubItemLoggingInfo build() { 702 return new SubItemLoggingInfo(mInstanceId, mFeatureType, mPackageName); 703 } 704 } 705 } 706 } 707