| /* |
| * Copyright (C) 2020 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package android.app.search; |
| |
| import android.annotation.FloatRange; |
| import android.annotation.IntDef; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.annotation.StringDef; |
| import android.annotation.SystemApi; |
| import android.app.slice.SliceManager; |
| import android.appwidget.AppWidgetProviderInfo; |
| import android.content.pm.PackageManager; |
| import android.content.pm.ShortcutInfo; |
| import android.content.pm.ShortcutManager; |
| import android.net.Uri; |
| import android.os.Bundle; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.os.UserHandle; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.Objects; |
| |
| /** |
| * A representation of a search result. Search result can be expressed in one of the following: |
| * app icon, shortcut, slice, widget, or a custom object using {@link SearchAction}. While |
| * app icon ({@link PackageManager}, shortcut {@link ShortcutManager}, slice {@link SliceManager}, |
| * or widget (@link AppWidgetManager} are published content backed by the system service, |
| * {@link SearchAction} is a custom object that the service can use to send search result to the |
| * client. |
| * |
| * These various types of Android primitives could be defined as {@link SearchResultType}. Some |
| * times, the result type can define the layout type that that this object can be rendered in. |
| * (e.g., app widget). Most times, {@link #getLayoutType()} assigned by the service |
| * can recommend which layout this target should be rendered in. |
| * |
| * The service can also use fields such as {@link #getScore()} to indicate |
| * how confidence the search result is and {@link #isHidden()} to indicate |
| * whether it is recommended to be shown by default. |
| * |
| * Finally, {@link #getId()} is the unique identifier of this search target and a single |
| * search target is defined by being able to express a single launcheable item. In case the |
| * service want to recommend how to combine multiple search target objects to render in a group |
| * (e.g., same row), {@link #getParentId()} can be assigned on the sub targets of the group |
| * using the primary search target's identifier. |
| * |
| * @hide |
| */ |
| @SystemApi |
| public final class SearchTarget implements Parcelable { |
| |
| public static final int RESULT_TYPE_APPLICATION = 1 << 0; |
| public static final int RESULT_TYPE_SHORTCUT = 1 << 1; |
| public static final int RESULT_TYPE_SLICE = 1 << 2; |
| public static final int RESULT_TYPE_WIDGETS = 1 << 3; |
| |
| // ------ |
| // | icon | |
| // ------ |
| // text |
| public static final String LAYOUT_TYPE_ICON = "icon"; |
| |
| // ------ ------ ------ |
| // | | title |(opt)| |(opt)| |
| // | icon | subtitle (optional) | icon| | icon| |
| // ------ ------ ------ |
| public static final String LAYOUT_TYPE_ICON_ROW = "icon_row"; |
| |
| // ------ |
| // | icon | title / subtitle (optional) |
| // ------ |
| public static final String LAYOUT_TYPE_SHORT_ICON_ROW = "short_icon_row"; |
| |
| /** |
| * @hide |
| */ |
| @IntDef(prefix = {"RESULT_TYPE_"}, value = { |
| RESULT_TYPE_APPLICATION, |
| RESULT_TYPE_SHORTCUT, |
| RESULT_TYPE_SLICE, |
| RESULT_TYPE_WIDGETS |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface SearchResultType {} |
| private final int mResultType; |
| |
| /** |
| * @hide |
| */ |
| @StringDef(prefix = {"LAYOUT_TYPE_"}, value = { |
| LAYOUT_TYPE_ICON, |
| LAYOUT_TYPE_ICON_ROW, |
| LAYOUT_TYPE_SHORT_ICON_ROW, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface SearchLayoutType {} |
| |
| /** |
| * Constant to express how the group of {@link SearchTarget} should be rendered on |
| * the client side. (e.g., "icon", "icon_row", "short_icon_row") |
| */ |
| @NonNull |
| private final String mLayoutType; |
| |
| @NonNull |
| private final String mId; |
| |
| @Nullable |
| private String mParentId; |
| |
| private final float mScore; |
| |
| private final boolean mHidden; |
| |
| @NonNull |
| private final String mPackageName; |
| @NonNull |
| private final UserHandle mUserHandle; |
| @Nullable |
| private final SearchAction mSearchAction; |
| @Nullable |
| private final ShortcutInfo mShortcutInfo; |
| @Nullable |
| private final AppWidgetProviderInfo mAppWidgetProviderInfo; |
| @Nullable |
| private final Uri mSliceUri; |
| |
| @NonNull |
| private final Bundle mExtras; |
| |
| private SearchTarget(Parcel parcel) { |
| mResultType = parcel.readInt(); |
| mLayoutType = parcel.readString(); |
| mId = parcel.readString(); |
| mParentId = parcel.readString(); |
| mScore = parcel.readFloat(); |
| mHidden = parcel.readBoolean(); |
| |
| mPackageName = parcel.readString(); |
| mUserHandle = UserHandle.of(parcel.readInt()); |
| mSearchAction = parcel.readTypedObject(SearchAction.CREATOR); |
| mShortcutInfo = parcel.readTypedObject(ShortcutInfo.CREATOR); |
| mAppWidgetProviderInfo = parcel.readTypedObject(AppWidgetProviderInfo.CREATOR); |
| mSliceUri = parcel.readTypedObject(Uri.CREATOR); |
| mExtras = parcel.readBundle(getClass().getClassLoader()); |
| } |
| |
| private SearchTarget( |
| int resultType, |
| @NonNull String layoutType, |
| @NonNull String id, |
| @Nullable String parentId, |
| float score, boolean hidden, |
| @NonNull String packageName, |
| @NonNull UserHandle userHandle, |
| @Nullable SearchAction action, |
| @Nullable ShortcutInfo shortcutInfo, |
| @Nullable Uri sliceUri, |
| @Nullable AppWidgetProviderInfo appWidgetProviderInfo, |
| @NonNull Bundle extras) { |
| mResultType = resultType; |
| mLayoutType = Objects.requireNonNull(layoutType); |
| mId = Objects.requireNonNull(id); |
| mParentId = parentId; |
| mScore = score; |
| mHidden = hidden; |
| mPackageName = Objects.requireNonNull(packageName); |
| mUserHandle = Objects.requireNonNull(userHandle); |
| mSearchAction = action; |
| mShortcutInfo = shortcutInfo; |
| mAppWidgetProviderInfo = appWidgetProviderInfo; |
| mSliceUri = sliceUri; |
| mExtras = extras != null ? extras : new Bundle(); |
| |
| int published = 0; |
| if (mSearchAction != null) published++; |
| if (mShortcutInfo != null) published++; |
| if (mAppWidgetProviderInfo != null) published++; |
| if (mSliceUri != null) published++; |
| if (published > 1) { |
| throw new IllegalStateException("Only one of SearchAction, ShortcutInfo," |
| + " AppWidgetProviderInfo, SliceUri can be assigned in a SearchTarget."); |
| } |
| } |
| |
| /** |
| * Retrieves the result type {@see SearchResultType}. |
| */ |
| public @SearchResultType int getResultType() { |
| return mResultType; |
| } |
| |
| /** |
| * Retrieves the layout type. |
| */ |
| @NonNull |
| public @SearchLayoutType String getLayoutType() { |
| return mLayoutType; |
| } |
| |
| /** |
| * Retrieves the id of the target. |
| */ |
| @NonNull |
| public String getId() { |
| return mId; |
| } |
| |
| /** |
| * Retrieves the parent id of the target. |
| */ |
| @NonNull |
| public String getParentId() { |
| return mParentId; |
| } |
| |
| /** |
| * Retrieves the score of the target. |
| */ |
| public float getScore() { |
| return mScore; |
| } |
| |
| /** |
| * Indicates whether this object should be hidden and shown only on demand. |
| * |
| * @deprecated will be removed once SDK drops |
| * @removed |
| */ |
| @Deprecated |
| public boolean shouldHide() { |
| return mHidden; |
| } |
| |
| /** |
| * Indicates whether this object should be hidden and shown only on demand. |
| */ |
| public boolean isHidden() { |
| return mHidden; |
| } |
| |
| /** |
| * Retrieves the package name of the target. |
| */ |
| @NonNull |
| public String getPackageName() { |
| return mPackageName; |
| } |
| |
| /** |
| * Retrieves the user handle of the target. |
| */ |
| @NonNull |
| public UserHandle getUserHandle() { |
| return mUserHandle; |
| } |
| |
| /** |
| * Retrieves the shortcut info of the target. |
| */ |
| @Nullable |
| public ShortcutInfo getShortcutInfo() { |
| return mShortcutInfo; |
| } |
| |
| /** |
| * Return a widget provider info. |
| */ |
| @Nullable |
| public AppWidgetProviderInfo getAppWidgetProviderInfo() { |
| return mAppWidgetProviderInfo; |
| } |
| |
| /** |
| * Returns a slice uri. |
| */ |
| @Nullable |
| public Uri getSliceUri() { |
| return mSliceUri; |
| } |
| |
| /** |
| * Returns a search action. |
| */ |
| @Nullable |
| public SearchAction getSearchAction() { |
| return mSearchAction; |
| } |
| |
| /** |
| * Return extra bundle. |
| */ |
| @NonNull |
| public Bundle getExtras() { |
| return mExtras; |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(@NonNull Parcel parcel, int flags) { |
| parcel.writeInt(mResultType); |
| parcel.writeString(mLayoutType); |
| parcel.writeString(mId); |
| parcel.writeString(mParentId); |
| parcel.writeFloat(mScore); |
| parcel.writeBoolean(mHidden); |
| parcel.writeString(mPackageName); |
| parcel.writeInt(mUserHandle.getIdentifier()); |
| parcel.writeTypedObject(mSearchAction, flags); |
| parcel.writeTypedObject(mShortcutInfo, flags); |
| parcel.writeTypedObject(mAppWidgetProviderInfo, flags); |
| parcel.writeTypedObject(mSliceUri, flags); |
| parcel.writeBundle(mExtras); |
| } |
| |
| /** |
| * @see Parcelable.Creator |
| */ |
| @NonNull |
| public static final Parcelable.Creator<SearchTarget> CREATOR = |
| new Parcelable.Creator<SearchTarget>() { |
| public SearchTarget createFromParcel(Parcel parcel) { |
| return new SearchTarget(parcel); |
| } |
| |
| public SearchTarget[] newArray(int size) { |
| return new SearchTarget[size]; |
| } |
| }; |
| |
| /** |
| * A builder for search target object. |
| * |
| * @hide |
| */ |
| @SystemApi |
| public static final class Builder { |
| private int mResultType; |
| @NonNull |
| private String mLayoutType; |
| @NonNull |
| private String mId; |
| @Nullable |
| private String mParentId; |
| private float mScore; |
| private boolean mHidden; |
| @NonNull |
| private String mPackageName; |
| @NonNull |
| private UserHandle mUserHandle; |
| @Nullable |
| private SearchAction mSearchAction; |
| @Nullable |
| private ShortcutInfo mShortcutInfo; |
| @Nullable |
| private Uri mSliceUri; |
| @Nullable |
| private AppWidgetProviderInfo mAppWidgetProviderInfo; |
| @NonNull |
| private Bundle mExtras; |
| |
| public Builder(@SearchResultType int resultType, |
| @SearchLayoutType @NonNull String layoutType, |
| @NonNull String id) { |
| mId = id; |
| mLayoutType = Objects.requireNonNull(layoutType); |
| mResultType = resultType; |
| mScore = 1f; |
| mHidden = false; |
| } |
| |
| /** |
| * Sets the parent id. |
| */ |
| @NonNull |
| public Builder setParentId(@NonNull String parentId) { |
| mParentId = Objects.requireNonNull(parentId); |
| return this; |
| } |
| |
| /** |
| * Sets the package name. |
| */ |
| @NonNull |
| public Builder setPackageName(@NonNull String packageName) { |
| mPackageName = Objects.requireNonNull(packageName); |
| return this; |
| } |
| |
| /** |
| * Sets the user handle. |
| */ |
| @NonNull |
| public Builder setUserHandle(@NonNull UserHandle userHandle) { |
| mUserHandle = Objects.requireNonNull(userHandle); |
| return this; |
| } |
| |
| /** |
| * Sets the shortcut info. |
| */ |
| @NonNull |
| public Builder setShortcutInfo(@NonNull ShortcutInfo shortcutInfo) { |
| mShortcutInfo = Objects.requireNonNull(shortcutInfo); |
| if (mPackageName != null && !mPackageName.equals(shortcutInfo.getPackage())) { |
| throw new IllegalStateException("SearchTarget packageName is different from " |
| + "shortcut's packageName"); |
| } |
| mPackageName = shortcutInfo.getPackage(); |
| return this; |
| } |
| |
| /** |
| * Sets the app widget provider info. |
| */ |
| @NonNull |
| public Builder setAppWidgetProviderInfo( |
| @NonNull AppWidgetProviderInfo appWidgetProviderInfo) { |
| mAppWidgetProviderInfo = Objects.requireNonNull(appWidgetProviderInfo); |
| if (mPackageName != null |
| && !mPackageName.equals(appWidgetProviderInfo.provider.getPackageName())) { |
| throw new IllegalStateException("SearchTarget packageName is different from " |
| + "appWidgetProviderInfo's packageName"); |
| } |
| return this; |
| } |
| |
| /** |
| * Sets the slice URI. |
| */ |
| @NonNull |
| public Builder setSliceUri(@NonNull Uri sliceUri) { |
| mSliceUri = sliceUri; |
| return this; |
| } |
| |
| /** |
| * Set the {@link SearchAction} object to this target. |
| */ |
| @NonNull |
| public Builder setSearchAction(@Nullable SearchAction searchAction) { |
| mSearchAction = searchAction; |
| return this; |
| } |
| |
| /** |
| * Set any extra information that needs to be shared between service and the client. |
| */ |
| @NonNull |
| public Builder setExtras(@NonNull Bundle extras) { |
| mExtras = Objects.requireNonNull(extras); |
| return this; |
| } |
| |
| /** |
| * Sets the score of the object. |
| */ |
| @NonNull |
| public Builder setScore(@FloatRange(from = 0.0f, to = 1.0f) float score) { |
| mScore = score; |
| return this; |
| } |
| |
| /** |
| * Sets whether the result should be hidden (e.g. not visible) by default inside client. |
| */ |
| @NonNull |
| public Builder setHidden(boolean hidden) { |
| mHidden = hidden; |
| return this; |
| } |
| |
| /** |
| * Sets whether the result should be hidden by default inside client. |
| * @deprecated will be removed once SDK drops |
| * @removed |
| */ |
| @NonNull |
| @Deprecated |
| public Builder setShouldHide(boolean shouldHide) { |
| mHidden = shouldHide; |
| return this; |
| } |
| |
| /** |
| * Builds a new SearchTarget instance. |
| * |
| * @throws IllegalStateException if no target is set |
| */ |
| @NonNull |
| public SearchTarget build() { |
| return new SearchTarget(mResultType, mLayoutType, mId, mParentId, mScore, mHidden, |
| mPackageName, mUserHandle, |
| mSearchAction, mShortcutInfo, mSliceUri, mAppWidgetProviderInfo, |
| mExtras); |
| } |
| } |
| } |