blob: 149f1dcbf2964adf876715d05e93bcdb29fe7529 [file] [log] [blame]
Ram Periathiruvadi4526a432018-01-24 13:00:54 -08001/*
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
17package android.car.drivingstate;
18
19import android.annotation.IntDef;
20import android.os.Parcel;
21import android.os.Parcelable;
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -070022
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080023import java.lang.annotation.Retention;
24import java.lang.annotation.RetentionPolicy;
25
26/**
Ram Periathiruvadi79029912018-07-11 20:34:14 -070027 * Car UX Restrictions event. This contains information on the set of UX restrictions that is in
28 * place due to the car's driving state.
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080029 * <p>
30 * The restriction information is organized as follows:
31 * <ul>
32 * <li> When there are no restrictions in place, for example when the car is parked,
33 * <ul>
Ram Periathiruvadi79029912018-07-11 20:34:14 -070034 * <li> {@link #isRequiresDistractionOptimization()} returns false. Apps can display activities
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080035 * that are not distraction optimized.
Ram Periathiruvadi79029912018-07-11 20:34:14 -070036 * <li> When {@link #isRequiresDistractionOptimization()} returns false, apps don't have to call
37 * {@link #getActiveRestrictions()}, since there is no distraction optimization required.
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080038 * </ul>
39 * <li> When the driving state changes, causing the UX restrictions to come in effect,
40 * <ul>
Ram Periathiruvadi79029912018-07-11 20:34:14 -070041 * <li> {@link #isRequiresDistractionOptimization()} returns true. Apps can only display activities
42 * that are distraction optimized. Distraction optimized activities must follow the base design
43 * guidelines to ensure a distraction free driving experience for the user.
44 * <li> When {@link #isRequiresDistractionOptimization()} returns true, apps must call
45 * {@link #getActiveRestrictions()}, to get the currently active UX restrictions to adhere to.
46 * {@link #getActiveRestrictions()} provides additional information on the set of UX
47 * restrictions that are in place for the current driving state.
48 * <p>
49 * The UX restrictions returned by {@link #getActiveRestrictions()}, for the same driving state of
50 * the vehicle, could vary depending on the OEM and the market. For example, when the car is
51 * idling, the set of active UX restrictions will depend on the car maker and the safety standards
52 * of the market that the vehicle is deployed in.
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080053 * </ul>
54 * </ul>
55 * <p>
56 * Apps that intend to be run when the car is being driven need to
57 * <ul>
58 * <li> Comply with the general distraction optimization guidelines.
59 * <li> Listen and react to the UX restrictions changes as detailed above. Since the restrictions
60 * could vary depending on the market, apps are expected to react to the restriction information
61 * and not to the absolute driving state.
62 * </ul>
63 */
Yao, Yuxing64cca8d2019-03-20 10:41:47 -070064public final class CarUxRestrictions implements Parcelable {
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080065
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -070066 // Default fallback values for the restriction related parameters if the information is
67 // not available from the underlying service.
Ram Periathiruvadidb664832018-05-23 13:56:50 -070068 private static final int DEFAULT_MAX_LENGTH = 120;
69 private static final int DEFAULT_MAX_CUMULATIVE_ITEMS = 21;
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -070070 private static final int DEFAULT_MAX_CONTENT_DEPTH = 3;
71
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080072 /**
Ram Periathiruvadic81855d2018-03-23 18:47:06 -070073 * No specific restrictions in place, but baseline distraction optimization guidelines need to
74 * be adhered to when {@link #isRequiresDistractionOptimization()} is true.
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080075 */
Ram Periathiruvadic81855d2018-03-23 18:47:06 -070076 public static final int UX_RESTRICTIONS_BASELINE = 0;
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080077
78 // Granular UX Restrictions that are imposed when distraction optimization is required.
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080079 /**
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -070080 * No dialpad for the purpose of initiating a phone call.
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080081 */
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -070082 public static final int UX_RESTRICTIONS_NO_DIALPAD = 1;
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080083
84 /**
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -070085 * No filtering a list.
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080086 */
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -070087 public static final int UX_RESTRICTIONS_NO_FILTERING = 0x1 << 1;
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080088
89 /**
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -070090 * General purpose strings length cannot exceed the character limit provided by
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -070091 * {@link #getMaxRestrictedStringLength()}
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080092 */
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080093 public static final int UX_RESTRICTIONS_LIMIT_STRING_LENGTH = 0x1 << 2;
94
95 /**
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -070096 * No text entry for the purpose of searching etc.
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080097 */
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -070098 public static final int UX_RESTRICTIONS_NO_KEYBOARD = 0x1 << 3;
Ram Periathiruvadi4526a432018-01-24 13:00:54 -080099
100 /**
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -0700101 * No video - no animated frames > 1fps.
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800102 */
103 public static final int UX_RESTRICTIONS_NO_VIDEO = 0x1 << 4;
104
105 /**
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -0700106 * Limit the number of items displayed on the screen.
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -0700107 * Refer to {@link #getMaxCumulativeContentItems()} and
108 * {@link #getMaxContentDepth()} for the upper bounds on content
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -0700109 * serving.
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800110 */
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -0700111 public static final int UX_RESTRICTIONS_LIMIT_CONTENT = 0x1 << 5;
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800112
113 /**
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -0700114 * No setup that requires form entry or interaction with external devices.
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800115 */
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -0700116 public static final int UX_RESTRICTIONS_NO_SETUP = 0x1 << 6;
117
118 /**
119 * No Text Message (SMS, email, conversational, etc.)
120 */
121 public static final int UX_RESTRICTIONS_NO_TEXT_MESSAGE = 0x1 << 7;
122
123 /**
124 * No text transcription (live or leave behind) of voice can be shown.
125 */
126 public static final int UX_RESTRICTIONS_NO_VOICE_TRANSCRIPTION = 0x1 << 8;
127
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800128
129 /**
130 * All the above restrictions are in effect.
131 */
132 public static final int UX_RESTRICTIONS_FULLY_RESTRICTED =
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -0700133 UX_RESTRICTIONS_NO_DIALPAD | UX_RESTRICTIONS_NO_FILTERING
134 | UX_RESTRICTIONS_LIMIT_STRING_LENGTH | UX_RESTRICTIONS_NO_KEYBOARD
135 | UX_RESTRICTIONS_NO_VIDEO | UX_RESTRICTIONS_LIMIT_CONTENT
136 | UX_RESTRICTIONS_NO_SETUP | UX_RESTRICTIONS_NO_TEXT_MESSAGE
137 | UX_RESTRICTIONS_NO_VOICE_TRANSCRIPTION;
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800138
139 @IntDef(flag = true,
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -0700140 prefix = {"UX_RESTRICTIONS_"},
Ram Periathiruvadic81855d2018-03-23 18:47:06 -0700141 value = {UX_RESTRICTIONS_BASELINE,
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -0700142 UX_RESTRICTIONS_NO_DIALPAD,
143 UX_RESTRICTIONS_NO_FILTERING,
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800144 UX_RESTRICTIONS_LIMIT_STRING_LENGTH,
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -0700145 UX_RESTRICTIONS_NO_KEYBOARD,
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800146 UX_RESTRICTIONS_NO_VIDEO,
Ram Periathiruvadia68f8e12018-03-19 14:34:41 -0700147 UX_RESTRICTIONS_LIMIT_CONTENT,
148 UX_RESTRICTIONS_NO_SETUP,
149 UX_RESTRICTIONS_NO_TEXT_MESSAGE,
150 UX_RESTRICTIONS_NO_VOICE_TRANSCRIPTION})
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800151 @Retention(RetentionPolicy.SOURCE)
152 public @interface CarUxRestrictionsInfo {
153 }
154
155 private final long mTimeStamp;
156 private final boolean mRequiresDistractionOptimization;
157 @CarUxRestrictionsInfo
158 private final int mActiveRestrictions;
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -0700159 // Restriction Parameters
160 private final int mMaxStringLength;
161 private final int mMaxCumulativeContentItems;
162 private final int mMaxContentDepth;
163
164 /**
165 * Builder class for {@link CarUxRestrictions}
166 */
167 public static class Builder {
168 private final long mTimeStamp;
169 private final boolean mRequiresDistractionOptimization;
170 @CarUxRestrictionsInfo
171 private final int mActiveRestrictions;
172 // Restriction Parameters
173 private int mMaxStringLength = DEFAULT_MAX_LENGTH;
174 private int mMaxCumulativeContentItems = DEFAULT_MAX_CUMULATIVE_ITEMS;
175 private int mMaxContentDepth = DEFAULT_MAX_CONTENT_DEPTH;
176
177 public Builder(boolean reqOpt, @CarUxRestrictionsInfo int restrictions, long time) {
178 mRequiresDistractionOptimization = reqOpt;
179 mActiveRestrictions = restrictions;
180 mTimeStamp = time;
181 }
182
183 /**
184 * Set the maximum length of general purpose strings that can be displayed when
185 * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_STRING_LENGTH} is imposed.
186 */
187 public Builder setMaxStringLength(int length) {
188 mMaxStringLength = length;
189 return this;
190 }
191
192 /**
193 * Set the maximum number of cumulative content items that can be displayed when
194 * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_CONTENT} is imposed.
195 */
196 public Builder setMaxCumulativeContentItems(int number) {
197 mMaxCumulativeContentItems = number;
198 return this;
199 }
200
201 /**
202 * Set the maximum number of levels that the user can navigate to when
203 * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_CONTENT} is imposed.
204 */
205 public Builder setMaxContentDepth(int depth) {
206 mMaxContentDepth = depth;
207 return this;
208 }
209
210 /**
211 * Build and return the {@link CarUxRestrictions} object
212 */
213 public CarUxRestrictions build() {
214 return new CarUxRestrictions(this);
215 }
216
217 }
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800218
219 /**
220 * Time at which this UX restriction event was deduced based on the car's driving state.
221 *
222 * @return Elapsed time in nanoseconds since system boot.
223 */
224 public long getTimeStamp() {
225 return mTimeStamp;
226 }
227
228 /**
229 * Conveys if the foreground activity needs to be distraction optimized.
230 * Activities that can handle distraction optimization need to be tagged as a distraction
231 * optimized in the app's manifest.
232 * <p>
233 * If the app has a foreground activity that has not been distraction optimized, the app has
234 * to switch to another activity that is distraction optimized. Failing that, the system will
235 * stop the foreground activity.
236 *
237 * @return true if distraction optimization is required, false if not
238 */
239 public boolean isRequiresDistractionOptimization() {
240 return mRequiresDistractionOptimization;
241 }
242
243 /**
244 * A combination of the Car UX Restrictions that is active for the current state of driving.
245 *
246 * @return A combination of the above {@code @CarUxRestrictionsInfo}
247 */
248 @CarUxRestrictionsInfo
249 public int getActiveRestrictions() {
250 return mActiveRestrictions;
251 }
252
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -0700253 /**
254 * Get the maximum length of general purpose strings that can be displayed when
255 * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_STRING_LENGTH} is imposed.
256 *
257 * @return the maximum length of string that can be displayed
258 */
259 public int getMaxRestrictedStringLength() {
260 return mMaxStringLength;
261 }
262
263 /**
Ram Periathiruvadid980d622018-04-13 12:22:13 -0700264 * Get the maximum allowable number of content items that can be displayed to a user during
265 * traversal through any one path in a single task, when
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -0700266 * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_CONTENT} is imposed.
267 * <p>
Ram Periathiruvadid980d622018-04-13 12:22:13 -0700268 * For example, if a task involving only one view, this represents the maximum allowable number
269 * of content items in this single view.
270 * <p>
271 * However, if the task involves selection of a content item in an originating view that then
272 * surfaces a secondary view to the user, then this value represents the maximum allowable
273 * number of content items between the originating and secondary views combined.
274 * <p>
275 * Specifically, if the maximum allowable value was 60 and a task involved browsing a list of
276 * countries and then viewing the top songs within a country, it would be acceptable to do
277 * either of the following:
278 * <ul>
279 * <li> list 10 countries, and then display the top 50 songs after country selection, or
280 * <li> list 20 countries, and then display the top 40 songs after country selection.
281 * </ul>
282 * <p>
283 * Please refer to this and {@link #getMaxContentDepth()} to know the upper bounds on the
284 * content display when the restriction is in place.
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -0700285 *
286 * @return maximum number of cumulative items that can be displayed
287 */
288 public int getMaxCumulativeContentItems() {
289 return mMaxCumulativeContentItems;
290 }
291
292 /**
Ram Periathiruvadid980d622018-04-13 12:22:13 -0700293 * Get the maximum allowable number of content depth levels or view traversals through any one
294 * path in a single task. This is applicable when
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -0700295 * {@link CarUxRestrictions#UX_RESTRICTIONS_LIMIT_CONTENT} is imposed.
296 * <p>
Ram Periathiruvadid980d622018-04-13 12:22:13 -0700297 * For example, if a task involves only selecting an item from a single list on one view,
298 * the task's content depth would be considered 1.
299 * <p>
300 * However, if the task involves selection of a content item in an originating view that then
301 * surfaces a secondary view to the user, the task's content depth would be considered 2.
302 * <p>
303 * Specifically, if a task involved browsing a list of countries, selecting a genre within the
304 * country, and then viewing the top songs within a country, the task's content depth would be
305 * considered 3.
306 * <p>
307 * Please refer to this and {@link #getMaxCumulativeContentItems()} to know the upper bounds on
308 * the content display when the restriction is in place.
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -0700309 *
310 * @return maximum number of cumulative items that can be displayed
311 */
312 public int getMaxContentDepth() {
313 return mMaxContentDepth;
314 }
315
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800316 @Override
317 public int describeContents() {
318 return 0;
319 }
320
321 @Override
322 public void writeToParcel(Parcel dest, int flags) {
323 dest.writeInt(mActiveRestrictions);
324 dest.writeLong(mTimeStamp);
325 dest.writeInt(mRequiresDistractionOptimization ? 1 : 0);
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -0700326 dest.writeInt(mMaxStringLength);
327 dest.writeInt(mMaxCumulativeContentItems);
328 dest.writeInt(mMaxContentDepth);
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800329 }
330
Yao, Yuxing0863c522018-09-06 14:33:47 -0700331 public static final Parcelable.Creator<CarUxRestrictions> CREATOR =
332 new Parcelable.Creator<CarUxRestrictions>() {
333 @Override
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800334 public CarUxRestrictions createFromParcel(Parcel in) {
335 return new CarUxRestrictions(in);
336 }
337
Yao, Yuxing0863c522018-09-06 14:33:47 -0700338 @Override
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800339 public CarUxRestrictions[] newArray(int size) {
340 return new CarUxRestrictions[size];
341 }
342 };
343
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800344 public CarUxRestrictions(CarUxRestrictions uxRestrictions) {
345 mTimeStamp = uxRestrictions.getTimeStamp();
346 mRequiresDistractionOptimization = uxRestrictions.isRequiresDistractionOptimization();
347 mActiveRestrictions = uxRestrictions.getActiveRestrictions();
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -0700348 mMaxStringLength = uxRestrictions.mMaxStringLength;
349 mMaxCumulativeContentItems = uxRestrictions.mMaxCumulativeContentItems;
350 mMaxContentDepth = uxRestrictions.mMaxContentDepth;
351 }
352
353 private CarUxRestrictions(Builder builder) {
354 mTimeStamp = builder.mTimeStamp;
355 mActiveRestrictions = builder.mActiveRestrictions;
356 mRequiresDistractionOptimization = builder.mRequiresDistractionOptimization;
357 mMaxStringLength = builder.mMaxStringLength;
358 mMaxCumulativeContentItems = builder.mMaxCumulativeContentItems;
359 mMaxContentDepth = builder.mMaxContentDepth;
Ram Periathiruvadi2da6d0e2018-01-26 18:02:10 -0800360 }
361
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800362 private CarUxRestrictions(Parcel in) {
363 mActiveRestrictions = in.readInt();
364 mTimeStamp = in.readLong();
365 mRequiresDistractionOptimization = in.readInt() != 0;
Ram Periathiruvadiac7e9792018-04-04 17:01:59 -0700366 mMaxStringLength = in.readInt();
367 mMaxCumulativeContentItems = in.readInt();
368 mMaxContentDepth = in.readInt();
Ram Periathiruvadi4526a432018-01-24 13:00:54 -0800369 }
370
371 @Override
372 public String toString() {
373 return "DO: " + mRequiresDistractionOptimization + " UxR: " + mActiveRestrictions
374 + " time: " + mTimeStamp;
375 }
376
377 /**
378 * Compares if the restrictions are the same. Doesn't compare the timestamps.
379 *
380 * @param other the other CarUxRestrictions object
381 * @return true if the restrictions are same, false otherwise
382 */
383 public boolean isSameRestrictions(CarUxRestrictions other) {
384 if (other == null) {
385 return false;
386 }
387 if (other == this) {
388 return true;
389 }
390 return other.mRequiresDistractionOptimization == mRequiresDistractionOptimization
391 && other.mActiveRestrictions == mActiveRestrictions;
392 }
393}