1 /* 2 * Copyright (C) 2015 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.google.android.car.kitchensink.hvac; 18 19 import static java.lang.Integer.toHexString; 20 21 import android.car.VehicleAreaSeat; 22 import android.car.VehicleAreaWindow; 23 import android.car.VehicleUnit; 24 import android.car.hardware.CarPropertyConfig; 25 import android.car.hardware.CarPropertyValue; 26 import android.car.hardware.hvac.CarHvacManager; 27 import android.os.Bundle; 28 import android.os.Handler; 29 import android.util.Log; 30 import android.view.LayoutInflater; 31 import android.view.View; 32 import android.view.ViewGroup; 33 import android.widget.Button; 34 import android.widget.RadioButton; 35 import android.widget.RadioGroup; 36 import android.widget.TextView; 37 import android.widget.Toast; 38 import android.widget.ToggleButton; 39 40 import androidx.fragment.app.Fragment; 41 42 import com.google.android.car.kitchensink.KitchenSinkActivity; 43 import com.google.android.car.kitchensink.R; 44 45 import java.util.List; 46 47 public class HvacTestFragment extends Fragment { 48 private static final boolean DBG = true; 49 private static final String TAG = HvacTestFragment.class.getSimpleName(); 50 private static final float TEMP_STEP = 0.5f; 51 52 private RadioButton mRbFanPositionFace; 53 private RadioButton mRbFanPositionFloor; 54 private RadioButton mRbFanPositionFaceAndFloor; 55 private RadioButton mRbFanPositionDefrost; 56 private RadioButton mRbFanPositionDefrostAndFloor; 57 private ToggleButton mTbAc; 58 private ToggleButton mTbAuto; 59 private ToggleButton mTbDefrostFront; 60 private ToggleButton mTbDefrostRear; 61 private ToggleButton mTbDual; 62 private ToggleButton mTbMaxAc; 63 private ToggleButton mTbMaxDefrost; 64 private ToggleButton mTbRecirc; 65 private ToggleButton mTbAutoRecirc; 66 private ToggleButton mTbTempDisplayUnit; 67 private ToggleButton mTbPower; 68 private Button mTbPowerAndAc; 69 private TextView mTvFanSpeed; 70 private TextView mTvDTemp; 71 private TextView mTvPTemp; 72 private TextView mTvOutsideTemp; 73 private int[] mCurFanSpeeds; 74 private int[] mMinFanSpeeds; 75 private int[] mMaxFanSpeeds; 76 private float mCurDTemp; 77 private float mCurPTemp; 78 private float mMinDTemp; 79 private float mMinPTemp; 80 private float mMaxDTemp; 81 private float mMaxPTemp; 82 private CarHvacManager mCarHvacManager; 83 private int mZoneForSetTempD; 84 private int mZoneForSetTempP; 85 private int[] mZonesForFanSpeed; 86 private List<CarPropertyConfig> mCarPropertyConfigs; 87 private View mHvacView; 88 89 private final CarHvacManager.CarHvacEventCallback mHvacCallback = 90 new CarHvacManager.CarHvacEventCallback() { 91 @Override 92 public void onChangeEvent(final CarPropertyValue value) { 93 int zones = value.getAreaId(); 94 switch (value.getPropertyId()) { 95 case CarHvacManager.ID_OUTSIDE_AIR_TEMP: 96 mTvOutsideTemp.setText(String.valueOf(value.getValue())); 97 break; 98 case CarHvacManager.ID_ZONED_DUAL_ZONE_ON: 99 mTbDual.setChecked((boolean) value.getValue()); 100 break; 101 case CarHvacManager.ID_ZONED_AC_ON: 102 mTbAc.setChecked((boolean) value.getValue()); 103 break; 104 case CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON: 105 mTbAuto.setChecked((boolean) value.getValue()); 106 break; 107 case CarHvacManager.ID_ZONED_FAN_DIRECTION: 108 switch ((int) value.getValue()) { 109 case CarHvacManager.FAN_DIRECTION_FACE: 110 mRbFanPositionFace.setChecked(true); 111 break; 112 case CarHvacManager.FAN_DIRECTION_FLOOR: 113 mRbFanPositionFloor.setChecked(true); 114 break; 115 case (CarHvacManager.FAN_DIRECTION_FACE | 116 CarHvacManager.FAN_DIRECTION_FLOOR): 117 mRbFanPositionFaceAndFloor.setChecked(true); 118 break; 119 case CarHvacManager.FAN_DIRECTION_DEFROST: 120 mRbFanPositionDefrost.setChecked(true); 121 break; 122 case (CarHvacManager.FAN_DIRECTION_DEFROST | 123 CarHvacManager.FAN_DIRECTION_FLOOR): 124 mRbFanPositionDefrostAndFloor.setChecked(true); 125 break; 126 default: 127 if (DBG) { 128 Log.e(TAG, "Unknown fan position: " + value.getValue()); 129 } 130 break; 131 } 132 break; 133 case CarHvacManager.ID_ZONED_MAX_AC_ON: 134 mTbMaxAc.setChecked((boolean) value.getValue()); 135 break; 136 case CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON: 137 mTbRecirc.setChecked((boolean) value.getValue()); 138 break; 139 case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT: 140 for (int i = 0; i < mZonesForFanSpeed.length; i++) { 141 if (zones == mZonesForFanSpeed[i]) { 142 mCurFanSpeeds[i] = (int) value.getValue(); 143 if (i == 0) { 144 mTvFanSpeed.setText(String.valueOf(mCurFanSpeeds[i])); 145 } 146 break; 147 } 148 } 149 break; 150 case CarHvacManager.ID_ZONED_TEMP_SETPOINT: 151 if ((zones & mZoneForSetTempD) == mZoneForSetTempD) { 152 mCurDTemp = (float) value.getValue(); 153 mTvDTemp.setText(String.valueOf(mCurDTemp)); 154 } 155 if ((zones & mZoneForSetTempP) == mZoneForSetTempP) { 156 mCurPTemp = (float) value.getValue(); 157 mTvPTemp.setText(String.valueOf(mCurPTemp)); 158 } 159 break; 160 case CarHvacManager.ID_ZONED_MAX_DEFROST_ON: 161 mTbMaxDefrost.setChecked((boolean) value.getValue()); 162 break; 163 case CarHvacManager.ID_WINDOW_DEFROSTER_ON: 164 if ((zones & VehicleAreaWindow.WINDOW_FRONT_WINDSHIELD) 165 == VehicleAreaWindow.WINDOW_FRONT_WINDSHIELD) { 166 mTbDefrostFront.setChecked((boolean) value.getValue()); 167 } 168 if ((zones & VehicleAreaWindow.WINDOW_REAR_WINDSHIELD) 169 == VehicleAreaWindow.WINDOW_REAR_WINDSHIELD) { 170 mTbDefrostRear.setChecked((boolean) value.getValue()); 171 } 172 break; 173 case CarHvacManager.ID_ZONED_HVAC_AUTO_RECIRC_ON: 174 mTbAutoRecirc.setChecked((boolean) value.getValue()); 175 break; 176 case CarHvacManager.ID_TEMPERATURE_DISPLAY_UNITS: 177 mTbTempDisplayUnit.setChecked( 178 ((Integer) value.getValue()).equals(VehicleUnit.FAHRENHEIT)); 179 break; 180 case CarHvacManager.ID_ZONED_HVAC_POWER_ON: 181 mTbPower.setChecked((boolean) value.getValue()); 182 break; 183 default: 184 Log.d(TAG, "onChangeEvent(): unknown property id = " + value 185 .getPropertyId()); 186 } 187 } 188 189 @Override 190 public void onErrorEvent(final int propertyId, final int zone) { 191 Log.w(TAG, "Error: propertyId=0x" + toHexString(propertyId) 192 + ", zone=0x" + toHexString(zone)); 193 } 194 }; 195 196 @Override onDestroy()197 public void onDestroy() { 198 super.onDestroy(); 199 mCarHvacManager.unregisterCallback(mHvacCallback); 200 } 201 202 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance)203 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstance) { 204 mHvacView = inflater.inflate(R.layout.hvac_test, container, false); 205 final Runnable r = () -> { 206 mCarHvacManager = ((KitchenSinkActivity) getActivity()).getHvacManager(); 207 mCarHvacManager.registerCallback(mHvacCallback); 208 mCarPropertyConfigs = mCarHvacManager.getPropertyList(); 209 for (CarPropertyConfig prop : mCarPropertyConfigs) { 210 int propId = prop.getPropertyId(); 211 212 if (DBG) { 213 Log.d(TAG, prop.toString()); 214 } 215 216 switch (propId) { 217 case CarHvacManager.ID_OUTSIDE_AIR_TEMP: 218 // Nothing is done in this case. 219 break; 220 case CarHvacManager.ID_ZONED_DUAL_ZONE_ON: 221 configureDualOn(mHvacView, prop); 222 break; 223 case CarHvacManager.ID_ZONED_AC_ON: 224 configureAcOn(mHvacView, prop); 225 break; 226 case CarHvacManager.ID_ZONED_FAN_DIRECTION: 227 configureFanPosition(mHvacView, prop); 228 break; 229 case CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT: 230 configureFanSpeed(mHvacView, prop); 231 break; 232 case CarHvacManager.ID_ZONED_TEMP_SETPOINT: 233 configureTempSetpoint(mHvacView, prop); 234 break; 235 case CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON: 236 configureAutoModeOn(mHvacView, prop); 237 break; 238 case CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON: 239 configureRecircOn(mHvacView, prop); 240 break; 241 case CarHvacManager.ID_ZONED_MAX_AC_ON: 242 configureMaxAcOn(mHvacView, prop); 243 break; 244 case CarHvacManager.ID_ZONED_MAX_DEFROST_ON: 245 configureMaxDefrostOn(mHvacView, prop); 246 break; 247 case CarHvacManager.ID_WINDOW_DEFROSTER_ON: 248 configureDefrosterOn(mHvacView, prop); 249 break; 250 case CarHvacManager.ID_ZONED_HVAC_AUTO_RECIRC_ON: 251 configureAutoRecircOn(mHvacView, prop); 252 break; 253 case CarHvacManager.ID_TEMPERATURE_DISPLAY_UNITS: 254 configureTempDisplayUnit(mHvacView, prop); 255 break; 256 case CarHvacManager.ID_ZONED_HVAC_POWER_ON: 257 configurePowerOn(mHvacView, prop); 258 configurePowerAndAcOn(mHvacView, prop); 259 break; 260 default: 261 Log.w(TAG, "propertyId " + propId + " is not handled"); 262 break; 263 } 264 } 265 266 mTvFanSpeed = (TextView) mHvacView.findViewById(R.id.tvFanSpeed); 267 mTvFanSpeed.setText(String.valueOf(mCurFanSpeeds[0])); 268 mTvDTemp = (TextView) mHvacView.findViewById(R.id.tvDTemp); 269 mTvDTemp.setText(String.valueOf(mCurDTemp)); 270 mTvPTemp = (TextView) mHvacView.findViewById(R.id.tvPTemp); 271 mTvPTemp.setText(String.valueOf(mCurPTemp)); 272 mTvOutsideTemp = (TextView) mHvacView.findViewById(R.id.tvOutsideTemp); 273 mTvOutsideTemp.setText("N/A"); 274 }; 275 276 ((KitchenSinkActivity) getActivity()).requestRefreshManager(r, 277 new Handler(getContext().getMainLooper())); 278 279 if (DBG) { 280 Log.d(TAG, "Starting HvacTestFragment"); 281 } 282 283 return mHvacView; 284 } 285 configureDualOn(View v, CarPropertyConfig prop)286 private void configureDualOn(View v, CarPropertyConfig prop) { 287 int[] areaIds = prop.getAreaIds(); 288 mTbDual = (ToggleButton) v.findViewById(R.id.tbDual); 289 mTbDual.setEnabled(true); 290 291 mTbDual.setOnClickListener(view -> { 292 for (int i = 0; i < areaIds.length; i++) { 293 setBooleanProperty(CarHvacManager.ID_ZONED_DUAL_ZONE_ON, areaIds[i], 294 mTbDual.isChecked()); 295 } 296 }); 297 } 298 configureAcOn(View v, CarPropertyConfig prop)299 private void configureAcOn(View v, CarPropertyConfig prop) { 300 int[] areaIds = prop.getAreaIds(); 301 mTbAc = (ToggleButton) v.findViewById(R.id.tbAc); 302 mTbAc.setEnabled(true); 303 304 mTbAc.setOnClickListener(view -> { 305 for (int i = 0; i < areaIds.length; i++) { 306 setBooleanProperty(CarHvacManager.ID_ZONED_AC_ON, areaIds[i], mTbAc.isChecked()); 307 } 308 }); 309 } 310 configureAutoModeOn(View v, CarPropertyConfig prop)311 private void configureAutoModeOn(View v, CarPropertyConfig prop) { 312 int[] areaIds = prop.getAreaIds(); 313 mTbAuto = (ToggleButton) v.findViewById(R.id.tbAuto); 314 mTbAuto.setEnabled(true); 315 316 mTbAuto.setOnClickListener(view -> { 317 for (int i = 0; i < areaIds.length; i++) { 318 setBooleanProperty(CarHvacManager.ID_ZONED_AUTOMATIC_MODE_ON, areaIds[i], 319 mTbAuto.isChecked()); 320 } 321 }); 322 } 323 configureFanPosition(View v, CarPropertyConfig prop)324 private void configureFanPosition(View v, CarPropertyConfig prop) { 325 int[] areaIds = prop.getAreaIds(); 326 RadioGroup rg = (RadioGroup) v.findViewById(R.id.rgFanPosition); 327 rg.setOnCheckedChangeListener((group, checkedId) -> { 328 int position; 329 switch (checkedId) { 330 case R.id.rbPositionFace: 331 position = CarHvacManager.FAN_DIRECTION_FACE; 332 break; 333 case R.id.rbPositionFloor: 334 position = CarHvacManager.FAN_DIRECTION_FLOOR; 335 break; 336 case R.id.rbPositionFaceAndFloor: 337 position = (CarHvacManager.FAN_DIRECTION_FACE | 338 CarHvacManager.FAN_DIRECTION_FLOOR); 339 break; 340 case R.id.rbPositionDefrost: 341 position = CarHvacManager.FAN_DIRECTION_DEFROST; 342 break; 343 case R.id.rbPositionDefrostAndFloor: 344 position = (CarHvacManager.FAN_DIRECTION_DEFROST | 345 CarHvacManager.FAN_DIRECTION_FLOOR); 346 break; 347 default: 348 throw new IllegalStateException("Unexpected fan position: " + checkedId); 349 } 350 try { 351 for (int i = 0; i < areaIds.length; i++) { 352 if (mCarHvacManager.isPropertyAvailable(CarHvacManager.ID_ZONED_FAN_DIRECTION, 353 mZonesForFanSpeed[i])) { 354 mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_DIRECTION, 355 areaIds[i], position); 356 } 357 } 358 } catch (IllegalStateException e) { 359 Log.e(TAG, "Failed to set HVAC integer property", e); 360 Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 361 } 362 }); 363 364 mRbFanPositionFace = (RadioButton) v.findViewById(R.id.rbPositionFace); 365 mRbFanPositionFace.setClickable(true); 366 mRbFanPositionFloor = (RadioButton) v.findViewById(R.id.rbPositionFloor); 367 mRbFanPositionFloor.setClickable(true); 368 mRbFanPositionFaceAndFloor = (RadioButton) v.findViewById(R.id.rbPositionFaceAndFloor); 369 mRbFanPositionFaceAndFloor.setClickable(true); 370 mRbFanPositionDefrost = (RadioButton) v.findViewById(R.id.rbPositionDefrost); 371 mRbFanPositionDefrost.setClickable(true); 372 mRbFanPositionDefrostAndFloor = (RadioButton) v.findViewById( 373 R.id.rbPositionDefrostAndFloor); 374 mRbFanPositionDefrostAndFloor.setClickable(true); 375 } 376 configureFanSpeed(View v, CarPropertyConfig prop)377 private void configureFanSpeed(View v, CarPropertyConfig prop) { 378 mZonesForFanSpeed = prop.getAreaIds(); 379 mCurFanSpeeds = new int[mZonesForFanSpeed.length]; 380 mMaxFanSpeeds = new int[mZonesForFanSpeed.length]; 381 mMinFanSpeeds = new int[mZonesForFanSpeed.length]; 382 383 for (int i = 0; i < mZonesForFanSpeed.length; i++) { 384 mMaxFanSpeeds[i] = (Integer) prop.getMaxValue(mZonesForFanSpeed[i]); 385 mMinFanSpeeds[i] = (Integer) prop.getMinValue(mZonesForFanSpeed[i]); 386 } 387 388 try { 389 for (int i = 0; i < mZonesForFanSpeed.length; i++) { 390 mCurFanSpeeds[i] = mCarHvacManager.getIntProperty( 391 CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT, mZonesForFanSpeed[i]); 392 } 393 } catch (IllegalStateException e) { 394 Log.e(TAG, "Failed to get HVAC int property", e); 395 } 396 397 Button btnFanSpeedUp = (Button) v.findViewById(R.id.btnFanSpeedUp); 398 btnFanSpeedUp.setEnabled(true); 399 btnFanSpeedUp.setOnClickListener(view -> changeFanSpeed(1)); 400 401 Button btnFanSpeedDn = (Button) v.findViewById(R.id.btnFanSpeedDn); 402 btnFanSpeedDn.setEnabled(true); 403 btnFanSpeedDn.setOnClickListener(view -> changeFanSpeed(-1)); 404 } 405 changeFanSpeed(int change)406 private void changeFanSpeed(int change) { 407 for (int i = 0; i < mZonesForFanSpeed.length; i++) { 408 int targetSpeed = mCurFanSpeeds[i] + change; 409 if (mMinFanSpeeds[i] <= targetSpeed && targetSpeed <= mMaxFanSpeeds[i]) { 410 mCurFanSpeeds[i] = targetSpeed; 411 if (i == 0) { 412 mTvFanSpeed.setText(String.valueOf(mCurFanSpeeds[i])); 413 } 414 try { 415 if (mCarHvacManager.isPropertyAvailable( 416 CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT, mZonesForFanSpeed[i])) { 417 mCarHvacManager.setIntProperty(CarHvacManager.ID_ZONED_FAN_SPEED_SETPOINT, 418 mZonesForFanSpeed[i], mCurFanSpeeds[i]); 419 } 420 } catch (IllegalStateException e) { 421 Log.e(TAG, "Failed to set HVAC int property", e); 422 Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 423 } 424 } 425 } 426 } 427 configureTempSetpoint(View v, CarPropertyConfig prop)428 private void configureTempSetpoint(View v, CarPropertyConfig prop) { 429 430 mZoneForSetTempD = 0; 431 if (prop.hasArea(VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT 432 | VehicleAreaSeat.SEAT_ROW_2_CENTER)) { 433 mZoneForSetTempD = VehicleAreaSeat.SEAT_ROW_1_LEFT | VehicleAreaSeat.SEAT_ROW_2_LEFT 434 | VehicleAreaSeat.SEAT_ROW_2_CENTER; 435 } 436 mZoneForSetTempP = 0; 437 if (prop.hasArea(VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT)) { 438 mZoneForSetTempP = VehicleAreaSeat.SEAT_ROW_1_RIGHT | VehicleAreaSeat.SEAT_ROW_2_RIGHT; 439 } 440 int[] areas = prop.getAreaIds(); 441 if (mZoneForSetTempD == 0 && areas.length > 1) { 442 mZoneForSetTempD = areas[0]; 443 } 444 if (mZoneForSetTempP == 0 && areas.length > 2) { 445 mZoneForSetTempP = areas[1]; 446 } 447 Button btnDTempUp = (Button) v.findViewById(R.id.btnDTempUp); 448 if (mZoneForSetTempD != 0) { 449 mMaxDTemp = (Float) prop.getMaxValue(mZoneForSetTempD); 450 mMinDTemp = (Float) prop.getMinValue(mZoneForSetTempD); 451 452 453 try { 454 mCurDTemp = mCarHvacManager.getFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT, 455 mZoneForSetTempD); 456 if (mCurDTemp < mMinDTemp) { 457 mCurDTemp = mMinDTemp; 458 } else if (mCurDTemp > mMaxDTemp) { 459 mCurDTemp = mMaxDTemp; 460 } 461 } catch (IllegalStateException e) { 462 Log.e(TAG, "Failed to get HVAC zoned temp property", e); 463 } 464 btnDTempUp.setEnabled(true); 465 btnDTempUp.setOnClickListener(view -> changeDriverTemperature(TEMP_STEP)); 466 467 Button btnDTempDn = (Button) v.findViewById(R.id.btnDTempDn); 468 btnDTempDn.setEnabled(true); 469 btnDTempDn.setOnClickListener(view -> changeDriverTemperature(-TEMP_STEP)); 470 } else { 471 btnDTempUp.setEnabled(false); 472 } 473 474 Button btnPTempUp = (Button) v.findViewById(R.id.btnPTempUp); 475 if (mZoneForSetTempP != 0) { 476 mMaxPTemp = (Float) prop.getMaxValue(mZoneForSetTempP); 477 mMinPTemp = (Float) prop.getMinValue(mZoneForSetTempP); 478 479 try { 480 mCurPTemp = mCarHvacManager.getFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT, 481 mZoneForSetTempP); 482 if (mCurPTemp < mMinPTemp) { 483 mCurPTemp = mMinPTemp; 484 } else if (mCurPTemp > mMaxPTemp) { 485 mCurPTemp = mMaxPTemp; 486 } 487 } catch (IllegalStateException e) { 488 Log.e(TAG, "Failed to get HVAC zoned temp property", e); 489 } 490 btnPTempUp.setEnabled(true); 491 btnPTempUp.setOnClickListener(view -> changePassengerTemperature(TEMP_STEP)); 492 493 Button btnPTempDn = (Button) v.findViewById(R.id.btnPTempDn); 494 btnPTempDn.setEnabled(true); 495 btnPTempDn.setOnClickListener(view -> changePassengerTemperature(-TEMP_STEP)); 496 } else { 497 btnPTempUp.setEnabled(false); 498 } 499 500 Button btnATempUp = (Button) v.findViewById(R.id.btnATempUp); 501 if (mZoneForSetTempD != 0 && mZoneForSetTempP != 0) { 502 btnATempUp.setEnabled(true); 503 btnATempUp.setOnClickListener(view -> { 504 changeDriverTemperature(TEMP_STEP); 505 changePassengerTemperature(TEMP_STEP); 506 }); 507 508 Button btnATempDn = (Button) v.findViewById(R.id.btnATempDn); 509 btnATempDn.setEnabled(true); 510 btnATempDn.setOnClickListener(view -> { 511 changeDriverTemperature(-TEMP_STEP); 512 changePassengerTemperature(-TEMP_STEP); 513 }); 514 } else { 515 btnATempUp.setEnabled(false); 516 } 517 } 518 changeDriverTemperature(float tempStep)519 private void changeDriverTemperature(float tempStep) { 520 float targetTemp = mCurDTemp + tempStep; 521 if (mMinDTemp < targetTemp && targetTemp < mMaxDTemp) { 522 mCurDTemp = targetTemp; 523 mTvDTemp.setText(String.valueOf(mCurDTemp)); 524 setFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT, mZoneForSetTempD, mCurDTemp); 525 } 526 } 527 changePassengerTemperature(float tempStep)528 private void changePassengerTemperature(float tempStep) { 529 float targetTemp = mCurPTemp + tempStep; 530 if (mMinPTemp < targetTemp && targetTemp < mMaxPTemp) { 531 mCurPTemp = targetTemp; 532 mTvPTemp.setText(String.valueOf(mCurPTemp)); 533 setFloatProperty(CarHvacManager.ID_ZONED_TEMP_SETPOINT, mZoneForSetTempP, mCurPTemp); 534 } 535 } 536 configureDefrosterOn(View v, CarPropertyConfig prop1)537 private void configureDefrosterOn(View v, CarPropertyConfig prop1) { 538 if (prop1.hasArea(VehicleAreaWindow.WINDOW_FRONT_WINDSHIELD)) { 539 mTbDefrostFront = (ToggleButton) v.findViewById(R.id.tbDefrostFront); 540 mTbDefrostFront.setEnabled(true); 541 mTbDefrostFront.setOnClickListener(view -> { 542 setBooleanProperty(CarHvacManager.ID_WINDOW_DEFROSTER_ON, 543 VehicleAreaWindow.WINDOW_FRONT_WINDSHIELD, mTbDefrostFront.isChecked()); 544 }); 545 } 546 if (prop1.hasArea(VehicleAreaWindow.WINDOW_REAR_WINDSHIELD)) { 547 mTbDefrostRear = (ToggleButton) v.findViewById(R.id.tbDefrostRear); 548 mTbDefrostRear.setEnabled(true); 549 mTbDefrostRear.setOnClickListener(view -> { 550 setBooleanProperty(CarHvacManager.ID_WINDOW_DEFROSTER_ON, 551 VehicleAreaWindow.WINDOW_REAR_WINDSHIELD, mTbDefrostRear.isChecked()); 552 }); 553 } 554 } 555 configureRecircOn(View v, CarPropertyConfig prop)556 private void configureRecircOn(View v, CarPropertyConfig prop) { 557 int[] areaIds = prop.getAreaIds(); 558 mTbRecirc = (ToggleButton) v.findViewById(R.id.tbRecirc); 559 mTbRecirc.setEnabled(true); 560 561 mTbRecirc.setOnClickListener(view -> { 562 for (int i = 0; i < areaIds.length; i++) { 563 setBooleanProperty(CarHvacManager.ID_ZONED_AIR_RECIRCULATION_ON, areaIds[i], 564 mTbRecirc.isChecked()); 565 } 566 }); 567 } 568 configureMaxAcOn(View v, CarPropertyConfig prop)569 private void configureMaxAcOn(View v, CarPropertyConfig prop) { 570 int[] areaIds = prop.getAreaIds(); 571 mTbMaxAc = (ToggleButton) v.findViewById(R.id.tbMaxAc); 572 mTbMaxAc.setEnabled(true); 573 574 mTbMaxAc.setOnClickListener(view -> { 575 for (int i = 0; i < areaIds.length; i++) { 576 setBooleanProperty(CarHvacManager.ID_ZONED_MAX_AC_ON, areaIds[i], 577 mTbMaxAc.isChecked()); 578 } 579 }); 580 } 581 configureMaxDefrostOn(View v, CarPropertyConfig prop)582 private void configureMaxDefrostOn(View v, CarPropertyConfig prop) { 583 int[] areaIds = prop.getAreaIds(); 584 mTbMaxDefrost = (ToggleButton) v.findViewById(R.id.tbMaxDefrost); 585 mTbMaxDefrost.setEnabled(true); 586 587 mTbMaxDefrost.setOnClickListener(view -> { 588 for (int i = 0; i < areaIds.length; i++) { 589 setBooleanProperty(CarHvacManager.ID_ZONED_MAX_DEFROST_ON, areaIds[i], 590 mTbMaxDefrost.isChecked()); 591 } 592 }); 593 } 594 configureAutoRecircOn(View v, CarPropertyConfig prop)595 private void configureAutoRecircOn(View v, CarPropertyConfig prop) { 596 int[] areaIds = prop.getAreaIds(); 597 mTbAutoRecirc = (ToggleButton) v.findViewById(R.id.tbAutoRecirc); 598 mTbAutoRecirc.setEnabled(true); 599 600 mTbAutoRecirc.setOnClickListener(view -> { 601 for (int i = 0; i < areaIds.length; i++) { 602 setBooleanProperty(CarHvacManager.ID_ZONED_HVAC_AUTO_RECIRC_ON, areaIds[i], 603 mTbAutoRecirc.isChecked()); 604 } 605 }); 606 } 607 configureTempDisplayUnit(View v, CarPropertyConfig prop)608 private void configureTempDisplayUnit(View v, CarPropertyConfig prop) { 609 int areaId = prop.getFirstAndOnlyAreaId(); 610 mTbTempDisplayUnit = (ToggleButton) v.findViewById(R.id.tbTempDisplayUnit); 611 mTbTempDisplayUnit.setEnabled(true); 612 613 mTbTempDisplayUnit.setOnClickListener(view -> { 614 int unit = 615 (mTbTempDisplayUnit.isChecked() ? VehicleUnit.FAHRENHEIT : VehicleUnit.CELSIUS); 616 setIntProperty(CarHvacManager.ID_TEMPERATURE_DISPLAY_UNITS, areaId, unit); 617 }); 618 } 619 configurePowerOn(View v, CarPropertyConfig prop)620 private void configurePowerOn(View v, CarPropertyConfig prop) { 621 int[] areaIds = prop.getAreaIds(); 622 mTbPower = (ToggleButton) v.findViewById(R.id.tbPower); 623 mTbPower.setEnabled(true); 624 625 mTbPower.setOnClickListener(view -> { 626 for (int i = 0; i < areaIds.length; i++) { 627 setBooleanProperty(CarHvacManager.ID_ZONED_HVAC_POWER_ON, areaIds[i], 628 mTbPower.isChecked()); 629 } 630 }); 631 } 632 configurePowerAndAcOn(View v, CarPropertyConfig prop)633 private void configurePowerAndAcOn(View v, CarPropertyConfig prop) { 634 int[] areaIds = prop.getAreaIds(); 635 mTbPowerAndAc = (Button) v.findViewById(R.id.tbPowerAndAc); 636 mTbPowerAndAc.setEnabled(true); 637 638 mTbPowerAndAc.setOnClickListener(view -> { 639 for (int i = 0; i < areaIds.length; i++) { 640 setBooleanProperty(CarHvacManager.ID_ZONED_HVAC_POWER_ON, areaIds[i], true); 641 setBooleanProperty(CarHvacManager.ID_ZONED_AC_ON, areaIds[i], true); 642 } 643 }); 644 } 645 setBooleanProperty(int propertyId, int areaId, boolean value)646 private void setBooleanProperty(int propertyId, int areaId, boolean value) { 647 try { 648 mCarHvacManager.setBooleanProperty(propertyId, areaId, value); 649 } catch (IllegalStateException e) { 650 Log.e(TAG, "Failed to set boolean property", e); 651 Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 652 } 653 } 654 setIntProperty(int propertyId, int areaId, int value)655 private void setIntProperty(int propertyId, int areaId, int value) { 656 try { 657 mCarHvacManager.setIntProperty(propertyId, areaId, value); 658 } catch (IllegalStateException e) { 659 Log.e(TAG, "Failed to set int property", e); 660 Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 661 } 662 } 663 setFloatProperty(int propertyId, int areaId, float value)664 private void setFloatProperty(int propertyId, int areaId, float value) { 665 try { 666 mCarHvacManager.setFloatProperty(propertyId, areaId, value); 667 } catch (IllegalStateException e) { 668 Log.e(TAG, "Failed to set float property", e); 669 Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); 670 } 671 } 672 } 673