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