1 /* 2 * Copyright (C) 2019 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 18 package com.android.car.settings.units; 19 20 import android.car.CarNotConnectedException; 21 import android.car.drivingstate.CarUxRestrictions; 22 import android.car.hardware.CarPropertyValue; 23 import android.car.hardware.property.CarPropertyManager; 24 import android.content.Context; 25 import android.text.BidiFormatter; 26 import android.text.TextDirectionHeuristics; 27 28 import androidx.annotation.CallSuper; 29 import androidx.preference.ListPreference; 30 31 import com.android.car.settings.R; 32 import com.android.car.settings.common.FragmentController; 33 import com.android.car.settings.common.PreferenceController; 34 import com.android.internal.annotations.VisibleForTesting; 35 36 /** 37 * Shared business logic for preference controllers related to Units. 38 */ 39 public abstract class UnitsBasePreferenceController extends PreferenceController<ListPreference> { 40 41 @VisibleForTesting 42 protected final CarUnitsManager.OnCarServiceListener mOnCarServiceListener = 43 new CarUnitsManager.OnCarServiceListener() { 44 @Override 45 public void handleServiceConnected(CarPropertyManager carPropertyManager) { 46 try { 47 if (carPropertyManager != null) { 48 carPropertyManager.registerCallback(mCarPropertyEventCallback, 49 getPropertyId(), CarPropertyManager.SENSOR_RATE_ONCHANGE); 50 } 51 mSupportedUnits = mCarUnitsManager.getUnitsSupportedByProperty( 52 getPropertyId()); 53 if (mSupportedUnits != null && mSupportedUnits.length > 0) { 54 // first element in the config array is the default Unit per VHAL spec. 55 mDefaultUnit = mSupportedUnits[0]; 56 getPreference().setEntries(getEntriesOfSupportedUnits()); 57 getPreference().setEntryValues(getIdsOfSupportedUnits()); 58 getPreference().setValue( 59 Integer.toString(getUnitUsedByThisProperty().getId())); 60 refreshUi(); 61 } 62 63 mIsCarUnitsManagerStarted = true; 64 } catch (CarNotConnectedException e) { 65 } 66 } 67 68 @Override 69 public void handleServiceDisconnected() { 70 mIsCarUnitsManagerStarted = false; 71 } 72 }; 73 74 @VisibleForTesting 75 protected final CarPropertyManager.CarPropertyEventCallback mCarPropertyEventCallback = 76 new CarPropertyManager.CarPropertyEventCallback() { 77 @Override 78 public void onChangeEvent(CarPropertyValue value) { 79 if (value != null && value.getStatus() == CarPropertyValue.STATUS_AVAILABLE) { 80 mUnitBeingUsed = UnitsMap.MAP.get(value.getValue()); 81 refreshUi(); 82 } 83 } 84 85 @Override 86 public void onErrorEvent(int propId, int zone) { 87 } 88 }; 89 90 private Unit[] mSupportedUnits; 91 private Unit mUnitBeingUsed; 92 private Unit mDefaultUnit; 93 private boolean mIsCarUnitsManagerStarted = false; 94 private CarUnitsManager mCarUnitsManager; 95 UnitsBasePreferenceController(Context context, String preferenceKey, FragmentController fragmentController, CarUxRestrictions uxRestrictions)96 public UnitsBasePreferenceController(Context context, String preferenceKey, 97 FragmentController fragmentController, CarUxRestrictions uxRestrictions) { 98 super(context, preferenceKey, fragmentController, uxRestrictions); 99 } 100 101 @Override 102 @CallSuper onCreateInternal()103 protected void onCreateInternal() { 104 super.onCreateInternal(); 105 mCarUnitsManager = createCarUnitsManager(); 106 mCarUnitsManager.registerCarServiceListener(mOnCarServiceListener); 107 } 108 109 @Override 110 @CallSuper onDestroyInternal()111 protected void onDestroyInternal() { 112 super.onDestroyInternal(); 113 mCarUnitsManager.disconnect(); 114 mCarUnitsManager.unregisterCarServiceListener(); 115 } 116 117 @Override 118 @CallSuper updateState(ListPreference preference)119 protected void updateState(ListPreference preference) { 120 if (mIsCarUnitsManagerStarted && mUnitBeingUsed != null) { 121 preference.setSummary(generateSummaryFromUnit(mUnitBeingUsed)); 122 preference.setValue(Integer.toString(mUnitBeingUsed.getId())); 123 } 124 } 125 126 @Override 127 @CallSuper handlePreferenceChanged(ListPreference preference, Object newValue)128 public boolean handlePreferenceChanged(ListPreference preference, Object newValue) { 129 int unitId = Integer.parseInt((String) newValue); 130 mCarUnitsManager.setUnitUsedByProperty(getPropertyId(), unitId); 131 return true; 132 } 133 134 @Override getAvailabilityStatus()135 protected int getAvailabilityStatus() { 136 return mSupportedUnits != null && mSupportedUnits.length > 0 137 ? AVAILABLE : CONDITIONALLY_UNAVAILABLE; 138 } 139 getPropertyId()140 protected abstract int getPropertyId(); 141 getEntriesOfSupportedUnits()142 protected String[] getEntriesOfSupportedUnits() { 143 String[] names = new String[mSupportedUnits.length]; 144 for (int i = 0; i < names.length; i++) { 145 Unit unit = mSupportedUnits[i]; 146 names[i] = generateEntryStringFromUnit(unit); 147 } 148 return names; 149 } 150 generateSummaryFromUnit(Unit unit)151 protected String generateSummaryFromUnit(Unit unit) { 152 return getContext().getString(unit.getAbbreviationResId()); 153 } 154 generateEntryStringFromUnit(Unit unit)155 protected String generateEntryStringFromUnit(Unit unit) { 156 return BidiFormatter.getInstance().unicodeWrap( 157 getContext().getString(R.string.units_list_entry, 158 getContext().getString(unit.getAbbreviationResId()), 159 getContext().getString(unit.getNameResId())), 160 TextDirectionHeuristics.LOCALE); 161 } 162 getIdsOfSupportedUnits()163 protected String[] getIdsOfSupportedUnits() { 164 String[] ids = new String[mSupportedUnits.length]; 165 for (int i = 0; i < ids.length; i++) { 166 ids[i] = Integer.toString(mSupportedUnits[i].getId()); 167 } 168 return ids; 169 } 170 getCarUnitsManager()171 protected CarUnitsManager getCarUnitsManager() { 172 return mCarUnitsManager; 173 } 174 175 @VisibleForTesting createCarUnitsManager()176 CarUnitsManager createCarUnitsManager() { 177 return new CarUnitsManager(getContext()); 178 } 179 getUnitUsedByThisProperty()180 private Unit getUnitUsedByThisProperty() { 181 Unit savedUnit = mCarUnitsManager.getUnitUsedByProperty(getPropertyId()); 182 if (savedUnit == null) { 183 return mDefaultUnit; 184 } 185 return savedUnit; 186 } 187 188 } 189