1 /* 2 * Copyright (C) 2016 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.apps.common; 17 18 import static android.car.drivingstate.CarUxRestrictions.UX_RESTRICTIONS_LIMIT_STRING_LENGTH; 19 20 import android.car.Car; 21 import android.car.CarNotConnectedException; 22 import android.car.drivingstate.CarUxRestrictions; 23 import android.car.drivingstate.CarUxRestrictions.CarUxRestrictionsInfo; 24 import android.car.drivingstate.CarUxRestrictionsManager; 25 import android.content.Context; 26 import android.util.Log; 27 28 import androidx.annotation.NonNull; 29 import androidx.annotation.Nullable; 30 31 import java.util.Collections; 32 import java.util.Set; 33 import java.util.WeakHashMap; 34 35 /** 36 * Utility class to access Car Restriction Manager. 37 * 38 * This class must be a singleton because only one listener can be registered with 39 * {@link CarUxRestrictionsManager} at a time, as documented in 40 * {@link CarUxRestrictionsManager#registerListener}. 41 */ 42 public class CarUxRestrictionsUtil { 43 private static final String TAG = "CarUxRestrictionsUtil"; 44 45 private final Car mCarApi; 46 private CarUxRestrictionsManager mCarUxRestrictionsManager; 47 @NonNull 48 private CarUxRestrictions mCarUxRestrictions = getDefaultRestrictions(); 49 50 private Set<OnUxRestrictionsChangedListener> mObservers; 51 private static CarUxRestrictionsUtil sInstance = null; 52 CarUxRestrictionsUtil(Context context)53 private CarUxRestrictionsUtil(Context context) { 54 CarUxRestrictionsManager.OnUxRestrictionsChangedListener listener = (carUxRestrictions) -> { 55 if (carUxRestrictions == null) { 56 mCarUxRestrictions = getDefaultRestrictions(); 57 } else { 58 mCarUxRestrictions = carUxRestrictions; 59 } 60 61 for (OnUxRestrictionsChangedListener observer : mObservers) { 62 observer.onRestrictionsChanged(mCarUxRestrictions); 63 } 64 }; 65 66 mCarApi = Car.createCar(context); 67 mObservers = Collections.newSetFromMap(new WeakHashMap<>()); 68 69 try { 70 mCarUxRestrictionsManager = (CarUxRestrictionsManager) mCarApi 71 .getCarManager(Car.CAR_UX_RESTRICTION_SERVICE); 72 mCarUxRestrictionsManager.registerListener(listener); 73 listener.onUxRestrictionsChanged( 74 mCarUxRestrictionsManager.getCurrentCarUxRestrictions()); 75 } catch (CarNotConnectedException e) { 76 Log.e(TAG, "Car not connected", e); 77 // mCarUxRestrictions will be the default 78 } catch (NullPointerException e) { 79 Log.e(TAG, "Car not connected", e); 80 // mCarUxRestrictions will be the default 81 } 82 } 83 84 @NonNull getDefaultRestrictions()85 private CarUxRestrictions getDefaultRestrictions() { 86 return new CarUxRestrictions.Builder(true, 87 CarUxRestrictions.UX_RESTRICTIONS_FULLY_RESTRICTED, 0).build(); 88 } 89 90 /** 91 * Listener interface used to update clients on UxRestrictions changes 92 */ 93 public interface OnUxRestrictionsChangedListener { 94 /** 95 * Called when CarUxRestrictions changes 96 */ onRestrictionsChanged(@onNull CarUxRestrictions carUxRestrictions)97 void onRestrictionsChanged(@NonNull CarUxRestrictions carUxRestrictions); 98 } 99 100 /** 101 * Returns the singleton instance of this class 102 */ 103 @NonNull getInstance(Context context)104 public static CarUxRestrictionsUtil getInstance(Context context) { 105 if (sInstance == null) { 106 sInstance = new CarUxRestrictionsUtil(context); 107 } 108 109 return sInstance; 110 } 111 112 /** 113 * Registers a listener on this class for updates to CarUxRestrictions. 114 * Multiple listeners may be registered. 115 */ register(OnUxRestrictionsChangedListener listener)116 public void register(OnUxRestrictionsChangedListener listener) { 117 mObservers.add(listener); 118 listener.onRestrictionsChanged(mCarUxRestrictions); 119 } 120 121 /** 122 * Unregisters a registered listener 123 */ unregister(OnUxRestrictionsChangedListener listener)124 public void unregister(OnUxRestrictionsChangedListener listener) { 125 mObservers.remove(listener); 126 } 127 128 /** 129 * Returns whether any of the given flags is blocked by the current restrictions. If null is 130 * given, the method returns true for safety. 131 */ isRestricted(@arUxRestrictionsInfo int restrictionFlags, @Nullable CarUxRestrictions uxr)132 public static boolean isRestricted(@CarUxRestrictionsInfo int restrictionFlags, 133 @Nullable CarUxRestrictions uxr) { 134 return (uxr == null) || ((uxr.getActiveRestrictions() & restrictionFlags) != 0); 135 } 136 137 /** 138 * Complies the input string with the given UX restrictions. 139 * Returns the original string if already compliant, otherwise a shortened ellipsized string. 140 */ complyString(Context context, String str, CarUxRestrictions uxr)141 public static String complyString(Context context, String str, CarUxRestrictions uxr) { 142 143 if (isRestricted(UX_RESTRICTIONS_LIMIT_STRING_LENGTH, uxr)) { 144 int maxLength = uxr == null 145 ? context.getResources().getInteger(R.integer.default_max_string_length) 146 : uxr.getMaxRestrictedStringLength(); 147 148 if (str.length() > maxLength) { 149 return str.substring(0, maxLength) + context.getString(R.string.ellipsis); 150 } 151 } 152 153 return str; 154 } 155 } 156