1 /* 2 * Copyright (C) 2021 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 package com.android.systemui.car.hvac.referenceui; 18 19 import static android.car.VehiclePropertyIds.HVAC_AUTO_ON; 20 import static android.car.VehiclePropertyIds.HVAC_FAN_DIRECTION; 21 import static android.car.VehiclePropertyIds.HVAC_POWER_ON; 22 23 import android.car.hardware.CarPropertyValue; 24 import android.content.Context; 25 import android.os.Build; 26 import android.util.AttributeSet; 27 import android.util.Log; 28 import android.widget.ImageView; 29 import android.widget.LinearLayout; 30 31 import androidx.annotation.IntDef; 32 import androidx.annotation.Nullable; 33 34 import com.android.systemui.R; 35 import com.android.systemui.car.hvac.HvacController; 36 import com.android.systemui.car.hvac.HvacPropertySetter; 37 import com.android.systemui.car.hvac.HvacView; 38 39 import java.util.ArrayList; 40 import java.util.HashMap; 41 import java.util.List; 42 import java.util.Map; 43 44 /** 45 * A group of buttons that allows users to select the fan direction. Only one button can be 46 * activated at a time. 47 */ 48 public class FanDirectionButtons extends LinearLayout implements HvacView { 49 50 /** 51 * NOTE: The integers below are not arbitrarily assigned and represent the corresponding values 52 * implemented in VHAL. 53 */ 54 public static final int FAN_DIRECTION_FACE = 1; 55 public static final int FAN_DIRECTION_FACE_FLOOR = 3; 56 public static final int FAN_DIRECTION_FLOOR = 2; 57 public static final int FAN_DIRECTION_FLOOR_DEFROSTER = 6; 58 public static final int FAN_DIRECTION_COUNT = 4; 59 60 private static final int INVALID_ID = -1; 61 private static final String TAG = FanDirectionButtons.class.getSimpleName(); 62 private static final boolean DEBUG = Build.IS_ENG || Build.IS_USERDEBUG; 63 64 @IntDef({FAN_DIRECTION_FACE, FAN_DIRECTION_FACE_FLOOR, 65 FAN_DIRECTION_FLOOR, FAN_DIRECTION_FLOOR_DEFROSTER}) 66 public @interface FanDirection { 67 } 68 69 /** 70 * A resource ID array for all fan direction buttons. 71 */ 72 private static final int[] FAN_DIRECTION_BUTTON_IDS = {R.id.direction_face, 73 R.id.direction_face_and_floor, R.id.direction_floor, R.id.direction_defrost}; 74 75 private final List<ImageView> mButtons = new ArrayList<ImageView>(); 76 private final List<Integer> mButtonDirections = new ArrayList<>(); 77 private final Map<Integer, Integer> mButtonIndicesByDirection = new HashMap<>(); 78 79 private HvacPropertySetter mHvacPropertySetter; 80 private boolean mPowerOn; 81 private boolean mAutoOn; 82 private float mOnAlpha; 83 private float mOffAlpha; 84 private int mCurrentDirection = INVALID_ID; 85 private int mHvacGlobalAreaId; 86 FanDirectionButtons(Context context)87 public FanDirectionButtons(Context context) { 88 super(context); 89 init(); 90 } 91 FanDirectionButtons(Context context, @Nullable AttributeSet attrs)92 public FanDirectionButtons(Context context, @Nullable AttributeSet attrs) { 93 super(context, attrs); 94 init(); 95 } 96 FanDirectionButtons(Context context, @Nullable AttributeSet attrs, int defStyleAttr)97 public FanDirectionButtons(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 98 super(context, attrs, defStyleAttr); 99 init(); 100 } 101 102 @Override onFinishInflate()103 protected void onFinishInflate() { 104 super.onFinishInflate(); 105 106 mOnAlpha = mContext.getResources().getFloat(R.dimen.hvac_turned_on_alpha); 107 mOffAlpha = mContext.getResources().getFloat(R.dimen.hvac_turned_off_alpha); 108 109 for (int i = 0; i < FAN_DIRECTION_COUNT; i++) { 110 ImageView button = (ImageView) findViewById(FAN_DIRECTION_BUTTON_IDS[i]); 111 int fanDirection = mButtonDirections.get(i); 112 button.setOnClickListener(v -> { 113 if (!shouldAllowControl()) return; 114 if (fanDirection != mCurrentDirection) { 115 mHvacPropertySetter.setHvacProperty(HVAC_FAN_DIRECTION, getAreaId(), 116 fanDirection); 117 } 118 }); 119 mButtons.add(button); 120 } 121 } 122 123 @Override setHvacPropertySetter(HvacPropertySetter hvacPropertySetter)124 public void setHvacPropertySetter(HvacPropertySetter hvacPropertySetter) { 125 mHvacPropertySetter = hvacPropertySetter; 126 } 127 128 @Override onPropertyChanged(CarPropertyValue value)129 public void onPropertyChanged(CarPropertyValue value) { 130 if (value.getPropertyId() == HVAC_FAN_DIRECTION) { 131 int newDirection = (Integer) value.getValue(); 132 if (!mButtonDirections.contains(newDirection)) { 133 if (DEBUG) { 134 Log.w(TAG, "Button is not defined for direction: " + newDirection); 135 } 136 return; 137 } 138 139 if (mCurrentDirection != INVALID_ID) { 140 mButtons.get(mButtonIndicesByDirection.get(mCurrentDirection)) 141 .setSelected(false); 142 } 143 mCurrentDirection = newDirection; 144 mButtons.get(mButtonIndicesByDirection.get(mCurrentDirection)) 145 .setSelected(true); 146 147 return; 148 } 149 150 if (value.getPropertyId() == HVAC_POWER_ON) { 151 mPowerOn = (Boolean) value.getValue(); 152 } 153 154 if (value.getPropertyId() == HVAC_AUTO_ON) { 155 mAutoOn = (Boolean) value.getValue(); 156 } 157 158 updateViewPerAvailability(); 159 } 160 161 @Override getHvacPropertyToView()162 public @HvacController.HvacProperty Integer getHvacPropertyToView() { 163 return HVAC_FAN_DIRECTION; 164 } 165 166 @Override getAreaId()167 public @HvacController.AreaId Integer getAreaId() { 168 return mHvacGlobalAreaId; 169 } 170 171 @Override onLocaleListChanged()172 public void onLocaleListChanged() { 173 // no-op. 174 } 175 176 @Override onHvacTemperatureUnitChanged(boolean usesFahrenheit)177 public void onHvacTemperatureUnitChanged(boolean usesFahrenheit) { 178 // no-op. 179 } 180 init()181 private void init() { 182 inflate(getContext(), R.layout.fan_direction, this); 183 mHvacGlobalAreaId = getContext().getResources().getInteger(R.integer.hvac_global_area_id); 184 mButtonDirections.add(FAN_DIRECTION_FACE); 185 mButtonDirections.add(FAN_DIRECTION_FACE_FLOOR); 186 mButtonDirections.add(FAN_DIRECTION_FLOOR); 187 mButtonDirections.add(FAN_DIRECTION_FLOOR_DEFROSTER); 188 189 mButtonIndicesByDirection.put(FAN_DIRECTION_FACE, 0); 190 mButtonIndicesByDirection.put(FAN_DIRECTION_FACE_FLOOR, 1); 191 mButtonIndicesByDirection.put(FAN_DIRECTION_FLOOR, 2); 192 mButtonIndicesByDirection.put(FAN_DIRECTION_FLOOR_DEFROSTER, 3); 193 } 194 updateViewPerAvailability()195 private void updateViewPerAvailability() { 196 setAlpha(shouldAllowControl() ? mOnAlpha : mOffAlpha); 197 } 198 shouldAllowControl()199 private boolean shouldAllowControl() { 200 return mPowerOn && !mAutoOn; 201 } 202 } 203