diff options
author | Steve Paik <spaik@google.com> | 2018-04-27 13:28:31 -0700 |
---|---|---|
committer | Steve Paik <spaik@google.com> | 2018-06-02 03:48:39 +0000 |
commit | 4d257023389c23b8836f10cda1bfa1ea136f56c9 (patch) | |
tree | d9b0d6e859dc1db4b0f7acd01c6fb28d85c42026 /tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink | |
parent | d3cb98e76080151bdfb5085b8971b5070f11d28b (diff) | |
download | Car-4d257023389c23b8836f10cda1bfa1ea136f56c9.tar.gz |
Create CarPropertyService and CarPropertyManager
CarPropertyService replaces Cabin, Hvac, Info, Sensor,
and VendorExtension services.
Bug: 78782959
Bug: 36649684
Bug: 68056035
Test: runtest -x packages/services/Car/tests/android_car_api_test
runtest -x packages/services/Car/tests/carservice_unit_test
Change-Id: I69756654473fe66ef95e9e2cd4f3c1045e3ac938
Merged-In: Ic0a94805f83cc0222fb2bcf9674b6031bc050986
(cherry picked from commit fc0257133967edcb217e07e9ab942690eeaae3de)
(cherry picked from commit 0265d8348716b2971f76e697f410f4cf7128371c)
Diffstat (limited to 'tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink')
4 files changed, 419 insertions, 0 deletions
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java index aa6202a804..0a00c66015 100644 --- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java +++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/KitchenSinkActivity.java @@ -19,6 +19,7 @@ package com.google.android.car.kitchensink; import android.car.hardware.hvac.CarHvacManager; import android.car.hardware.power.CarPowerManager; +import android.car.hardware.property.CarPropertyManager; import android.content.Intent; import android.content.pm.PackageManager; import android.os.Bundle; @@ -50,6 +51,7 @@ import com.google.android.car.kitchensink.job.JobSchedulerFragment; import com.google.android.car.kitchensink.notification.NotificationFragment; import com.google.android.car.kitchensink.orientation.OrientationTestFragment; import com.google.android.car.kitchensink.power.PowerTestFragment; +import com.google.android.car.kitchensink.property.PropertyTestFragment; import com.google.android.car.kitchensink.sensor.SensorsTestFragment; import com.google.android.car.kitchensink.setting.CarServiceSettingsActivity; import com.google.android.car.kitchensink.storagelifetime.StorageLifetimeFragment; @@ -153,6 +155,7 @@ public class KitchenSinkActivity extends CarDrawerActivity { add("notification", NotificationFragment.class); add("orientation test", OrientationTestFragment.class); add("power test", PowerTestFragment.class); + add("property test", PropertyTestFragment.class); add("sensors", SensorsTestFragment.class); add("storage lifetime", StorageLifetimeFragment.class); add("touch test", TouchTestFragment.class); @@ -177,6 +180,7 @@ public class KitchenSinkActivity extends CarDrawerActivity { private Car mCarApi; private CarHvacManager mHvacManager; private CarPowerManager mPowerManager; + private CarPropertyManager mPropertyManager; private CarSensorManager mCarSensorManager; private CarAppFocusManager mCarAppFocusManager; @@ -196,6 +200,10 @@ public class KitchenSinkActivity extends CarDrawerActivity { return mPowerManager; } + public CarPropertyManager getPropertyManager() { + return mPropertyManager; + } + @Override protected CarDrawerAdapter getRootAdapter() { return new DrawerAdapter(); @@ -271,6 +279,8 @@ public class KitchenSinkActivity extends CarDrawerActivity { mHvacManager = (CarHvacManager) mCarApi.getCarManager(android.car.Car.HVAC_SERVICE); mPowerManager = (CarPowerManager) mCarApi.getCarManager( android.car.Car.POWER_SERVICE); + mPropertyManager = (CarPropertyManager) mCarApi.getCarManager( + android.car.Car.PROPERTY_SERVICE); mCarSensorManager = (CarSensorManager) mCarApi.getCarManager(Car.SENSOR_SERVICE); mCarSensorManager.addListener(mListener, CarSensorManager.SENSOR_TYPE_DRIVING_STATUS, diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyInfo.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyInfo.java new file mode 100644 index 0000000000..0f0b5d4614 --- /dev/null +++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyInfo.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 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.google.android.car.kitchensink.property; + +import android.car.hardware.CarPropertyConfig; +import android.hardware.automotive.vehicle.V2_0.VehicleProperty; + +class PropertyInfo implements Comparable<PropertyInfo> { + public final CarPropertyConfig mConfig; + public final String mName; + public final int mPropId; + + PropertyInfo(CarPropertyConfig config) { + mConfig = config; + mPropId = config.getPropertyId(); + mName = VehicleProperty.toString(mPropId); + } + + @Override + public String toString() { + return mName; + } + + @Override + public boolean equals(Object other) { + if (other instanceof PropertyInfo) { + return ((PropertyInfo) other).mPropId == mPropId; + } + return false; + } + + @Override + public int hashCode() { + return mPropId; + } + + @Override + public int compareTo(PropertyInfo propertyInfo) { + return mName.compareTo(propertyInfo.mName); + } +} diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyListAdapter.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyListAdapter.java new file mode 100644 index 0000000000..06ea4eef4c --- /dev/null +++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyListAdapter.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2018 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.google.android.car.kitchensink.property; + +import static java.lang.Integer.toHexString; + +import android.car.hardware.CarPropertyConfig; +import android.car.hardware.CarPropertyValue; +import android.car.hardware.property.CarPropertyManager; +import android.content.Context; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.BaseAdapter; +import android.widget.ListAdapter; +import android.widget.ScrollView; +import android.widget.TextView; +import android.widget.ToggleButton; + +import com.google.android.car.kitchensink.R; + +import java.util.List; + +class PropertyListAdapter extends BaseAdapter implements ListAdapter { + private static final int DEFAULT_RATE = 1; + private static final String TAG = "PropertyListAdapter"; + private final Context mContext; + private final PropertyListEventListener mListener; + private final CarPropertyManager mMgr; + private final List<PropertyInfo> mPropInfo; + private final TextView mTvEventLog; + + PropertyListAdapter(List<PropertyInfo> propInfo, CarPropertyManager mgr, TextView eventLog, + ScrollView svEventLog, Context context) { + mContext = context; + mListener = new PropertyListEventListener(eventLog, svEventLog); + mMgr = mgr; + mPropInfo = propInfo; + mTvEventLog = eventLog; + } + + @Override + public int getCount() { + return mPropInfo.size(); + } + + @Override + public Object getItem(int pos) { + return mPropInfo.get(pos); + } + + @Override + public long getItemId(int pos) { + return mPropInfo.get(pos).mPropId; + } + + @Override + public View getView(final int position, View convertView, ViewGroup parent) { + View view = convertView; + if (view == null) { + LayoutInflater inflater = (LayoutInflater) mContext.getSystemService( + Context.LAYOUT_INFLATER_SERVICE); + view = inflater.inflate(R.layout.property_list_item, null); + } + + //Handle TextView and display string from your list + TextView listItemText = (TextView) view.findViewById(R.id.tvPropertyName); + listItemText.setText(mPropInfo.get(position).toString()); + + //Handle buttons and add onClickListeners + ToggleButton btn = (ToggleButton) view.findViewById(R.id.tbRegisterPropertyBtn); + + btn.setOnClickListener(new View.OnClickListener(){ + @Override + public void onClick(View v) { + CarPropertyConfig c = mPropInfo.get(position).mConfig; + int propId = c.getPropertyId(); + try { + if (btn.isChecked()) { + mMgr.registerListener(mListener, propId, DEFAULT_RATE); + } else { + mMgr.unregisterListener(mListener, propId); + } + } catch (Exception e) { + Log.e(TAG, "Unhandled exception: ", e); + } + } + }); + return view; + } + + + private static class PropertyListEventListener implements + CarPropertyManager.CarPropertyEventListener { + private int mNumEvents; + private ScrollView mScrollView; + private TextView mTvLogEvent; + + PropertyListEventListener(TextView logEvent, ScrollView scrollView) { + mScrollView = scrollView; + mTvLogEvent = logEvent; + } + + @Override + public void onChangeEvent(CarPropertyValue value) { + mNumEvents++; + mTvLogEvent.append("Event " + mNumEvents + ":" + + " time=" + value.getTimestamp() + + " propId=0x" + toHexString(value.getPropertyId()) + + " areaId=0x" + toHexString(value.getAreaId()) + + " status=" + value.getStatus() + + " value=" + value.getValue() + + "\n"); + scrollToBottom(); + } + + @Override + public void onErrorEvent(int propId, int areaId) { + mTvLogEvent.append("Received error event propId=0x" + toHexString(propId) + + ", areaId=0x" + toHexString(areaId)); + scrollToBottom(); + } + + private void scrollToBottom() { + mScrollView.post(new Runnable() { + public void run() { + mScrollView.fullScroll(View.FOCUS_DOWN); + //mScrollView.smoothScrollTo(0, mTextStatus.getBottom()); + } + }); + } + + } +} diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyTestFragment.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyTestFragment.java new file mode 100644 index 0000000000..fc6621a7ca --- /dev/null +++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/property/PropertyTestFragment.java @@ -0,0 +1,205 @@ +/* + * Copyright (C) 2018 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.google.android.car.kitchensink.property; + +import static java.lang.Integer.toHexString; + +import android.annotation.Nullable; +import android.car.hardware.CarPropertyValue; +import android.car.hardware.property.CarPropertyManager; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.hardware.automotive.vehicle.V2_0.VehicleProperty; +import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ListView; +import android.widget.ScrollView; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.car.kitchensink.KitchenSinkActivity; +import com.google.android.car.kitchensink.R; + +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +public class PropertyTestFragment extends Fragment implements OnItemSelectedListener{ + private static final String TAG = "PropertyTestFragment"; + + private KitchenSinkActivity mActivity; + private CarPropertyManager mMgr; + private List<PropertyInfo> mPropInfo = null; + private Spinner mAreaId; + private TextView mEventLog; + private TextView mGetValue; + private ListView mListView; + private Spinner mPropertyId; + private ScrollView mScrollView; + private EditText mSetValue; + + private final OnClickListener mNopOnClickListener = new OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { } + }; + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.property, container, false); + mActivity = (KitchenSinkActivity) getHost(); + mMgr = mActivity.getPropertyManager(); + + // Get resource IDs + mAreaId = view.findViewById(R.id.sAreaId); + mEventLog = view.findViewById(R.id.tvEventLog); + mGetValue = view.findViewById(R.id.tvGetPropertyValue); + mListView = view.findViewById(R.id.lvPropertyList); + mPropertyId = view.findViewById(R.id.sPropertyId); + mScrollView = view.findViewById(R.id.svEventLog); + mSetValue = view.findViewById(R.id.etSetPropertyValue); + + populateConfigList(); + mListView.setAdapter(new PropertyListAdapter(mPropInfo, mMgr, mEventLog, mScrollView, + mActivity)); + + // Configure dropdown menu for propertyId spinner + ArrayAdapter<PropertyInfo> adapter = + new ArrayAdapter<PropertyInfo>(mActivity, android.R.layout.simple_spinner_item, + mPropInfo); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mPropertyId.setAdapter(adapter); + mPropertyId.setOnItemSelectedListener(this); + + + + // Configure listeners for buttons + Button b = view.findViewById(R.id.bGetProperty); + b.setOnClickListener(v -> { + try { + PropertyInfo info = (PropertyInfo) mPropertyId.getSelectedItem(); + int propId = info.mConfig.getPropertyId(); + int areaId = Integer.decode(mAreaId.getSelectedItem().toString()); + CarPropertyValue value = mMgr.getProperty(propId, areaId); + if (propId == VehicleProperty.WHEEL_TICK) { + Object[] ticks = (Object[]) value.getValue(); + mGetValue.setText("Timestamp=" + value.getTimestamp() + + "\nstatus=" + value.getStatus() + + "\n[0]=" + (Long) ticks[0] + + "\n[1]=" + (Long) ticks[1] + " [2]=" + (Long) ticks[2] + + "\n[3]=" + (Long) ticks[3] + " [4]=" + (Long) ticks[4]); + } else { + mGetValue.setText("Timestamp=" + value.getTimestamp() + + "\nstatus=" + value.getStatus() + + "\nvalue=" + value.getValue()); + } + } catch (Exception e) { + Log.e(TAG, "Failed to get property", e); + } + }); + + b = view.findViewById(R.id.bSetProperty); + b.setOnClickListener(v -> { + try { + PropertyInfo info = (PropertyInfo) mPropertyId.getSelectedItem(); + int propId = info.mConfig.getPropertyId(); + int areaId = Integer.decode(mAreaId.getSelectedItem().toString()); + String valueString = mSetValue.getText().toString(); + + switch (propId & VehiclePropertyType.MASK) { + case VehiclePropertyType.BOOLEAN: + Boolean boolVal = Boolean.parseBoolean(valueString); + mMgr.setBooleanProperty(propId, areaId, boolVal); + break; + case VehiclePropertyType.FLOAT: + Float floatVal = Float.parseFloat(valueString); + mMgr.setFloatProperty(propId, areaId, floatVal); + break; + case VehiclePropertyType.INT32: + Integer intVal = Integer.parseInt(valueString); + mMgr.setIntProperty(propId, areaId, intVal); + break; + default: + Toast.makeText(mActivity, "PropertyType=0x" + toHexString(propId + & VehiclePropertyType.MASK) + " is not handled!", + Toast.LENGTH_LONG).show(); + break; + } + } catch (Exception e) { + Log.e(TAG, "Failed to set HVAC boolean property", e); + } + }); + + b = view.findViewById(R.id.bClearLog); + b.setOnClickListener(v -> { + mEventLog.setText(""); + }); + + return view; + } + + private void populateConfigList() { + try { + mPropInfo = mMgr.getPropertyList() + .stream() + .map(PropertyInfo::new) + .sorted() + .collect(Collectors.toList()); + } catch (Exception e) { + Log.e(TAG, "Unhandled exception in populateConfigList: ", e); + } + } + + // Spinner callbacks + public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { + // An item was selected. You can retrieve the selected item using + PropertyInfo info = (PropertyInfo) parent.getItemAtPosition(pos); + int[] areaIds = info.mConfig.getAreaIds(); + List<String> areaString = new LinkedList<String>(); + if (areaIds.length == 0) { + areaString.add("0x0"); + } else { + for (int areaId : areaIds) { + areaString.add("0x" + toHexString(areaId)); + } + } + + // Configure dropdown menu for propertyId spinner + ArrayAdapter<String> adapter = + new ArrayAdapter<String>(mActivity, android.R.layout.simple_spinner_item, + areaString); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mAreaId.setAdapter(adapter); + } + + public void onNothingSelected(AdapterView<?> parent) { + // Another interface callback + } +} |