1c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme/* 2c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * Copyright (C) 2018 The Android Open Source Project 3c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * 4c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * Licensed under the Apache License, Version 2.0 (the "License"); 5c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * you may not use this file except in compliance with the License. 6c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * You may obtain a copy of the License at 7c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * 8c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * http://www.apache.org/licenses/LICENSE-2.0 9c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * 10c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * Unless required by applicable law or agreed to in writing, software 11c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * distributed under the License is distributed on an "AS IS" BASIS, 12c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * See the License for the specific language governing permissions and 14c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * limitations under the License. 15c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme */ 16c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 17c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemepackage android.service.autofill; 18c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 19c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport static android.view.autofill.Helper.sDebug; 20c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 21c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport android.annotation.NonNull; 22c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport android.annotation.TestApi; 2327206d7940540b3eb961700ff07702ca14704742Felipe Lemeimport android.icu.text.DateFormat; 24c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport android.os.Parcel; 25c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport android.os.Parcelable; 26c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport android.util.Log; 27c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport android.view.autofill.AutofillId; 28c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport android.view.autofill.AutofillValue; 29c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport android.widget.RemoteViews; 30c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport android.widget.TextView; 31c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 32c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport com.android.internal.util.Preconditions; 33c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 34c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemeimport java.util.Date; 35c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 36c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme/** 37c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * Replaces a {@link TextView} child of a {@link CustomDescription} with the contents of a field 38c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * that is expected to have a {@link AutofillValue#forDate(long) date value}. 39c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * 40c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * <p>For example, a transformation to display a credit card expiration date as month/year would be: 41c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * 42c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * <pre class="prettyprint"> 43c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * new DateTransformation(ccExpDate, new java.text.SimpleDateFormat("MM/yyyy") 44c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * </pre> 45c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme */ 46c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Lemepublic final class DateTransformation extends InternalTransformation implements 47c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme Transformation, Parcelable { 48c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme private static final String TAG = "DateTransformation"; 49c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 50c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme private final AutofillId mFieldId; 51c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme private final DateFormat mDateFormat; 52c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 53c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme /** 54c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * Creates a new transformation. 55c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * 56c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * @param id id of the screen field. 57c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme * @param dateFormat object used to transform the date value of the field to a String. 58c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme */ 59c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme public DateTransformation(@NonNull AutofillId id, @NonNull DateFormat dateFormat) { 60c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme mFieldId = Preconditions.checkNotNull(id); 61c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme mDateFormat = Preconditions.checkNotNull(dateFormat); 62c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme } 63c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 64c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme /** @hide */ 65c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme @Override 66c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme @TestApi 67c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme public void apply(@NonNull ValueFinder finder, @NonNull RemoteViews parentTemplate, 68c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme int childViewId) throws Exception { 69c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme final AutofillValue value = finder.findRawValueByAutofillId(mFieldId); 70c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme if (value == null) { 71c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme Log.w(TAG, "No value for id " + mFieldId); 72c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme return; 73c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme } 74c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme if (!value.isDate()) { 75c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme Log.w(TAG, "Value for " + mFieldId + " is not date: " + value); 76c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme return; 77c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme } 78c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 79c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme try { 80c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme final Date date = new Date(value.getDateValue()); 81c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme final String transformed = mDateFormat.format(date); 82c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme if (sDebug) Log.d(TAG, "Transformed " + date + " to " + transformed); 83c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 84c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme parentTemplate.setCharSequence(childViewId, "setText", transformed); 85c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme } catch (Exception e) { 86c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme Log.w(TAG, "Could not apply " + mDateFormat + " to " + value + ": " + e); 87c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme } 88c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme } 89c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 90c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme ///////////////////////////////////// 91c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme // Object "contract" methods. // 92c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme ///////////////////////////////////// 93c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme @Override 94c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme public String toString() { 95c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme if (!sDebug) return super.toString(); 96c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 97c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme return "DateTransformation: [id=" + mFieldId + ", format=" + mDateFormat + "]"; 98c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme } 99c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 100c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme ///////////////////////////////////// 101c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme // Parcelable "contract" methods. // 102c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme ///////////////////////////////////// 103c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme @Override 104c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme public int describeContents() { 105c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme return 0; 106c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme } 107c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 108c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme @Override 109c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme public void writeToParcel(Parcel parcel, int flags) { 110c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme parcel.writeParcelable(mFieldId, flags); 111c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme parcel.writeSerializable(mDateFormat); 112c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme } 113c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 114c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme public static final Parcelable.Creator<DateTransformation> CREATOR = 115c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme new Parcelable.Creator<DateTransformation>() { 116c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme @Override 117c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme public DateTransformation createFromParcel(Parcel parcel) { 118c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme return new DateTransformation(parcel.readParcelable(null), 119c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme (DateFormat) parcel.readSerializable()); 120c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme } 121c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme 122c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme @Override 123c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme public DateTransformation[] newArray(int size) { 124c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme return new DateTransformation[size]; 125c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme } 126c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme }; 127c8c0a82f56a5ef0cb3c8f749006d3a3b3e501849Felipe Leme} 128