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