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