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         // An item was selected. You can retrieve the selected item using
192         PropertyInfo info = (PropertyInfo) parent.getItemAtPosition(pos);
193         int[] areaIds = info.mConfig.getAreaIds();
194         List<String> areaString = new LinkedList<String>();
195         if (areaIds.length == 0) {
196             areaString.add("0x0");
197         } else {
198             for (int areaId : areaIds) {
199                 areaString.add("0x" + toHexString(areaId));
200             }
201         }
202 
203         // Configure dropdown menu for propertyId spinner
204         ArrayAdapter<String> adapter = new ArrayAdapter<String>(mActivity,
205                 android.R.layout.simple_spinner_item, areaString);
206         adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
207         mAreaId.setAdapter(adapter);
208     }
209 
onNothingSelected(AdapterView<?> parent)210     public void onNothingSelected(AdapterView<?> parent) {
211         // Another interface callback
212     }
213 }
214