1 /*
2  * Copyright (C) 2018 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 package android.view.textclassifier;
17 
18 import static java.lang.annotation.RetentionPolicy.SOURCE;
19 
20 import android.annotation.FloatRange;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.StringDef;
24 import android.app.RemoteAction;
25 import android.os.Bundle;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 
29 import com.android.internal.util.Preconditions;
30 
31 import java.lang.annotation.Retention;
32 
33 /** Represents the action suggested by a {@link TextClassifier} on a given conversation. */
34 public final class ConversationAction implements Parcelable {
35 
36     /** @hide */
37     @Retention(SOURCE)
38     @StringDef(
39             value = {
40                     TYPE_VIEW_CALENDAR,
41                     TYPE_VIEW_MAP,
42                     TYPE_TRACK_FLIGHT,
43                     TYPE_OPEN_URL,
44                     TYPE_SEND_SMS,
45                     TYPE_CALL_PHONE,
46                     TYPE_SEND_EMAIL,
47                     TYPE_TEXT_REPLY,
48                     TYPE_CREATE_REMINDER,
49                     TYPE_SHARE_LOCATION
50             },
51             prefix = "TYPE_")
52     public @interface ActionType {}
53 
54     /**
55      * Indicates an action to view a calendar at a specified time.
56      */
57     public static final String TYPE_VIEW_CALENDAR = "view_calendar";
58     /**
59      * Indicates an action to view the map at a specified location.
60      */
61     public static final String TYPE_VIEW_MAP = "view_map";
62     /**
63      * Indicates an action to track a flight.
64      */
65     public static final String TYPE_TRACK_FLIGHT = "track_flight";
66     /**
67      * Indicates an action to open an URL.
68      */
69     public static final String TYPE_OPEN_URL = "open_url";
70     /**
71      * Indicates an action to send a SMS.
72      */
73     public static final String TYPE_SEND_SMS = "send_sms";
74     /**
75      * Indicates an action to call a phone number.
76      */
77     public static final String TYPE_CALL_PHONE = "call_phone";
78     /**
79      * Indicates an action to send an email.
80      */
81     public static final String TYPE_SEND_EMAIL = "send_email";
82     /**
83      * Indicates an action to reply with a text message.
84      */
85     public static final String TYPE_TEXT_REPLY = "text_reply";
86     /**
87      * Indicates an action to create a reminder.
88      */
89     public static final String TYPE_CREATE_REMINDER = "create_reminder";
90     /**
91      * Indicates an action to reply with a location.
92      */
93     public static final String TYPE_SHARE_LOCATION = "share_location";
94 
95     // TODO: Make this public API
96     /** @hide **/
97     public static final String TYPE_ADD_CONTACT = "add_contact";
98 
99     // TODO: Make this public API
100     /** @hide **/
101     public static final String TYPE_COPY = "copy";
102 
103     public static final @NonNull Creator<ConversationAction> CREATOR =
104             new Creator<ConversationAction>() {
105                 @Override
106                 public ConversationAction createFromParcel(Parcel in) {
107                     return new ConversationAction(in);
108                 }
109 
110                 @Override
111                 public ConversationAction[] newArray(int size) {
112                     return new ConversationAction[size];
113                 }
114             };
115 
116     @NonNull
117     @ActionType
118     private final String mType;
119     @NonNull
120     private final CharSequence mTextReply;
121     @Nullable
122     private final RemoteAction mAction;
123 
124     @FloatRange(from = 0, to = 1)
125     private final float mScore;
126 
127     @NonNull
128     private final Bundle mExtras;
129 
ConversationAction( @onNull String type, @Nullable RemoteAction action, @Nullable CharSequence textReply, float score, @NonNull Bundle extras)130     private ConversationAction(
131             @NonNull String type,
132             @Nullable RemoteAction action,
133             @Nullable CharSequence textReply,
134             float score,
135             @NonNull Bundle extras) {
136         mType = Preconditions.checkNotNull(type);
137         mAction = action;
138         mTextReply = textReply;
139         mScore = score;
140         mExtras = Preconditions.checkNotNull(extras);
141     }
142 
ConversationAction(Parcel in)143     private ConversationAction(Parcel in) {
144         mType = in.readString();
145         mAction = in.readParcelable(null);
146         mTextReply = in.readCharSequence();
147         mScore = in.readFloat();
148         mExtras = in.readBundle();
149     }
150 
151     @Override
writeToParcel(Parcel parcel, int flags)152     public void writeToParcel(Parcel parcel, int flags) {
153         parcel.writeString(mType);
154         parcel.writeParcelable(mAction, flags);
155         parcel.writeCharSequence(mTextReply);
156         parcel.writeFloat(mScore);
157         parcel.writeBundle(mExtras);
158     }
159 
160     @Override
describeContents()161     public int describeContents() {
162         return 0;
163     }
164 
165     /** Returns the type of this action, for example, {@link #TYPE_VIEW_CALENDAR}. */
166     @NonNull
167     @ActionType
getType()168     public String getType() {
169         return mType;
170     }
171 
172     /**
173      * Returns a RemoteAction object, which contains the icon, label and a PendingIntent, for
174      * the specified action type.
175      */
176     @Nullable
getAction()177     public RemoteAction getAction() {
178         return mAction;
179     }
180 
181     /**
182      * Returns the confidence score for the specified action. The value ranges from 0 (low
183      * confidence) to 1 (high confidence).
184      */
185     @FloatRange(from = 0, to = 1)
getConfidenceScore()186     public float getConfidenceScore() {
187         return mScore;
188     }
189 
190     /**
191      * Returns the text reply that could be sent as a reply to the given conversation.
192      * <p>
193      * This is only available when the type of the action is {@link #TYPE_TEXT_REPLY}.
194      */
195     @Nullable
getTextReply()196     public CharSequence getTextReply() {
197         return mTextReply;
198     }
199 
200     /**
201      * Returns the extended data related to this conversation action.
202      *
203      * <p><b>NOTE: </b>Do not modify this bundle.
204      */
205     @NonNull
getExtras()206     public Bundle getExtras() {
207         return mExtras;
208     }
209 
210     /** Builder class to construct {@link ConversationAction}. */
211     public static final class Builder {
212         @Nullable
213         @ActionType
214         private String mType;
215         @Nullable
216         private RemoteAction mAction;
217         @Nullable
218         private CharSequence mTextReply;
219         private float mScore;
220         @Nullable
221         private Bundle mExtras;
222 
Builder(@onNull @ctionType String actionType)223         public Builder(@NonNull @ActionType String actionType) {
224             mType = Preconditions.checkNotNull(actionType);
225         }
226 
227         /**
228          * Sets an action that may be performed on the given conversation.
229          */
230         @NonNull
setAction(@ullable RemoteAction action)231         public Builder setAction(@Nullable RemoteAction action) {
232             mAction = action;
233             return this;
234         }
235 
236         /**
237          * Sets a text reply that may be performed on the given conversation.
238          */
239         @NonNull
setTextReply(@ullable CharSequence textReply)240         public Builder setTextReply(@Nullable CharSequence textReply) {
241             mTextReply = textReply;
242             return this;
243         }
244 
245         /** Sets the confident score. */
246         @NonNull
setConfidenceScore(@loatRangefrom = 0, to = 1) float score)247         public Builder setConfidenceScore(@FloatRange(from = 0, to = 1) float score) {
248             mScore = score;
249             return this;
250         }
251 
252         /**
253          * Sets the extended data for the conversation action object.
254          */
255         @NonNull
setExtras(@ullable Bundle extras)256         public Builder setExtras(@Nullable Bundle extras) {
257             mExtras = extras;
258             return this;
259         }
260 
261         /** Builds the {@link ConversationAction} object. */
262         @NonNull
build()263         public ConversationAction build() {
264             return new ConversationAction(
265                     mType,
266                     mAction,
267                     mTextReply,
268                     mScore,
269                     mExtras == null ? Bundle.EMPTY : mExtras);
270         }
271     }
272 }
273