• 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.annotation.Nullable;
20 import android.car.Car;
21 import android.car.ICar;
22 import android.car.ICarResultReceiver;
23 import android.car.cluster.IInstrumentClusterManagerService;
24 import android.car.content.pm.ICarPackageManager;
25 import android.car.diagnostic.ICarDiagnostic;
26 import android.car.drivingstate.ICarDrivingState;
27 import android.car.hardware.power.ICarPower;
28 import android.car.storagemonitoring.ICarStorageMonitoring;
29 import android.content.Context;
30 import android.os.IBinder;
31 import android.os.RemoteException;
32 import android.util.Log;
33 
34 import com.android.car.internal.ICarServiceHelper;
35 
36 import org.mockito.Mock;
37 import org.mockito.MockitoAnnotations;
38 
39 import java.util.Collections;
40 import java.util.List;
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 placeholder 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 final 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     /**
110      * Returns the test controller to change the behavior of the underlying
111      * {@link android.car.CarAppFocusManager}
112      */
getAppFocusController()113     public CarAppFocusController getAppFocusController() {
114         return mService.mAppFocus;
115     }
116 
117     /**
118      * Returns the test controller to change the behavior of as well as query the underlying {@link
119      * android.car.navigation.CarNavigationStatusManager}.
120      */
getCarNavigationStatusController()121     public CarNavigationStatusController getCarNavigationStatusController() {
122         return mService.mInstrumentClusterNavigation;
123     }
124 
125     /**
126      * Returns a test controller that can modify and query the underlying service for the {@link
127      * android.car.drivingstate.CarUxRestrictionsManager}.
128      */
getCarUxRestrictionController()129     public CarUxRestrictionsController getCarUxRestrictionController() {
130         return mService.mCarUxRestrictionService;
131     }
132 
133     private static class FakeCarService extends ICar.Stub {
134         @Mock ICarPackageManager.Stub mCarPackageManager;
135         @Mock ICarDiagnostic.Stub mCarDiagnostic;
136         @Mock ICarPower.Stub mCarPower;
137         @Mock IInstrumentClusterManagerService.Stub mClusterService;
138         @Mock ICarStorageMonitoring.Stub mCarStorageMonitoring;
139         @Mock ICarDrivingState.Stub mCarDrivingState;
140 
141         private final FakeCarAudioService mCarAudio;
142         private final FakeAppFocusService mAppFocus;
143         private final FakeCarPropertyService mCarProperty;
144         private final FakeCarProjectionService mCarProjection;
145         private final FakeInstrumentClusterNavigation mInstrumentClusterNavigation;
146         private final FakeCarUxRestrictionsService mCarUxRestrictionService;
147 
FakeCarService(Context context)148         FakeCarService(Context context) {
149             MockitoAnnotations.initMocks(this);
150             mCarAudio = new FakeCarAudioService();
151             mAppFocus = new FakeAppFocusService(context);
152             mCarProperty = new FakeCarPropertyService();
153             mCarProjection = new FakeCarProjectionService(context);
154             mInstrumentClusterNavigation = new FakeInstrumentClusterNavigation();
155             mCarUxRestrictionService = new FakeCarUxRestrictionsService();
156         }
157 
158         @Override
setSystemServerConnections(ICarServiceHelper helper, ICarResultReceiver receiver)159         public void setSystemServerConnections(ICarServiceHelper helper,
160                 ICarResultReceiver receiver)
161                 throws RemoteException {
162             // Nothing to do yet.
163         }
164 
165         @Override
166         @Nullable
getCarService(String serviceName)167         public IBinder getCarService(String serviceName) throws RemoteException {
168             switch (serviceName) {
169                 case Car.AUDIO_SERVICE:
170                     return mCarAudio;
171                 case Car.APP_FOCUS_SERVICE:
172                     return mAppFocus;
173                 case Car.PACKAGE_SERVICE:
174                     return mCarPackageManager;
175                 case Car.DIAGNOSTIC_SERVICE:
176                     return mCarDiagnostic;
177                 case Car.POWER_SERVICE:
178                     return mCarPower;
179                 case Car.CABIN_SERVICE:
180                 case Car.HVAC_SERVICE:
181                 case Car.INFO_SERVICE:
182                 case Car.PROPERTY_SERVICE:
183                 case Car.SENSOR_SERVICE:
184                 case Car.VENDOR_EXTENSION_SERVICE:
185                     return mCarProperty;
186                 case Car.CAR_NAVIGATION_SERVICE:
187                     return mInstrumentClusterNavigation;
188                 case Car.CAR_INSTRUMENT_CLUSTER_SERVICE:
189                     return mClusterService;
190                 case Car.PROJECTION_SERVICE:
191                     return mCarProjection;
192                 case Car.STORAGE_MONITORING_SERVICE:
193                     return mCarStorageMonitoring;
194                 case Car.CAR_DRIVING_STATE_SERVICE:
195                     return mCarDrivingState;
196                 case Car.CAR_UX_RESTRICTION_SERVICE:
197                     return mCarUxRestrictionService;
198                 default:
199                     Log.w(TAG, "getCarService for unknown service:" + serviceName);
200                     return null;
201             }
202         }
203 
204         @Override
getCarConnectionType()205         public int getCarConnectionType() throws RemoteException {
206             return Car.CONNECTION_TYPE_EMBEDDED;
207         }
208 
209         @Override
isFeatureEnabled(String featureName)210         public boolean isFeatureEnabled(String featureName) {
211             return false;
212         }
213 
214         @Override
enableFeature(String featureName)215         public int enableFeature(String featureName) {
216             return Car.FEATURE_REQUEST_SUCCESS;
217         }
218 
219         @Override
disableFeature(String featureName)220         public int disableFeature(String featureName) {
221             return Car.FEATURE_REQUEST_SUCCESS;
222         }
223 
224         @Override
getAllEnabledFeatures()225         public List<String> getAllEnabledFeatures() {
226             return Collections.emptyList();
227         }
228 
229         @Override
getAllPendingDisabledFeatures()230         public List<String> getAllPendingDisabledFeatures() {
231             return Collections.emptyList();
232         }
233 
234         @Override
getAllPendingEnabledFeatures()235         public List<String> getAllPendingEnabledFeatures() {
236             return Collections.emptyList();
237         }
238 
239         @Override
getCarManagerClassForFeature(String featureName)240         public String getCarManagerClassForFeature(String featureName) {
241             return null;
242         }
243     }
244 
245 }
246