• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.car.testapi;
18 
19 import android.car.Car;
20 import android.car.IAppFocus;
21 import android.car.ICar;
22 import android.car.ICarBluetooth;
23 import android.car.cluster.IInstrumentClusterManagerService;
24 import android.car.cluster.renderer.IInstrumentClusterNavigation;
25 import android.car.content.pm.ICarPackageManager;
26 import android.car.diagnostic.ICarDiagnostic;
27 import android.car.drivingstate.ICarDrivingState;
28 import android.car.drivingstate.ICarUxRestrictionsManager;
29 import android.car.hardware.power.ICarPower;
30 import android.car.media.ICarAudio;
31 import android.car.settings.ICarConfigurationManager;
32 import android.car.storagemonitoring.ICarStorageMonitoring;
33 import android.car.vms.IVmsSubscriberService;
34 import android.content.Context;
35 import android.os.IBinder;
36 import android.os.RemoteException;
37 import android.util.Log;
38 
39 import org.mockito.Mock;
40 import org.mockito.MockitoAnnotations;
41 
42 /*
43     The idea behind this class is that we can fake-out interfaces between Car*Manager and
44     Car Service.  Effectively creating a fake version of Car Service that can run under Robolectric
45     environment (thus running on the desktop rather than on a real device).
46 
47     By default all interfaces are mocked out just to allow dummy implementation and avoid crashes.
48     This will allow production code to call into Car*Manager w/o crashes because managers will just
49     pass the call into mocked version of the interface. However, in many cases
50     developers would like to have more sophisticated test cases and ability to simulate vehicle as
51     they need.  In this case mocked version of particular service needs to be replaced with the fake
52     one which will have fake implementation to satisfy test needs and additional interface needs
53     to be exposed to the app developers such that they can simulate fake car behavior, this
54     interface has -Controller suffix and defined as inner interface in this class.
55  */
56 
57 /**
58  * Test API to get Car Managers backed by fake car service.
59  *
60  * <p>In order to use it in your tests you should create Car object by calling static method
61  * {@link FakeCar#createFakeCar(Context)}.  It will effectively create {@link FakeCar} object and
62  * you can get access to {@link Car} by calling {@link FakeCar#getCar()}.  Also, {@code FakeCar}
63  * provides additional testing API that will allow you to simulate vehicle's behavior as you need.
64  *
65  * <p>Here's an example of usage:
66  * <code>
67  *     FakeCar fakeCar = FakeCar.createFakeCar(appContext);
68  *     Car realCar = fakeCar.getCar();  // pass this instance to your DI framework or class to test
69  *
70  *     // Then you can obtain different controllers to modify behavior of your fake car.
71  *     PropertyController propertyController = fakeCar.getPropertyController();
72  *     propertyController.setProperties(listOfSupportedProperties)
73  * </code>
74  */
75 public class FakeCar {
76     private static final String TAG = FakeCar.class.getSimpleName();
77 
78     private final Car mCar;
79     private final FakeCarService mService;
80 
81     /** Creates an instance of {@link FakeCar} */
createFakeCar(Context context)82     public static FakeCar createFakeCar(Context context) {
83         FakeCarService service = new FakeCarService(context);
84         Car car = new Car(context, service, null);
85 
86         return new FakeCar(car, service);
87     }
88 
FakeCar(Car car, FakeCarService service)89     private FakeCar(Car car, FakeCarService service) {
90         mCar = car;
91         mService = service;
92     }
93 
94     /** Returns Car object which is backed by fake implementation. */
getCar()95     public Car getCar() {
96         return mCar;
97     }
98 
99     /** Returns test controller to modify car properties */
getCarPropertyController()100     public CarPropertyController getCarPropertyController() {
101         return mService.mCarProperty;
102     }
103 
104     /** Returns test controller to change behavior of {@link android.car.CarProjectionManager} */
getCarProjectionController()105     public CarProjectionController getCarProjectionController() {
106         return mService.mCarProjection;
107     }
108 
109     private static class FakeCarService extends ICar.Stub {
110         @Mock ICarAudio.Stub mCarAudio;
111         @Mock IAppFocus.Stub mAppFocus;
112         @Mock ICarPackageManager.Stub mCarPackageManager;
113         @Mock ICarDiagnostic.Stub mCarDiagnostic;
114         @Mock ICarPower.Stub mCarPower;
115         @Mock IInstrumentClusterNavigation.Stub mClusterNavigation;
116         @Mock IInstrumentClusterManagerService.Stub mClusterService;
117         @Mock IVmsSubscriberService.Stub mVmsSubscriberService;
118         @Mock ICarBluetooth.Stub mCarBluetooth;
119         @Mock ICarStorageMonitoring.Stub mCarStorageMonitoring;
120         @Mock ICarDrivingState.Stub mCarDrivingState;
121         @Mock ICarUxRestrictionsManager.Stub mCarUxRestriction;
122         @Mock ICarConfigurationManager.Stub mCarConfigurationManager;
123 
124         private final FakeCarPropertyService mCarProperty;
125         private final FakeCarProjectionService mCarProjection;
126 
FakeCarService(Context context)127         FakeCarService(Context context) {
128             MockitoAnnotations.initMocks(this);
129             mCarProperty = new FakeCarPropertyService();
130             mCarProjection = new FakeCarProjectionService(context);
131         }
132 
133         @Override
setCarServiceHelper(IBinder helper)134         public void setCarServiceHelper(IBinder helper) throws RemoteException {
135             // Nothing to do yet.
136         }
137 
138         @Override
setUserLockStatus(int userHandle, int unlocked)139         public void setUserLockStatus(int userHandle, int unlocked) throws RemoteException {
140             // Nothing to do yet.
141         }
142 
143         @Override
onSwitchUser(int userHandle)144         public void onSwitchUser(int userHandle) throws RemoteException {
145             // Nothing to do yet.
146         }
147 
148         @Override
getCarService(String serviceName)149         public IBinder getCarService(String serviceName) throws RemoteException {
150             switch (serviceName) {
151                 case Car.AUDIO_SERVICE:
152                     return mCarAudio;
153                 case Car.APP_FOCUS_SERVICE:
154                     return mAppFocus;
155                 case Car.PACKAGE_SERVICE:
156                     return mCarPackageManager;
157                 case Car.DIAGNOSTIC_SERVICE:
158                     return mCarDiagnostic;
159                 case Car.POWER_SERVICE:
160                     return mCarPower;
161                 case Car.CABIN_SERVICE:
162                 case Car.HVAC_SERVICE:
163                 case Car.INFO_SERVICE:
164                 case Car.PROPERTY_SERVICE:
165                 case Car.SENSOR_SERVICE:
166                 case Car.VENDOR_EXTENSION_SERVICE:
167                     return mCarProperty;
168                 case Car.CAR_NAVIGATION_SERVICE:
169                     return mClusterNavigation;
170                 case Car.CAR_INSTRUMENT_CLUSTER_SERVICE:
171                     return mClusterService;
172                 case Car.PROJECTION_SERVICE:
173                     return mCarProjection;
174                 case Car.VMS_SUBSCRIBER_SERVICE:
175                     return mVmsSubscriberService;
176                 case Car.BLUETOOTH_SERVICE:
177                     return mCarBluetooth;
178                 case Car.STORAGE_MONITORING_SERVICE:
179                     return mCarStorageMonitoring;
180                 case Car.CAR_DRIVING_STATE_SERVICE:
181                     return mCarDrivingState;
182                 case Car.CAR_UX_RESTRICTION_SERVICE:
183                     return mCarUxRestriction;
184                 case Car.CAR_CONFIGURATION_SERVICE:
185                     return mCarConfigurationManager;
186                 default:
187                     Log.w(TAG, "getCarService for unknown service:" + serviceName);
188                     return null;
189             }
190         }
191 
192         @Override
getCarConnectionType()193         public int getCarConnectionType() throws RemoteException {
194             return Car.CONNECTION_TYPE_EMBEDDED;
195         }
196     }
197 
198 }
199