1 /*
2  * Copyright (C) 2019 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.vehiclectrl;
18 
19 import android.annotation.IdRes;
20 import android.annotation.Nullable;
21 import android.annotation.SuppressLint;
22 import android.car.VehicleAreaType;
23 import android.car.VehicleAreaWindow;
24 import android.car.VehiclePropertyIds;
25 import android.car.VehiclePropertyType;
26 import android.car.hardware.CarPropertyValue;
27 import android.car.hardware.property.CarPropertyManager;
28 import android.os.Bundle;
29 import android.util.Log;
30 import android.view.LayoutInflater;
31 import android.view.View;
32 import android.view.ViewGroup;
33 import android.widget.TextView;
34 
35 import androidx.fragment.app.Fragment;
36 import androidx.viewpager.widget.ViewPager;
37 
38 import com.google.android.car.kitchensink.KitchenSinkActivity;
39 import com.google.android.car.kitchensink.R;
40 import com.google.android.car.kitchensink.SimplePagerAdapter;
41 
42 import java.util.HashMap;
43 import java.util.Map;
44 
45 @SuppressLint("SetTextI18n")
46 public final class VehicleCtrlFragment extends Fragment {
47     private static final String TAG = VehicleCtrlFragment.class.getSimpleName();
48     // Same as defined in VehiclePropertyGroup.aidl.
49     private static final int VEHICLE_PROPERTY_GROUP_VENDOR = 0x20000000;
50 
51     public static final class CustomVehicleProperty {
52         public static final int PROTOCAN_TEST = (
53                 0x0ABC
54                 | VEHICLE_PROPERTY_GROUP_VENDOR
55                 | VehiclePropertyType.BOOLEAN
56                 | VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL);
57 
CustomVehicleProperty()58         private CustomVehicleProperty() {}
59     };
60 
61     private CarPropertyManager mPropMgr;
62     private final Map<Integer, TextView> mWindowPosWidgets = new HashMap<>();
63 
64     private final CarPropertyManager.CarPropertyEventCallback mPropCb =
65             new CarPropertyManager.CarPropertyEventCallback() {
66         @Override
67         public void onChangeEvent(CarPropertyValue value) {
68             onPropertyEvent(value);
69         }
70 
71         @Override
72         public void onErrorEvent(int propId, int zone) {}
73     };
74 
75     @Override
onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState)76     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
77             @Nullable Bundle savedInstanceState) {
78         View view = inflater.inflate(R.layout.vehicle_ctrl_fragment, container, false);
79 
80         ViewPager pager = view.findViewById(R.id.vehicle_ctrl_pager);
81         pager.setAdapter(new SimplePagerAdapter(pager));
82 
83         KitchenSinkActivity activity = (KitchenSinkActivity) getHost();
84         mPropMgr = activity.getPropertyManager();
85 
86         subscribeProps();
87 
88         initWindowBtns(view, VehicleAreaWindow.WINDOW_ROW_1_LEFT,
89                 R.id.winFLOpen, R.id.winFLClose, R.id.winFLPos);
90         initWindowBtns(view, VehicleAreaWindow.WINDOW_ROW_1_RIGHT,
91                 R.id.winFROpen, R.id.winFRClose, R.id.winFRPos);
92         initWindowBtns(view, VehicleAreaWindow.WINDOW_ROW_2_LEFT,
93                 R.id.winRLOpen, R.id.winRLClose, R.id.winRLPos);
94         initWindowBtns(view, VehicleAreaWindow.WINDOW_ROW_2_RIGHT,
95                 R.id.winRROpen, R.id.winRRClose, R.id.winRRPos);
96 
97         initTestBtn(view, R.id.protocan_test_on, true);
98         initTestBtn(view, R.id.protocan_test_off, false);
99 
100         return view;
101     }
102 
103     @Override
onDestroyView()104     public void onDestroyView() {
105         super.onDestroyView();
106         unsubscribeProps();
107     }
108 
subscribeProps()109     private void subscribeProps() {
110         mPropMgr.registerCallback(mPropCb, VehiclePropertyIds.WINDOW_POS, 10);
111     }
112 
unsubscribeProps()113     private void unsubscribeProps() {
114         mPropMgr.unregisterCallback(mPropCb);
115     }
116 
onPropertyEvent(CarPropertyValue prop)117     public void onPropertyEvent(CarPropertyValue prop) {
118         if (prop.getPropertyId() == VehiclePropertyIds.WINDOW_POS) {
119             Log.i(TAG, "Window pos: " + prop.getValue());
120             updateWindowPos(prop.getAreaId(), (int) prop.getValue());
121         }
122     }
123 
initWindowBtns(View view, int winId, @IdRes int openId, @IdRes int closeId, @IdRes int posId)124     private void initWindowBtns(View view, int winId, @IdRes int openId, @IdRes int closeId,
125             @IdRes int posId) {
126         // TODO(twasilczyk): fetch the actual min/max values
127         view.findViewById(openId).setOnClickListener(v -> moveWindow(winId, 1));
128         view.findViewById(closeId).setOnClickListener(v -> moveWindow(winId, -1));
129         mWindowPosWidgets.put(winId, view.findViewById(posId));
130     }
131 
moveWindow(int windowId, int speed)132     private void moveWindow(int windowId, int speed) {
133         Log.i(TAG, "Moving window " + windowId + " with speed " + speed);
134         mPropMgr.setIntProperty(VehiclePropertyIds.WINDOW_MOVE, windowId, speed);
135     }
136 
updateWindowPos(int windowId, int pos)137     private void updateWindowPos(int windowId, int pos) {
138         TextView view = mWindowPosWidgets.get(windowId);
139         view.post(() -> view.setText(pos + "%"));
140     }
141 
initTestBtn(View view, @IdRes int btnId, boolean on)142     private void initTestBtn(View view, @IdRes int btnId, boolean on) {
143         view.findViewById(btnId).setOnClickListener(v -> onTestBtnClicked(on));
144     }
145 
onTestBtnClicked(boolean on)146     private void onTestBtnClicked(boolean on) {
147         Log.i(TAG, "onTestBtnClicked " + on);
148         mPropMgr.setBooleanProperty(CustomVehicleProperty.PROTOCAN_TEST,
149                 VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL, on);
150     }
151 }
152