• 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 com.android.car;
18 
19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
20 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doThrow;
21 
22 import static org.junit.Assert.fail;
23 import static org.mockito.ArgumentMatchers.any;
24 import static org.mockito.ArgumentMatchers.anyInt;
25 import static org.mockito.ArgumentMatchers.anyString;
26 import static org.mockito.ArgumentMatchers.eq;
27 import static org.mockito.Mockito.doReturn;
28 import static org.mockito.Mockito.spy;
29 
30 import android.car.Car;
31 import android.car.ICarResultReceiver;
32 import android.car.test.mocks.AbstractExtendedMockitoTestCase;
33 import android.content.Context;
34 import android.content.res.Resources;
35 import android.os.Bundle;
36 import android.os.HandlerThread;
37 import android.os.Looper;
38 import android.os.UserHandle;
39 import android.os.UserManager;
40 import android.util.Log;
41 
42 import androidx.test.platform.app.InstrumentationRegistry;
43 
44 import com.android.car.garagemode.GarageModeService;
45 import com.android.car.internal.ICarServiceHelper;
46 import com.android.car.os.CarPerformanceService;
47 import com.android.car.remoteaccess.CarRemoteAccessService;
48 import com.android.car.systeminterface.ActivityManagerInterface;
49 import com.android.car.systeminterface.DisplayInterface;
50 import com.android.car.systeminterface.IOInterface;
51 import com.android.car.systeminterface.StorageMonitoringInterface;
52 import com.android.car.systeminterface.SystemInterface;
53 import com.android.car.systeminterface.SystemInterface.Builder;
54 import com.android.car.systeminterface.SystemStateInterface;
55 import com.android.car.systeminterface.TimeInterface;
56 import com.android.car.systeminterface.WakeLockInterface;
57 import com.android.car.telemetry.CarTelemetryService;
58 import com.android.car.test.utils.TemporaryDirectory;
59 import com.android.car.watchdog.CarWatchdogService;
60 
61 import org.junit.After;
62 import org.junit.Before;
63 import org.junit.Test;
64 import org.junit.runner.RunWith;
65 import org.mockito.Mock;
66 import org.mockito.junit.MockitoJUnitRunner;
67 
68 import java.io.File;
69 import java.io.IOException;
70 
71 /**
72  * This class contains unit tests for the {@link ICarImpl}.
73  *
74  * <p>It tests that services started with {@link ICarImpl} are initialized properly.
75  * <p>The following mocks are used:
76  * <ol>
77  * <li>{@link ActivityManagerInterface} broadcasts intent for a user.</li>
78  * <li>{@link DisplayInterface} provides access to display operations.</li>
79  * <li>{@link IVehicle} provides access to vehicle properties.</li>
80  * <li>{@link StorageMonitoringInterface} provides access to storage monitoring operations.</li>
81  * <li>{@link SystemStateInterface} provides system statuses (booting, sleeping, ...).</li>
82  * <li>{@link TimeInterface} provides access to time operations.</li>
83  * <li>{@link TimeInterface} provides access to wake lock operations.</li>
84  * </ol>
85  */
86 @RunWith(MockitoJUnitRunner.class)
87 public final class ICarImplTest extends AbstractExtendedMockitoTestCase {
88     private static final String TAG = ICarImplTest.class.getSimpleName();
89 
90     @Mock private ActivityManagerInterface mMockActivityManagerInterface;
91     @Mock private DisplayInterface mMockDisplayInterface;
92     @Mock private VehicleStub mMockVehicle;
93     @Mock private StorageMonitoringInterface mMockStorageMonitoringInterface;
94     @Mock private SystemStateInterface mMockSystemStateInterface;
95     @Mock private TimeInterface mMockTimeInterface;
96     @Mock private WakeLockInterface mMockWakeLockInterface;
97     @Mock private CarWatchdogService mMockCarWatchdogService;
98     @Mock private CarPerformanceService mMockCarPerformanceService;
99     @Mock private GarageModeService mMockGarageModeService;
100     @Mock private CarTelemetryService mMockCarTelemetryService;
101     @Mock private CarRemoteAccessService mMockCarRemoteAccessService;
102     @Mock private ICarServiceHelper mICarServiceHelper;
103 
104     private Context mContext;
105     private SystemInterface mFakeSystemInterface;
106     private UserManager mUserManager;
107 
108     private final MockIOInterface mMockIOInterface = new MockIOInterface();
109 
110     static final class CarServiceConnectedCallback extends ICarResultReceiver.Stub {
111         @Override
send(int resultCode, Bundle resultData)112         public void send(int resultCode, Bundle resultData) {
113             Log.i(TAG, "CarServiceConnectedCallback.send(int resultCode, Bundle resultData)");
114         }
115     }
116 
ICarImplTest()117     public ICarImplTest() {
118         super(ICarImpl.TAG, CarLog.TAG_SERVICE);
119     }
120 
121     @Override
onSessionBuilder(CustomMockitoSessionBuilder builder)122     protected void onSessionBuilder(CustomMockitoSessionBuilder builder) {
123         builder.spyStatic(ICarImpl.class);
124     }
125 
126     /**
127      * Initialize all of the objects with the @Mock annotation.
128      */
129     @Before
setUp()130     public void setUp() throws Exception {
131         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
132         // http://b/25897652.
133         if (Looper.myLooper() == null) {
134             Looper.prepare();
135         }
136 
137         mContext = spy(InstrumentationRegistry.getInstrumentation().getTargetContext());
138 
139         mUserManager = spy(mContext.getSystemService(UserManager.class));
140         doReturn(mUserManager).when(mContext).getSystemService(eq(UserManager.class));
141         doReturn(mUserManager).when(mContext).getSystemService(eq(Context.USER_SERVICE));
142 
143         Resources resources = spy(mContext.getResources());
144         doReturn("").when(resources).getString(
145                 eq(com.android.car.R.string.instrumentClusterRendererService));
146         doReturn(false).when(resources).getBoolean(
147                 eq(com.android.car.R.bool.audioUseDynamicRouting));
148         doReturn(new String[0]).when(resources).getStringArray(
149                 eq(com.android.car.R.array.config_earlyStartupServices));
150         doReturn(resources).when(mContext).getResources();
151 
152         mFakeSystemInterface = Builder.newSystemInterface()
153                 .withSystemStateInterface(mMockSystemStateInterface)
154                 .withActivityManagerInterface(mMockActivityManagerInterface)
155                 .withDisplayInterface(mMockDisplayInterface)
156                 .withIOInterface(mMockIOInterface)
157                 .withStorageMonitoringInterface(mMockStorageMonitoringInterface)
158                 .withTimeInterface(mMockTimeInterface)
159                 .withWakeLockInterface(mMockWakeLockInterface).build();
160         // ICarImpl will register new CarLocalServices services.
161         // This prevents one test failure in tearDown from triggering assertion failure for single
162         // CarLocalServices service.
163         CarLocalServices.removeAllServices();
164     }
165 
166     /**
167      *  Clean up before running the next test.
168      */
169     @After
tearDown()170     public void tearDown() {
171         try {
172             if (mMockIOInterface != null) {
173                 mMockIOInterface.tearDown();
174             }
175         } finally {
176             CarLocalServices.removeAllServices();
177         }
178     }
179 
180     @Test
testNoShardedPreferencesAccessedBeforeUserZeroUnlock()181     public void testNoShardedPreferencesAccessedBeforeUserZeroUnlock() {
182         doReturn(true).when(mContext).isCredentialProtectedStorage();
183         doReturn(false).when(mUserManager).isUserUnlockingOrUnlocked(anyInt());
184         doReturn(false).when(mUserManager).isUserUnlocked();
185         doReturn(false).when(mUserManager).isUserUnlocked(anyInt());
186         doReturn(false).when(mUserManager).isUserUnlocked(any(UserHandle.class));
187         doReturn(false).when(mUserManager).isUserUnlockingOrUnlocked(any(UserHandle.class));
188 
189         doThrow(new NullPointerException()).when(mContext).getSharedPrefsFile(anyString());
190         doThrow(new NullPointerException()).when(mContext).getSharedPreferencesPath(any());
191         doThrow(new NullPointerException()).when(mContext).getSharedPreferences(
192                 anyString(), anyInt());
193         doThrow(new NullPointerException()).when(mContext).getSharedPreferences(
194                 any(File.class), anyInt());
195         doThrow(new NullPointerException()).when(mContext).getDataDir();
196 
197         ICarImpl carImpl = new ICarImpl(mContext, null, mMockVehicle, mFakeSystemInterface,
198                 "MockedCar", /* carUserService= */ null, mMockCarWatchdogService,
199                 mMockCarPerformanceService, mMockGarageModeService,
200                 new MockedCarTestBase.FakeCarPowerPolicyDaemon(), mMockCarTelemetryService,
201                 mMockCarRemoteAccessService, false);
202         doNothing().when(() -> ICarImpl.assertCallingFromSystemProcess());
203         carImpl.setSystemServerConnections(mICarServiceHelper, new CarServiceConnectedCallback());
204         carImpl.init();
205         Car mCar = new Car(mContext, carImpl, /* handler= */ null);
206 
207         // Post tasks for Handler Threads to ensure all the tasks that will be queued inside init
208         // will be done.
209         for (Thread t : Thread.getAllStackTraces().keySet()) {
210             if (!HandlerThread.class.isInstance(t)) {
211                 continue;
212             }
213             HandlerThread ht = (HandlerThread) t;
214             CarServiceUtils.runOnLooperSync(ht.getLooper(), () -> {
215                 // Do nothing, just need to make sure looper finishes current task.
216             });
217         }
218 
219         mCar.disconnect();
220         carImpl.release();
221     }
222 
223     static final class MockIOInterface implements IOInterface {
224         private TemporaryDirectory mFilesDir = null;
225 
226         @Override
getSystemCarDir()227         public File getSystemCarDir() {
228             if (mFilesDir == null) {
229                 try {
230                     mFilesDir = new TemporaryDirectory(TAG);
231                 } catch (IOException e) {
232                     Log.e(TAG, "failed to create temporary directory", e);
233                     fail("failed to create temporary directory. exception was: " + e);
234                 }
235             }
236             return mFilesDir.getDirectory();
237         }
238 
tearDown()239         public void tearDown() {
240             if (mFilesDir != null) {
241                 try {
242                     mFilesDir.close();
243                 } catch (Exception e) {
244                     Log.w(TAG, "could not remove temporary directory", e);
245                 }
246             }
247         }
248     }
249 }
250