1 /* 2 * Copyright (C) 2016 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 package com.android.car; 17 18 import static org.junit.Assert.assertArrayEquals; 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertNotNull; 21 import static org.junit.Assert.assertNull; 22 import static org.junit.Assert.assertTrue; 23 24 import android.car.settings.CarSettings; 25 import android.content.Context; 26 import android.content.SharedPreferences; 27 import android.os.HandlerThread; 28 import android.os.Looper; 29 import android.support.test.InstrumentationRegistry; 30 import android.support.test.annotation.UiThreadTest; 31 import android.support.test.filters.MediumTest; 32 import android.support.test.runner.AndroidJUnit4; 33 34 import com.android.car.GarageModeService.GarageModePolicy; 35 import com.android.car.GarageModeService.WakeupTime; 36 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 40 @RunWith(AndroidJUnit4.class) 41 @MediumTest 42 public class GarageModeTest { 43 private static final int WAIT_FOR_COMPLETION_TIME = 3000;//ms 44 45 @Test 46 @UiThreadTest testMaintenanceActive()47 public void testMaintenanceActive() throws Exception { 48 MockCarPowerManagementService powerManagementService = new MockCarPowerManagementService(); 49 MockDeviceIdleController controller = new MockDeviceIdleController(true); 50 GarageModeServiceForTest garageMode = new GarageModeServiceForTest(getContext(), 51 powerManagementService, 52 controller); 53 garageMode.init(); 54 final int index1 = garageMode.getGarageModeIndex(); 55 assertEquals(garageMode.getMaintenanceWindow(), 56 powerManagementService.doNotifyPrepareShutdown(false)); 57 assertEquals(true, garageMode.isInGarageMode()); 58 assertEquals(true, garageMode.isMaintenanceActive()); 59 60 controller.setMaintenanceActivity(false); 61 assertEquals(false, garageMode.isInGarageMode()); 62 assertEquals(false, garageMode.isMaintenanceActive()); 63 final int index2 = garageMode.getGarageModeIndex(); 64 65 assertEquals(1, index2 - index1); 66 } 67 68 @Test 69 @UiThreadTest testMaintenanceInactive()70 public void testMaintenanceInactive() throws Exception { 71 MockCarPowerManagementService powerManagementService = new MockCarPowerManagementService(); 72 MockDeviceIdleController controller = new MockDeviceIdleController(false); 73 GarageModeServiceForTest garageMode = new GarageModeServiceForTest(getContext(), 74 powerManagementService, 75 controller); 76 garageMode.init(); 77 assertEquals(garageMode.getMaintenanceWindow(), 78 powerManagementService.doNotifyPrepareShutdown(false)); 79 assertEquals(true, garageMode.isInGarageMode()); 80 assertEquals(false, garageMode.isMaintenanceActive()); 81 } 82 83 @Test 84 @UiThreadTest testDisplayOn()85 public void testDisplayOn() throws Exception { 86 MockCarPowerManagementService powerManagementService = new MockCarPowerManagementService(); 87 MockDeviceIdleController controller = new MockDeviceIdleController(true); 88 GarageModeServiceForTest garageMode = new GarageModeServiceForTest(getContext(), 89 powerManagementService, 90 controller); 91 garageMode.init(); 92 93 powerManagementService.doNotifyPrepareShutdown(false); 94 assertTrue(garageMode.getGarageModeIndex() > 0); 95 powerManagementService.doNotifyPowerOn(true); 96 assertEquals(0,garageMode.getGarageModeIndex()); 97 } 98 99 @Test 100 @UiThreadTest testPolicyIndexing()101 public void testPolicyIndexing() throws Exception { 102 // Background processing of asynchronous messages. 103 HandlerThread thread = new HandlerThread("testPolicy"); 104 thread.start(); 105 106 // Test that the index is saved in the prefs and that this index is used to determine the 107 // next wakeup time. 108 MockCarPowerManagementService powerManagementService = new MockCarPowerManagementService(); 109 MockDeviceIdleController controller = new MockDeviceIdleController(true); 110 GarageModeServiceForTest garageMode = new GarageModeServiceForTest(getContext(), 111 powerManagementService, 112 controller, 113 thread.getLooper()); 114 String[] policy = { 115 "15m,1", 116 "6h,8", 117 "1d,5", 118 }; 119 SharedPreferences prefs = 120 getContext().getSharedPreferences("testPolicy", Context.MODE_PRIVATE); 121 prefs.edit().putInt("garage_mode_index", 0).apply(); 122 garageMode.init(policy, prefs); 123 124 assertEquals(15 * 60, garageMode.getWakeupTime()); 125 garageMode.onPrepareShutdown(false); 126 garageMode.onShutdown(); 127 assertEquals(6 * 60 * 60, garageMode.getWakeupTime()); 128 Thread.sleep(WAIT_FOR_COMPLETION_TIME); 129 assertEquals(1, prefs.getInt("garage_mode_index", 0)); 130 131 garageMode = new GarageModeServiceForTest(getContext(), 132 powerManagementService, 133 controller, 134 thread.getLooper()); 135 // Jump ahead 8 restarts. 136 prefs = getContext().getSharedPreferences("testPolicy", Context.MODE_PRIVATE); 137 prefs.edit().putInt("garage_mode_index", 8).apply(); 138 garageMode.init(policy, prefs); 139 140 assertEquals(6 * 60 * 60, garageMode.getWakeupTime()); 141 garageMode.onPrepareShutdown(false); 142 garageMode.onShutdown(); 143 assertEquals(24 * 60 * 60, garageMode.getWakeupTime()); 144 Thread.sleep(WAIT_FOR_COMPLETION_TIME); 145 assertEquals(9, prefs.getInt("garage_mode_index", 0)); 146 } 147 148 @Test testPolicyParserValid()149 public void testPolicyParserValid() throws Exception { 150 WakeupTime expected[] = new WakeupTime[]{ 151 new WakeupTime(15 * 60, 1), 152 new WakeupTime(6 * 60 * 60, 8), 153 new WakeupTime(24 * 60 * 60, 5), 154 }; 155 WakeupTime received[] = new GarageModePolicy(new String[] { 156 "15m,1", 157 "6h,8", 158 "1d,5", 159 }).mWakeupTime; 160 161 assertEquals(expected.length, received.length); 162 for (int i = 0; i < expected.length; i++) { 163 assertEquals(expected[i].mWakeupTime, received[i].mWakeupTime); 164 assertEquals(expected[i].mNumAttempts, received[i].mNumAttempts); 165 } 166 } 167 168 @Test(expected=RuntimeException.class) testPolicyParserNull()169 public void testPolicyParserNull() { 170 new GarageModePolicy(null); 171 } 172 @Test(expected=RuntimeException.class) testPolicyParserEmptyArray()173 public void testPolicyParserEmptyArray() { 174 new GarageModePolicy(new String[] {}); 175 } 176 @Test(expected=RuntimeException.class) testPolicyParserEmptyString()177 public void testPolicyParserEmptyString() { 178 new GarageModePolicy(new String[] {""}); 179 } 180 @Test(expected=RuntimeException.class) testPolicyParserMissingUnits()181 public void testPolicyParserMissingUnits() { 182 new GarageModePolicy(new String[] {"15,1"}); 183 } 184 @Test(expected=RuntimeException.class) testPolicyParserInvalidUnits()185 public void testPolicyParserInvalidUnits() { 186 new GarageModePolicy(new String[] {"15y,1"}); 187 } 188 @Test(expected=RuntimeException.class) testPolicyParserNoCount()189 public void testPolicyParserNoCount() { 190 new GarageModePolicy(new String[] {"15m"}); 191 } 192 @Test(expected=RuntimeException.class) testPolicyParserBadCount()193 public void testPolicyParserBadCount() { 194 new GarageModePolicy(new String[] {"15m,Q"}); 195 } 196 @Test(expected=RuntimeException.class) testPolicyParserNegativeCount()197 public void testPolicyParserNegativeCount() { 198 new GarageModePolicy(new String[] {"15m,-1"}); 199 } 200 @Test(expected=RuntimeException.class) testPolicyParserNoTime()201 public void testPolicyParserNoTime() { 202 new GarageModePolicy(new String[] {",1"}); 203 } 204 @Test(expected=RuntimeException.class) testPolicyParserNoTimeValue()205 public void testPolicyParserNoTimeValue() { 206 new GarageModePolicy(new String[] {"m,1"}); 207 } 208 @Test(expected=RuntimeException.class) testPolicyParserBadTime()209 public void testPolicyParserBadTime() { 210 new GarageModePolicy(new String[] {"Qm,1"}); 211 } 212 @Test(expected=RuntimeException.class) testPolicyParserNegativeTime()213 public void testPolicyParserNegativeTime() { 214 new GarageModePolicy(new String[] {"-10m,1"}); 215 } 216 217 @Test testPolicyInResource()218 public void testPolicyInResource() throws Exception { 219 // Test that the policy in the resource file parses fine. 220 assertNotNull(new GarageModePolicy(getContext().getResources().getStringArray( 221 R.array.config_garageModeCadence)).mWakeupTime); 222 } 223 224 private static class MockCarPowerManagementService extends CarPowerManagementService { doNotifyPrepareShutdown(boolean shuttingdown)225 public long doNotifyPrepareShutdown(boolean shuttingdown) { 226 return notifyPrepareShutdown(shuttingdown); 227 } 228 doNotifyPowerOn(boolean displayOn)229 public void doNotifyPowerOn(boolean displayOn) { 230 notifyPowerOn(displayOn); 231 } 232 } 233 234 private static class GarageModeServiceForTest extends GarageModeService { GarageModeServiceForTest(Context context, CarPowerManagementService powerManagementService, DeviceIdleControllerWrapper controllerWrapper, Looper looper)235 public GarageModeServiceForTest(Context context, 236 CarPowerManagementService powerManagementService, 237 DeviceIdleControllerWrapper controllerWrapper, 238 Looper looper) { 239 super(context, powerManagementService, controllerWrapper, looper); 240 } 241 GarageModeServiceForTest(Context context, CarPowerManagementService powerManagementService, DeviceIdleControllerWrapper controllerWrapper)242 public GarageModeServiceForTest(Context context, 243 CarPowerManagementService powerManagementService, 244 DeviceIdleControllerWrapper controllerWrapper) { 245 super(context, powerManagementService, controllerWrapper, Looper.myLooper()); 246 } 247 getMaintenanceWindow()248 public long getMaintenanceWindow() { 249 return CarSettings.DEFAULT_GARAGE_MODE_MAINTENANCE_WINDOW; 250 } 251 isInGarageMode()252 public boolean isInGarageMode() { 253 synchronized (this) { 254 return mInGarageMode; 255 } 256 } 257 isMaintenanceActive()258 public boolean isMaintenanceActive() { 259 synchronized (this) { 260 return mMaintenanceActive; 261 } 262 } 263 getGarageModeIndex()264 public int getGarageModeIndex() { 265 synchronized (this) { 266 return mGarageModeIndex; 267 } 268 } 269 } 270 getContext()271 private Context getContext() { 272 return InstrumentationRegistry.getTargetContext(); 273 } 274 275 private static class MockDeviceIdleController extends DeviceIdleControllerWrapper { 276 277 private final boolean mInitialActive; 278 MockDeviceIdleController(boolean active)279 MockDeviceIdleController(boolean active) { 280 super(); 281 mInitialActive = active; 282 } 283 284 @Override startLocked()285 protected boolean startLocked() { 286 return mInitialActive; 287 } 288 289 @Override stopTracking()290 public void stopTracking() { 291 // nothing to clean up 292 } 293 294 @Override reportActiveLocked(final boolean active)295 protected void reportActiveLocked(final boolean active) { 296 // directly calling the callback instead of posting to handler, to make testing easier. 297 if (mListener.get() != null) { 298 mListener.get().onMaintenanceActivityChanged(active); 299 } 300 } 301 setMaintenanceActivity(boolean active)302 public void setMaintenanceActivity(boolean active) { 303 super.setMaintenanceActivity(active); 304 } 305 } 306 } 307