• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 com.android.car.settings.datetime;
17 
18 import android.app.timedetector.ManualTimeSuggestion;
19 import android.app.timedetector.TimeDetector;
20 import android.app.timedetector.TimeDetectorHelper;
21 import android.car.drivingstate.CarUxRestrictions;
22 import android.content.Intent;
23 import android.os.Bundle;
24 import android.util.Log;
25 import android.view.ViewGroup;
26 import android.widget.DatePicker;
27 import android.widget.NumberPicker;
28 
29 import androidx.annotation.LayoutRes;
30 import androidx.annotation.StringRes;
31 
32 import com.android.car.settings.R;
33 import com.android.car.settings.common.BaseFragment;
34 import com.android.car.settings.common.rotary.DirectManipulationHandler;
35 import com.android.car.settings.common.rotary.DirectManipulationState;
36 import com.android.car.settings.common.rotary.NumberPickerNudgeHandler;
37 import com.android.car.settings.common.rotary.NumberPickerRotationHandler;
38 import com.android.car.settings.common.rotary.NumberPickerUtils;
39 
40 import java.util.ArrayList;
41 import java.util.Calendar;
42 import java.util.GregorianCalendar;
43 import java.util.List;
44 
45 /**
46  * Sets the system date.
47  */
48 public class DatePickerFragment extends BaseFragment {
49     private static final String TAG = "DatePickerFragment";
50 
51     private DirectManipulationState mDirectManipulationMode;
52     private DatePicker mDatePicker;
53     private List<NumberPicker> mNumberPickers;
54 
55     @Override
onStop()56     public void onStop() {
57         super.onStop();
58         Calendar c = Calendar.getInstance();
59         c.set(Calendar.YEAR, mDatePicker.getYear());
60         c.set(Calendar.MONTH, mDatePicker.getMonth());
61         c.set(Calendar.DAY_OF_MONTH, mDatePicker.getDayOfMonth());
62 
63         long when = c.getTimeInMillis();
64         TimeDetector timeDetector = getContext().getSystemService(TimeDetector.class);
65         ManualTimeSuggestion manualTimeSuggestion =
66                 TimeDetector.createManualTimeSuggestion(when, "Settings: Set date");
67         boolean success = timeDetector.suggestManualTime(manualTimeSuggestion);
68         if (success) {
69             getContext().sendBroadcast(new Intent(Intent.ACTION_TIME_CHANGED));
70         } else {
71             // This implies the system server is applying tighter bounds than the settings app or
72             // the date/time cannot be set for other reasons, e.g. perhaps "auto time" is turned on.
73             Log.w(TAG, "Unable to set date with suggestion=" + manualTimeSuggestion);
74         }
75     }
76 
77     @Override
78     @LayoutRes
getLayoutId()79     protected int getLayoutId() {
80         return R.layout.date_picker;
81     }
82 
83     @Override
84     @StringRes
getTitleId()85     protected int getTitleId() {
86         return R.string.date_picker_title;
87     }
88 
89     @Override
onActivityCreated(Bundle savedInstanceState)90     public void onActivityCreated(Bundle savedInstanceState) {
91         super.onActivityCreated(savedInstanceState);
92 
93         mDirectManipulationMode = new DirectManipulationState();
94         mDatePicker = getView().findViewById(R.id.date_picker);
95         mDatePicker.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
96 
97         // Set lower and upper bounds for the date that the user is able to select.
98         GregorianCalendar calendar = new GregorianCalendar();
99         calendar.clear();
100         calendar.set(Calendar.DAY_OF_MONTH, 1);
101         calendar.set(Calendar.MONTH, Calendar.JANUARY);
102         calendar.set(Calendar.YEAR, TimeDetectorHelper.INSTANCE.getManualDateSelectionYearMin());
103         mDatePicker.setMinDate(calendar.getTimeInMillis());
104 
105         calendar.clear();
106         calendar.set(Calendar.DAY_OF_MONTH, 31);
107         calendar.set(Calendar.MONTH, Calendar.DECEMBER);
108         calendar.set(Calendar.YEAR, TimeDetectorHelper.INSTANCE.getManualDateSelectionYearMax());
109         mDatePicker.setMaxDate(calendar.getTimeInMillis());
110 
111         mNumberPickers = new ArrayList<>();
112         NumberPickerUtils.getNumberPickerDescendants(mNumberPickers, mDatePicker);
113 
114         DirectManipulationHandler.setDirectManipulationHandler(mDatePicker,
115                 new DirectManipulationHandler.Builder(mDirectManipulationMode)
116                         // Use no-op nudge handler, since we never stay on this view in direct
117                         // manipulation mode.
118                         .setNudgeHandler((v, keyCode, event) -> true)
119                         .setCenterButtonHandler(inDirectManipulationMode -> {
120                             if (inDirectManipulationMode) {
121                                 return true;
122                             }
123 
124                             NumberPicker picker = mNumberPickers.get(0);
125                             if (picker != null) {
126                                 picker.requestFocus();
127                             }
128                             return true;
129                         })
130                         .setBackHandler(inDirectManipulationMode -> {
131                             // Only handle back if we weren't previously in direct manipulation
132                             // mode.
133                             if (!inDirectManipulationMode) {
134                                 onBackPressed();
135                             }
136                             return true;
137                         })
138                         .build());
139 
140         DirectManipulationHandler numberPickerListener =
141                 new DirectManipulationHandler.Builder(mDirectManipulationMode)
142                         .setNudgeHandler(new NumberPickerNudgeHandler())
143                         .setCenterButtonHandler(inDirectManipulationMode -> {
144                             if (!inDirectManipulationMode) {
145                                 return true;
146                             }
147 
148                             mDatePicker.requestFocus();
149                             return true;
150                         })
151                         .setBackHandler(inDirectManipulationMode -> {
152                             mDatePicker.requestFocus();
153                             return true;
154                         })
155                         .setRotationHandler(new NumberPickerRotationHandler())
156                         .build();
157 
158         for (int i = 0; i < mNumberPickers.size(); i++) {
159             DirectManipulationHandler.setDirectManipulationHandler(mNumberPickers.get(i),
160                     numberPickerListener);
161         }
162     }
163 
164     @Override
onUxRestrictionsChanged(CarUxRestrictions restrictionInfo)165     public void onUxRestrictionsChanged(CarUxRestrictions restrictionInfo) {
166         if (canBeShown(restrictionInfo)) {
167             return;
168         }
169         if (mDirectManipulationMode != null && mDirectManipulationMode.isActive()) {
170             mDirectManipulationMode.disable();
171         }
172     }
173 
174     @Override
onDestroy()175     public void onDestroy() {
176         DirectManipulationHandler.setDirectManipulationHandler(mDatePicker, /* handler= */ null);
177         for (int i = 0; i < mNumberPickers.size(); i++) {
178             DirectManipulationHandler.setDirectManipulationHandler(mNumberPickers.get(i),
179                     /* handler= */ null);
180         }
181 
182         super.onDestroy();
183     }
184 }
185