blob: 7514c8c40965c9c9e7107125c5509dbf6668cf0f [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.car.vehiclenetwork;
import android.annotation.Nullable;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import com.android.car.vehiclenetwork.VehicleNetworkConsts.VehicleValueType;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropConfigs;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValue;
import com.android.car.vehiclenetwork.VehicleNetworkProto.VehiclePropValues;
import java.lang.ref.WeakReference;
/**
* System API to access Vehicle network. This is only for system services and applications should
* not use this. All APIs will fail with security error if normal app tries this.
*/
public class VehicleNetwork {
public interface VehicleNetworkListener {
void onVehicleNetworkEvents(VehiclePropValues values);
}
private static final String TAG = VehicleNetwork.class.getSimpleName();
private final IVehicleNetwork mService;
private final VehicleNetworkListener mListener;
private final IVehicleNetworkListenerImpl mVehicleNetworkListener;
private final EventHandler mEventHandler;
public static VehicleNetwork createVehicleNetwork(VehicleNetworkListener listener,
Looper looper) {
IVehicleNetwork service = IVehicleNetwork.Stub.asInterface(ServiceManager.getService(
IVehicleNetwork.class.getCanonicalName()));
if (service == null) {
throw new RuntimeException("Vehicle network service not available:" +
IVehicleNetwork.class.getCanonicalName());
}
return new VehicleNetwork(service, listener, looper);
}
private VehicleNetwork(IVehicleNetwork service, VehicleNetworkListener listener,
Looper looper) {
mService = service;
mListener = listener;
mEventHandler = new EventHandler(looper);
mVehicleNetworkListener = new IVehicleNetworkListenerImpl(this);
}
public VehiclePropConfigs listProperties() {
return listProperties(0 /* all */);
}
public VehiclePropConfigs listProperties(int property) {
try {
VehiclePropConfigsParcelable parcelable = mService.listProperties(property);
if (parcelable != null) {
return parcelable.configs;
}
} catch (RemoteException e) {
handleRemoteException(e);
}
return null;
}
public void setProperty(VehiclePropValue value) {
VehiclePropValueParcelable parcelable = new VehiclePropValueParcelable(value);
try {
mService.setProperty(parcelable);
} catch (RemoteException e) {
handleRemoteException(e);
}
}
public void setIntProperty(int property, int value) {
VehiclePropValue v = VehiclePropValue.newBuilder().
setProp(property).
setValueType(VehicleValueType.VEHICLE_VALUE_TYPE_INT32).
addInt32Values(value).
build();
setProperty(v);
}
public void setIntVectorProperty(int property, int[] values) {
int len = values.length;
VehiclePropValue.Builder builder = VehiclePropValue.newBuilder().
setProp(property).
setValueType(VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2 + len - 2);
for (int v : values) {
builder.addInt32Values(v);
}
setProperty(builder.build());
}
public void setLongProperty(int property, long value) {
VehiclePropValue v = VehiclePropValue.newBuilder().
setProp(property).
setValueType(VehicleValueType.VEHICLE_VALUE_TYPE_INT64).
setInt64Value(value).
build();
setProperty(v);
}
public void setFloatProperty(int property, float value) {
VehiclePropValue v = VehiclePropValue.newBuilder().
setProp(property).
setValueType(VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT).
addFloatValues(value).
build();
setProperty(v);
}
public void setFloatVectorProperty(int property, float[] values) {
int len = values.length;
VehiclePropValue.Builder builder = VehiclePropValue.newBuilder().
setProp(property).
setValueType(VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC2 + len - 2);
for (float v : values) {
builder.addFloatValues(v);
}
setProperty(builder.build());
}
public VehiclePropValue getProperty(int property) {
try {
VehiclePropValueParcelable parcelable = mService.getProperty(property);
if (parcelable != null) {
return parcelable.value;
}
} catch (RemoteException e) {
handleRemoteException(e);
}
return null;
}
public int getIntProperty(int property) {
VehiclePropValue v = getProperty(property);
if (v == null) {
// if property is invalid, IllegalArgumentException should have been thrown
// from getProperty.
throw new IllegalStateException();
}
if (v.getValueType() != VehicleValueType.VEHICLE_VALUE_TYPE_INT32) {
throw new IllegalArgumentException();
}
if (v.getInt32ValuesCount() != 1) {
throw new IllegalStateException();
}
return v.getInt32Values(0);
}
public void getIntVectorProperty(int property, int[] values) {
VehiclePropValue v = getProperty(property);
if (v == null) {
// if property is invalid, IllegalArgumentException should have been thrown
// from getProperty.
throw new IllegalStateException();
}
switch (v.getValueType()) {
case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2:
case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC3:
case VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC4:
if (values.length !=
(v.getValueType() - VehicleValueType.VEHICLE_VALUE_TYPE_INT32_VEC2 + 2)) {
throw new IllegalArgumentException("wrong array length");
}
break;
default:
throw new IllegalArgumentException();
}
if (v.getInt32ValuesCount() != values.length) {
throw new IllegalStateException();
}
for (int i = 0; i < values.length; i++) {
values[i] = v.getInt32Values(i);
}
}
public float getFloatProperty(int property) {
VehiclePropValue v = getProperty(property);
if (v == null) {
throw new IllegalStateException();
}
if (v.getValueType() != VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT) {
throw new IllegalArgumentException();
}
if (v.getFloatValuesCount() != 1) {
throw new IllegalStateException();
}
return v.getFloatValues(0);
}
public void getFloatVectorProperty(int property, float[] values) {
VehiclePropValue v = getProperty(property);
if (v == null) {
// if property is invalid, IllegalArgumentException should have been thrown
// from getProperty.
throw new IllegalStateException();
}
switch (v.getValueType()) {
case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC2:
case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC3:
case VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC4:
if (values.length !=
(v.getValueType() - VehicleValueType.VEHICLE_VALUE_TYPE_FLOAT_VEC2 + 2)) {
throw new IllegalArgumentException("wrong array length");
}
break;
default:
throw new IllegalArgumentException();
}
if (v.getFloatValuesCount() != values.length) {
throw new IllegalStateException();
}
for (int i = 0; i < values.length; i++) {
values[i] = v.getFloatValues(i);
}
}
public long getLongProperty(int property) {
VehiclePropValue v = getProperty(property);
if (v == null) {
throw new IllegalStateException();
}
if (v.getValueType() != VehicleValueType.VEHICLE_VALUE_TYPE_INT64) {
throw new IllegalArgumentException();
}
return v.getInt64Value();
}
//TODO check UTF8 to java string conversion
public String getStringProperty(int property) {
VehiclePropValue v = getProperty(property);
if (v == null) {
throw new IllegalStateException();
}
if (v.getValueType() != VehicleValueType.VEHICLE_VALUE_TYPE_STRING) {
throw new IllegalArgumentException();
}
return v.getStringValue();
}
public void subscribe(int property, float sampleRate) {
try {
mService.subscribe(mVehicleNetworkListener, property, sampleRate);
} catch (RemoteException e) {
handleRemoteException(e);
}
}
public void unsubscribe(int property) {
try {
mService.unsubscribe(mVehicleNetworkListener, property);
} catch (RemoteException e) {
handleRemoteException(e);
}
}
private void handleRemoteException(RemoteException e) {
throw new RuntimeException("Vehicle network service not working ", e);
}
private void handleVehicleNetworkEvents(VehiclePropValues values) {
mEventHandler.notifyEvents(values);
}
private void doHandleVehicleNetworkEvents(VehiclePropValues values) {
mListener.onVehicleNetworkEvents(values);
}
private class EventHandler extends Handler {
private static final int MSG_EVENTS = 0;
private EventHandler(Looper looper) {
super(looper);
}
private void notifyEvents(VehiclePropValues values) {
Message msg = obtainMessage(MSG_EVENTS, values);
sendMessage(msg);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_EVENTS:
doHandleVehicleNetworkEvents((VehiclePropValues)msg.obj);
break;
default:
Log.w(TAG, "unown message:" + msg.what, new RuntimeException());
break;
}
}
}
private static class IVehicleNetworkListenerImpl extends IVehicleNetworkListener.Stub {
private final WeakReference<VehicleNetwork> mVehicleNetwork;
private IVehicleNetworkListenerImpl(VehicleNetwork vehicleNewotk) {
mVehicleNetwork = new WeakReference<VehicleNetwork>(vehicleNewotk);
}
@Override
public void onVehicleNetworkEvents(VehiclePropValuesParcelable values) {
VehicleNetwork vehicleNetwork = mVehicleNetwork.get();
if (vehicleNetwork != null) {
vehicleNetwork.handleVehicleNetworkEvents(values.values);
}
}
}
}