1 /* 2 * Copyright (C) 2018 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.property; 18 19 import static java.lang.Integer.toHexString; 20 21 import android.annotation.Nullable; 22 import android.car.hardware.CarPropertyValue; 23 import android.car.hardware.property.CarPropertyManager; 24 import android.content.DialogInterface; 25 import android.content.DialogInterface.OnClickListener; 26 import android.hardware.automotive.vehicle.V2_0.VehicleProperty; 27 import android.hardware.automotive.vehicle.V2_0.VehiclePropertyType; 28 import android.os.Bundle; 29 import android.os.Handler; 30 import android.util.Log; 31 import android.view.LayoutInflater; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.widget.AdapterView; 35 import android.widget.AdapterView.OnItemSelectedListener; 36 import android.widget.ArrayAdapter; 37 import android.widget.Button; 38 import android.widget.EditText; 39 import android.widget.ListView; 40 import android.widget.ScrollView; 41 import android.widget.Spinner; 42 import android.widget.TextView; 43 import android.widget.Toast; 44 45 import androidx.fragment.app.Fragment; 46 47 import com.google.android.car.kitchensink.KitchenSinkActivity; 48 import com.google.android.car.kitchensink.R; 49 50 import java.util.LinkedList; 51 import java.util.List; 52 import java.util.stream.Collectors; 53 54 public class PropertyTestFragment extends Fragment implements OnItemSelectedListener { 55 private static final String TAG = "PropertyTestFragment"; 56 57 private KitchenSinkActivity mActivity; 58 private CarPropertyManager mMgr; 59 private List<PropertyInfo> mPropInfo = null; 60 private Spinner mAreaId; 61 private TextView mEventLog; 62 private TextView mGetValue; 63 private ListView mListView; 64 private Spinner mPropertyId; 65 private ScrollView mScrollView; 66 private EditText mSetValue; 67 68 private final OnClickListener mNopOnClickListener = new OnClickListener() { 69 @Override 70 public void onClick(DialogInterface dialog, int which) { 71 } 72 }; 73 74 @Nullable 75 @Override onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)76 public View onCreateView(LayoutInflater inflater, 77 @Nullable ViewGroup container, 78 @Nullable Bundle savedInstanceState) { 79 View view = inflater.inflate(R.layout.property, container, false); 80 // Get resource IDs 81 mAreaId = view.findViewById(R.id.sAreaId); 82 mEventLog = view.findViewById(R.id.tvEventLog); 83 mGetValue = view.findViewById(R.id.tvGetPropertyValue); 84 mListView = view.findViewById(R.id.lvPropertyList); 85 mPropertyId = view.findViewById(R.id.sPropertyId); 86 mScrollView = view.findViewById(R.id.svEventLog); 87 mSetValue = view.findViewById(R.id.etSetPropertyValue); 88 mActivity = (KitchenSinkActivity) getActivity(); 89 90 final Runnable r = () -> { 91 mMgr = mActivity.getPropertyManager(); 92 populateConfigList(); 93 mListView.setAdapter(new PropertyListAdapter(mPropInfo, mMgr, mEventLog, mScrollView, 94 mActivity)); 95 96 // Configure dropdown menu for propertyId spinner 97 ArrayAdapter<PropertyInfo> adapter = 98 new ArrayAdapter<PropertyInfo>(mActivity, android.R.layout.simple_spinner_item, 99 mPropInfo); 100 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 101 mPropertyId.setAdapter(adapter); 102 mPropertyId.setOnItemSelectedListener(this); 103 }; 104 mActivity.requestRefreshManager(r, new Handler(getContext().getMainLooper())); 105 106 // Configure listeners for buttons 107 Button b = view.findViewById(R.id.bGetProperty); 108 b.setOnClickListener(v -> { 109 try { 110 PropertyInfo info = (PropertyInfo) mPropertyId.getSelectedItem(); 111 int propId = info.mConfig.getPropertyId(); 112 int areaId = Integer.decode(mAreaId.getSelectedItem().toString()); 113 CarPropertyValue value = mMgr.getProperty(propId, areaId); 114 if (propId == VehicleProperty.WHEEL_TICK) { 115 Object[] ticks = (Object[]) value.getValue(); 116 mGetValue.setText("Timestamp=" + value.getTimestamp() 117 + "\nstatus=" + value.getStatus() 118 + "\n[0]=" + (Long) ticks[0] 119 + "\n[1]=" + (Long) ticks[1] + " [2]=" + (Long) ticks[2] 120 + "\n[3]=" + (Long) ticks[3] + " [4]=" + (Long) ticks[4]); 121 } else { 122 mGetValue.setText("Timestamp=" + value.getTimestamp() 123 + "\nstatus=" + value.getStatus() 124 + "\nvalue=" + value.getValue() 125 + "\nread=" + mMgr.getReadPermission(propId) 126 + "\nwrite=" + mMgr.getWritePermission(propId)); 127 } 128 } catch (Exception e) { 129 Log.e(TAG, "Failed to get VHAL property", e); 130 Toast.makeText(mActivity, "Failed to get VHAL property: " + e.getMessage(), 131 Toast.LENGTH_SHORT).show(); 132 } 133 }); 134 135 b = view.findViewById(R.id.bSetProperty); 136 b.setOnClickListener(v -> { 137 try { 138 PropertyInfo info = (PropertyInfo) mPropertyId.getSelectedItem(); 139 int propId = info.mConfig.getPropertyId(); 140 int areaId = Integer.decode(mAreaId.getSelectedItem().toString()); 141 String valueString = mSetValue.getText().toString(); 142 143 switch (propId & VehiclePropertyType.MASK) { 144 case VehiclePropertyType.BOOLEAN: 145 Boolean boolVal = Boolean.parseBoolean(valueString); 146 mMgr.setBooleanProperty(propId, areaId, boolVal); 147 break; 148 case VehiclePropertyType.FLOAT: 149 Float floatVal = Float.parseFloat(valueString); 150 mMgr.setFloatProperty(propId, areaId, floatVal); 151 break; 152 case VehiclePropertyType.INT32: 153 Integer intVal = Integer.parseInt(valueString); 154 mMgr.setIntProperty(propId, areaId, intVal); 155 break; 156 default: 157 Toast.makeText(mActivity, "PropertyType=0x" + toHexString(propId 158 & VehiclePropertyType.MASK) + " is not handled!", 159 Toast.LENGTH_LONG).show(); 160 break; 161 } 162 } catch (Exception e) { 163 Log.e(TAG, "Failed to set VHAL property", e); 164 Toast.makeText(mActivity, "Failed to set VHAL property: " + e.getMessage(), 165 Toast.LENGTH_SHORT).show(); 166 } 167 }); 168 169 b = view.findViewById(R.id.bClearLog); 170 b.setOnClickListener(v -> { 171 mEventLog.setText(""); 172 }); 173 174 return view; 175 } 176 populateConfigList()177 private void populateConfigList() { 178 try { 179 mPropInfo = mMgr.getPropertyList() 180 .stream() 181 .map(PropertyInfo::new) 182 .sorted() 183 .collect(Collectors.toList()); 184 } catch (Exception e) { 185 Log.e(TAG, "Unhandled exception in populateConfigList: ", e); 186 } 187 } 188 189 // Spinner callbacks onItemSelected(AdapterView<?> parent, View view, int pos, long id)190 public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { 191 PropertyInfo info = (PropertyInfo) parent.getItemAtPosition(pos); 192 int[] areaIds = info.mConfig.getAreaIds(); 193 List<String> areaString = new LinkedList<String>(); 194 if (areaIds.length == 0) { 195 areaString.add("0x0"); 196 } else { 197 for (int areaId : areaIds) { 198 areaString.add("0x" + toHexString(areaId)); 199 } 200 } 201 202 // Configure dropdown menu for propertyId spinner 203 ArrayAdapter<String> adapter = new ArrayAdapter<String>(mActivity, 204 android.R.layout.simple_spinner_item, areaString); 205 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 206 mAreaId.setAdapter(adapter); 207 } 208 onNothingSelected(AdapterView<?> parent)209 public void onNothingSelected(AdapterView<?> parent) { 210 // Another interface callback 211 } 212 } 213