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 
17 package android.service.autofill;
18 
19 import static android.view.autofill.Helper.sDebug;
20 
21 import android.annotation.NonNull;
22 import android.annotation.TestApi;
23 import android.icu.text.DateFormat;
24 import android.os.Parcel;
25 import android.os.Parcelable;
26 import android.util.Log;
27 import android.view.autofill.AutofillId;
28 import android.view.autofill.AutofillValue;
29 import android.widget.RemoteViews;
30 import android.widget.TextView;
31 
32 import java.util.Date;
33 import java.util.Objects;
34 
35 /**
36  * Replaces a {@link TextView} child of a {@link CustomDescription} with the contents of a field
37  * that is expected to have a {@link AutofillValue#forDate(long) date value}.
38  *
39  * <p>For example, a transformation to display a credit card expiration date as month/year would be:
40  *
41  * <pre class="prettyprint">
42  * new DateTransformation(ccExpDate, new java.text.SimpleDateFormat("MM/yyyy")
43  * </pre>
44  */
45 public final class DateTransformation extends InternalTransformation implements
46         Transformation, Parcelable {
47     private static final String TAG = "DateTransformation";
48 
49     private final AutofillId mFieldId;
50     private final DateFormat mDateFormat;
51 
52     /**
53      * Creates a new transformation.
54      *
55      * @param id id of the screen field.
56      * @param dateFormat object used to transform the date value of the field to a String.
57      */
DateTransformation(@onNull AutofillId id, @NonNull DateFormat dateFormat)58     public DateTransformation(@NonNull AutofillId id, @NonNull DateFormat dateFormat) {
59         mFieldId = Objects.requireNonNull(id);
60         mDateFormat = Objects.requireNonNull(dateFormat);
61     }
62 
63     /** @hide */
64     @Override
65     @TestApi
apply(@onNull ValueFinder finder, @NonNull RemoteViews parentTemplate, int childViewId)66     public void apply(@NonNull ValueFinder finder, @NonNull RemoteViews parentTemplate,
67             int childViewId) throws Exception {
68         final AutofillValue value = finder.findRawValueByAutofillId(mFieldId);
69         if (value == null) {
70             Log.w(TAG, "No value for id " + mFieldId);
71             return;
72         }
73         if (!value.isDate()) {
74             Log.w(TAG, "Value for " + mFieldId + " is not date: " + value);
75             return;
76         }
77 
78         try {
79             final Date date = new Date(value.getDateValue());
80             final String transformed = mDateFormat.format(date);
81             if (sDebug) Log.d(TAG, "Transformed " + date + " to " + transformed);
82 
83             parentTemplate.setCharSequence(childViewId, "setText", transformed);
84         } catch (Exception e) {
85             Log.w(TAG, "Could not apply " + mDateFormat + " to " + value + ": " + e);
86         }
87     }
88 
89     /////////////////////////////////////
90     // Object "contract" methods. //
91     /////////////////////////////////////
92     @Override
toString()93     public String toString() {
94         if (!sDebug) return super.toString();
95 
96         return "DateTransformation: [id=" + mFieldId + ", format=" + mDateFormat + "]";
97     }
98 
99     /////////////////////////////////////
100     // Parcelable "contract" methods. //
101     /////////////////////////////////////
102     @Override
describeContents()103     public int describeContents() {
104         return 0;
105     }
106 
107     @Override
writeToParcel(Parcel parcel, int flags)108     public void writeToParcel(Parcel parcel, int flags) {
109         parcel.writeParcelable(mFieldId, flags);
110         parcel.writeSerializable(mDateFormat);
111     }
112 
113     public static final @android.annotation.NonNull Parcelable.Creator<DateTransformation> CREATOR =
114             new Parcelable.Creator<DateTransformation>() {
115         @Override
116         public DateTransformation createFromParcel(Parcel parcel) {
117             return new DateTransformation(parcel.readParcelable(null, android.view.autofill.AutofillId.class),
118                     (DateFormat) parcel.readSerializable(android.icu.text.DateFormat.class.getClassLoader(), android.icu.text.DateFormat.class));
119         }
120 
121         @Override
122         public DateTransformation[] newArray(int size) {
123             return new DateTransformation[size];
124         }
125     };
126 }
127