13cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal/*
23cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * Copyright (C) 2015 The Android Open Source Project
33cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal *
43cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * Licensed under the Apache License, Version 2.0 (the "License");
53cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * you may not use this file except in compliance with the License.
63cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * You may obtain a copy of the License at
73cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal *
83cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal *      http://www.apache.org/licenses/LICENSE-2.0
93cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal *
103cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * Unless required by applicable law or agreed to in writing, software
113cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * distributed under the License is distributed on an "AS IS" BASIS,
123cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * See the License for the specific language governing permissions and
143cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * limitations under the License.
153cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal */
163cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
173cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwalpackage com.android.car.hal;
183cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
190d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.annotation.Nullable;
20e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.car.hardware.radio.CarRadioEvent;
21e54ac276796c6535558f8444d882adecd19ce2bdKeun-young Parkimport android.car.hardware.radio.CarRadioPreset;
223cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwalimport android.hardware.radio.RadioManager;
23cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.VehiclePropConfig;
24cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
25cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.VehicleProperty;
26cfe93105f637c2822da113308f113ed418d0b319Pavel Maltsevimport android.hardware.automotive.vehicle.V2_0.VehicleRadioConstants;
270d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport android.util.Log;
283cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
293cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwalimport com.android.car.CarLog;
303cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
310d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport java.io.PrintWriter;
320d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport java.util.Arrays;
330d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsevimport java.util.Collection;
343cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwalimport java.util.LinkedList;
353cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwalimport java.util.List;
363cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
373cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal/**
383cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * This class exposes the Radio related features in the HAL layer.
393cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal *
403cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * The current set of features support radio presets. The rest of the radio functionality is already
413cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal * covered under RadioManager API.
423cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal */
433cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwalpublic class RadioHalService extends HalServiceBase {
441b1247b5648975dd41ee73c25425825abb256234Vitalii Tomkiv    public static boolean DBG = false;
453cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public static String TAG = CarLog.TAG_HAL + ".RadioHalService";
463cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
473cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    private int mPresetCount = 0;
483cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    private VehicleHal mHal;
493cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    private RadioListener mListener;
503cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
513cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public interface RadioListener {
520d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        void onEvent(CarRadioEvent event);
533cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
543cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
553cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public RadioHalService(VehicleHal hal) {
563cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        mHal = hal;
573cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
583cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
593cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    @Override
603cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public synchronized void init() {
613cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
623cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
633cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    @Override
643cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public synchronized void release() {
653cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        mListener = null;
663cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
673cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
683cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    @Override
690d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    public synchronized Collection<VehiclePropConfig> takeSupportedProperties(
700d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            Collection<VehiclePropConfig> allProperties) {
710d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        Collection<VehiclePropConfig> supported = new LinkedList<>();
723cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        for (VehiclePropConfig p : allProperties) {
733cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            if (handleRadioProperty(p)) {
743cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                supported.add(p);
753cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            }
763cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
773cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        return supported;
783cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
793cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
803cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    @Override
813cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public void handleHalEvents(List<VehiclePropValue> values) {
823cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (DBG) {
833cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            Log.d(TAG, "handleHalEvents");
843cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
850d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        RadioHalService.RadioListener radioListener;
863cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        synchronized (this) {
873cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            radioListener = mListener;
883cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
893cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
903cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (radioListener == null) {
913cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            Log.e(TAG, "radio listener is null, ignoring event: " + values);
923cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            return;
933cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
943cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
953cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        for (VehiclePropValue v : values) {
963cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            CarRadioEvent radioEvent = createCarRadioEvent(v);
973cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            if (radioEvent != null) {
983cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                if (DBG) {
993cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                    Log.d(TAG, "Sending event to listener: " + radioEvent);
1003cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                }
1013cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                radioListener.onEvent(radioEvent);
1023cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            } else {
1033cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                Log.w(TAG, "Value conversion failed: " + v);
1043cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            }
1053cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
1063cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
1073cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1083cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    @Override
1093cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public void dump(PrintWriter writer) {
1103cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        writer.println("*RadioHal*");
1113cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        writer.println("**Supported properties**");
1120d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        writer.println(VehicleProperty.RADIO_PRESET);
1133cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (mListener != null) {
1143cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            writer.println("Hal service registered.");
1153cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
1163cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
1173cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1183cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public synchronized void registerListener(RadioListener listener) {
1193cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (DBG) {
1203cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            Log.d(TAG, "registerListener");
1213cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
1223cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        mListener = listener;
1233cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1243cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        // Subscribe to all radio properties.
12579d5e12ad8708c1f7f7f1a60aaeb349ac7ed0f7bPavel Maltsev        mHal.subscribeProperty(this, VehicleProperty.RADIO_PRESET);
1263cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
1273cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1283cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public synchronized void unregisterListener() {
1293cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (DBG) {
1303cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            Log.d(TAG, "unregisterListener");
1313cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
1323cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        mListener = null;
1333cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1340d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        // Unsubscribe from all properties.
1350d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        mHal.unsubscribeProperty(this, VehicleProperty.RADIO_PRESET);
1363cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
1373cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1383cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public synchronized int getPresetCount() {
1393cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        Log.d(TAG, "get preset count: " + mPresetCount);
1403cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        return mPresetCount;
1413cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
1423cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1430d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev    @Nullable
1443cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public CarRadioPreset getRadioPreset(int presetNumber) {
1453cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        // Check if the preset number is out of range. We should return NULL if that is the case.
1463cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (DBG) {
1473cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            Log.d(TAG, "getRadioPreset called with preset number " + presetNumber);
1483cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
1493cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (!isValidPresetNumber(presetNumber)) {
1503cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            throw new IllegalArgumentException("Preset number not valid: " + presetNumber);
1513cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
1523cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1530d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        VehiclePropValue presetNumberValue = new VehiclePropValue();
1540d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        presetNumberValue.prop = VehicleProperty.RADIO_PRESET;
1550d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        presetNumberValue.value.int32Values.addAll(Arrays.asList(presetNumber, 0, 0, 0));
1563cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
157ba48548a489950968d212ffbfd8772ef1349cd60Keun-young Park        VehiclePropValue presetConfig;
158ba48548a489950968d212ffbfd8772ef1349cd60Keun-young Park        try {
1590d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            presetConfig = mHal.get(presetNumberValue);
1600d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        } catch (PropertyTimeoutException e) {
1610d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            Log.e(TAG, "property VehicleProperty.RADIO_PRESET not ready", e);
162ba48548a489950968d212ffbfd8772ef1349cd60Keun-young Park            return null;
163ba48548a489950968d212ffbfd8772ef1349cd60Keun-young Park        }
1643cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        // Sanity check the output from HAL.
1650d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (presetConfig.value.int32Values.size() != 4) {
1663cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            Log.e(TAG, "Return value does not have 4 elements: " +
1670d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                Arrays.toString(presetConfig.value.int32Values.toArray()));
1683cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            throw new IllegalStateException(
1690d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                "Invalid preset returned from service: "
1700d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                        + Arrays.toString(presetConfig.value.int32Values.toArray()));
1713cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
1723cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1730d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int retPresetNumber = presetConfig.value.int32Values.get(0);
1740d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int retBand = presetConfig.value.int32Values.get(1);
1750d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int retChannel = presetConfig.value.int32Values.get(2);
1760d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        int retSubChannel = presetConfig.value.int32Values.get(3);
1773cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (retPresetNumber != presetNumber) {
1783cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            Log.e(TAG, "Preset number is not the same: " + presetNumber + " vs " + retPresetNumber);
1793cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            return null;
1803cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
1813cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (!isValidBand(retBand)) return null;
1823cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1833cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        // Return the actual config.
1843cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        CarRadioPreset retConfig =
1853cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            new CarRadioPreset(retPresetNumber, retBand, retChannel, retSubChannel);
1863cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (DBG) {
1873cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            Log.d(TAG, "Preset obtained: " + retConfig);
1883cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
1893cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        return retConfig;
1903cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
1913cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1923cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    public boolean setRadioPreset(CarRadioPreset preset) {
1933cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (DBG) {
1943cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            Log.d(TAG, "setRadioPreset with config " + preset);
1953cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
1963cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
1973cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (!isValidPresetNumber(preset.getPresetNumber()) ||
1983cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            !isValidBand(preset.getBand())) {
1993cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            return false;
2003cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
2013cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
202e78bf53959151d07c90bbb69fd3f99240dd139b1Keun-young Park        try {
2030d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            mHal.set(VehicleProperty.RADIO_PRESET).to(new int[] {
2040d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    preset.getPresetNumber(),
2050d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    preset.getBand(),
2060d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    preset.getChannel(),
2070d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    preset.getSubChannel()});
2080d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        } catch (PropertyTimeoutException e) {
209e78bf53959151d07c90bbb69fd3f99240dd139b1Keun-young Park            Log.e(CarLog.TAG_POWER, "cannot set to RADIO_PRESET", e);
210e78bf53959151d07c90bbb69fd3f99240dd139b1Keun-young Park            return false;
211e78bf53959151d07c90bbb69fd3f99240dd139b1Keun-young Park        }
2123cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        return true;
2133cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
2143cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
2153cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    private boolean isValidPresetNumber(int presetNumber) {
2163cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        // Check for preset number.
2170d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        if (presetNumber < VehicleRadioConstants.VEHICLE_RADIO_PRESET_MIN_VALUE
2183cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            || presetNumber > mPresetCount) {
2193cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            Log.e(TAG, "Preset number not in range (1, " + mPresetCount + ") - " + presetNumber);
2203cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            return false;
2213cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
2223cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        return true;
2233cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
2243cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
2253cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    private boolean isValidBand(int band) {
2263cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        // Check for band info.
2273cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        if (band != RadioManager.BAND_AM &&
2283cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            band != RadioManager.BAND_FM &&
2293cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            band != RadioManager.BAND_FM_HD &&
2303cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            band != RadioManager.BAND_AM_HD) {
2313cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            Log.e(TAG, "Preset band is not valid: " + band);
2323cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            return false;
2333cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
2343cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        return true;
2353cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
2363cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
2373cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    private boolean handleRadioProperty(VehiclePropConfig property) {
2380d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        switch (property.prop) {
2390d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            case VehicleProperty.RADIO_PRESET:
2403cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                // Extract the count of presets.
2410d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                mPresetCount = property.configArray.get(0);
2423cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                Log.d(TAG, "Read presets count: " + mPresetCount);
2433cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                return true;
2443cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            default:
2453cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                return false;
2463cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
2473cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        // Should never come here.
2483cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
2493cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
2503cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    private CarRadioEvent createCarRadioEvent(VehiclePropValue v) {
2510d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev        switch (v.prop) {
2520d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev            case VehicleProperty.RADIO_PRESET:
2530d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                int vecSize = v.value.int32Values.size();
2540d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                if (vecSize != 4) {
2550d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                    Log.e(TAG, "Returned a wrong array size: " + vecSize);
2563cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                    return null;
2573cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                }
2583cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
2593cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                Integer intValues[] = new Integer[4];
2600d07c76bbc788fba8c77d8e932330ab22ec6ba27Pavel Maltsev                v.value.int32Values.toArray(intValues);
2613cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
2623cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                // Verify the correctness of the values.
2633cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                if (!isValidPresetNumber(intValues[0]) && !isValidBand(intValues[1])) {
2643cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                    return null;
2653cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                }
2663cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal
2673cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                CarRadioPreset preset =
2683cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                    new CarRadioPreset(intValues[0], intValues[1], intValues[2], intValues[3]);
2693cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                CarRadioEvent event = new CarRadioEvent(CarRadioEvent.RADIO_PRESET, preset);
2703cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                return event;
2713cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal            default:
2723cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                Log.e(TAG, "createCarRadioEvent: Value not supported as event: " + v);
2733cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal                return null;
2743cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal        }
2753cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal    }
2763cf096ae0d992d22cfba1b0711af2211c511a9feSanket Agarwal}
277