aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnrico Granata <egranata@google.com>2017-10-12 12:25:06 -0700
committerEnrico Granata <egranata@google.com>2017-10-17 13:11:48 -0700
commitb19bc326413285806ecca7fb7b54ec7a9074f286 (patch)
treea870f3d504e10d0ce0e23c4c5b9a77837f6c234f
parent9739b3cb1c663f54157a55189a448da607e063c0 (diff)
downloadCar-b19bc326413285806ecca7fb7b54ec7a9074f286.tar.gz
Refactor SystemInterface.
Split SystemInterface into a set of smaller chunks, each wrapping one specific functional set of system APIs. Provide default implementations of each of those chunks. Rework SystemInterface to be a class that wraps all the chunks and forwards to each of them. Add a Builder API to allow one to construct a full SystemInterface from individual chunks. This turns a fairly heavy-weight interface into smaller pieces which are easier to use individually, and it also makes it easier for tests to only change a subset of SystemInterface functionality when they need to do so. Test: runtest -x packages/services/Car/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java runtest -x packages/services/Car/tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java runtest -x packages/services/Car/tests/carservice_test/src/com/android/car/CarPowerManagementTest.java runtest -x packages/services/Car/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java runtest -x packages/services/Car/tests/carservice_test/src/com/android/car/CarDiagnosticManagerTest.java runtest -x packages/services/Car/tests/carservice_test/src/com/android/car/CarSensorManagerTest.java Change-Id: I34c89b526d052126198a148d742123af78eafcbd Fixes: 67739411
-rw-r--r--service/src/com/android/car/CarPowerManagementService.java1
-rw-r--r--service/src/com/android/car/CarService.java6
-rw-r--r--service/src/com/android/car/CarStorageMonitoringService.java3
-rw-r--r--service/src/com/android/car/ICarImpl.java1
-rw-r--r--service/src/com/android/car/SystemInterface.java261
-rw-r--r--service/src/com/android/car/UptimeTracker.java82
-rw-r--r--service/src/com/android/car/systeminterface/DisplayInterface.java115
-rw-r--r--service/src/com/android/car/systeminterface/IOInterface.java40
-rw-r--r--service/src/com/android/car/systeminterface/StorageMonitoringInterface.java41
-rw-r--r--service/src/com/android/car/systeminterface/SystemInterface.java227
-rw-r--r--service/src/com/android/car/systeminterface/SystemStateInterface.java107
-rw-r--r--service/src/com/android/car/systeminterface/TimeInterface.java57
-rw-r--r--service/src/com/android/car/systeminterface/WakeLockInterface.java75
-rw-r--r--tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/CarEmulator.java6
-rw-r--r--tests/carservice_test/src/com/android/car/CarPowerManagementTest.java40
-rw-r--r--tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java85
-rw-r--r--tests/carservice_test/src/com/android/car/MockedCarTestBase.java177
-rw-r--r--tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java143
-rw-r--r--tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java57
19 files changed, 985 insertions, 539 deletions
diff --git a/service/src/com/android/car/CarPowerManagementService.java b/service/src/com/android/car/CarPowerManagementService.java
index 4eb04b46c5..745c46d5ae 100644
--- a/service/src/com/android/car/CarPowerManagementService.java
+++ b/service/src/com/android/car/CarPowerManagementService.java
@@ -24,6 +24,7 @@ import android.util.Log;
import com.android.car.hal.PowerHalService;
import com.android.car.hal.PowerHalService.PowerState;
+import com.android.car.systeminterface.SystemInterface;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
diff --git a/service/src/com/android/car/CarService.java b/service/src/com/android/car/CarService.java
index ae5f0f8152..497135e69b 100644
--- a/service/src/com/android/car/CarService.java
+++ b/service/src/com/android/car/CarService.java
@@ -31,6 +31,8 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.util.Log;
+import com.android.car.systeminterface.SystemInterface;
+
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.RingBufferIndices;
@@ -85,7 +87,9 @@ public class CarService extends Service {
Log.i(CarLog.TAG_SERVICE, "Connected to " + mVehicleInterfaceName);
- mICarImpl = new ICarImpl(this, mVehicle, SystemInterface.createDefault(this),
+ mICarImpl = new ICarImpl(this,
+ mVehicle,
+ SystemInterface.Builder.defaultSystemInterface(this).build(),
mCanBusErrorNotifier);
mICarImpl.init();
SystemProperties.set("boot.car_service_created", "1");
diff --git a/service/src/com/android/car/CarStorageMonitoringService.java b/service/src/com/android/car/CarStorageMonitoringService.java
index d933455afc..ae2c710aa4 100644
--- a/service/src/com/android/car/CarStorageMonitoringService.java
+++ b/service/src/com/android/car/CarStorageMonitoringService.java
@@ -31,6 +31,7 @@ import com.android.car.storagemonitoring.WearEstimateRecord;
import com.android.car.storagemonitoring.WearHistory;
import com.android.car.storagemonitoring.WearInformation;
import com.android.car.storagemonitoring.WearInformationProvider;
+import com.android.car.systeminterface.SystemInterface;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
@@ -41,8 +42,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
-import java.util.function.BiPredicate;
-import java.util.function.Function;
import org.json.JSONException;
public class CarStorageMonitoringService extends ICarStorageMonitoring.Stub
diff --git a/service/src/com/android/car/ICarImpl.java b/service/src/com/android/car/ICarImpl.java
index d522debd52..1d1f997459 100644
--- a/service/src/com/android/car/ICarImpl.java
+++ b/service/src/com/android/car/ICarImpl.java
@@ -36,6 +36,7 @@ import com.android.car.hal.VehicleHal;
import com.android.car.internal.FeatureConfiguration;
import com.android.car.internal.FeatureUtil;
import com.android.car.pm.CarPackageManagerService;
+import com.android.car.systeminterface.SystemInterface;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.car.ICarServiceHelper;
import java.io.PrintWriter;
diff --git a/service/src/com/android/car/SystemInterface.java b/service/src/com/android/car/SystemInterface.java
deleted file mode 100644
index 7272355dc1..0000000000
--- a/service/src/com/android/car/SystemInterface.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.car;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.hardware.display.DisplayManager;
-import android.os.PowerManager;
-import android.os.PowerManager.WakeLock;
-import android.os.SystemClock;
-import android.util.Log;
-import android.util.Pair;
-import android.view.Display;
-import com.android.car.storagemonitoring.EMmcWearInformationProvider;
-import com.android.car.storagemonitoring.UfsWearInformationProvider;
-import com.android.car.storagemonitoring.WearInformationProvider;
-import java.io.File;
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Interface that abstracts all interactions with Android system APIs.
- */
-public interface SystemInterface {
- public static final boolean INCLUDE_DEEP_SLEEP_TIME = true;
- public static final boolean EXCLUDE_DEEP_SLEEP_TIME = false;
-
- void setDisplayState(boolean on);
- void releaseAllWakeLocks();
- void shutdown();
- void enterDeepSleep(int wakeupTimeSec);
- void switchToPartialWakeLock();
- void switchToFullWakeLock();
- void startDisplayStateMonitoring(CarPowerManagementService service);
- void stopDisplayStateMonitoring();
- File getFilesDir();
- void scheduleActionForBootCompleted(Runnable action, Duration delay);
-
- default WearInformationProvider[] getFlashWearInformationProviders() {
- return new WearInformationProvider[] {
- new EMmcWearInformationProvider(),
- new UfsWearInformationProvider()
- };
- }
-
- default long getUptime() {
- return getUptime(EXCLUDE_DEEP_SLEEP_TIME);
- }
- default long getUptime(boolean includeDeepSleepTime) {
- return includeDeepSleepTime ?
- SystemClock.elapsedRealtime() :
- SystemClock.uptimeMillis();
- }
-
- default boolean isWakeupCausedByTimer() {
- //TODO bug: 32061842, check wake up reason and do necessary operation information should
- // come from kernel. it can be either power on or wake up for maintenance
- // power on will involve GPIO trigger from power controller
- // its own wakeup will involve timer expiration.
- return false;
- }
-
- default boolean isSystemSupportingDeepSleep() {
- //TODO should return by checking some kernel suspend control sysfs, bug: 32061842
- return false;
- }
-
- public static SystemInterface createDefault(Context context) {
- return new SystemInterfaceImpl(context);
- }
-
- class SystemInterfaceImpl implements SystemInterface {
- private final static Duration MIN_BOOT_COMPLETE_ACTION_DELAY = Duration.ofSeconds(10);
-
- private final Context mContext;
- private final PowerManager mPowerManager;
- private final DisplayManager mDisplayManager;
- private final WakeLock mFullWakeLock;
- private final WakeLock mPartialWakeLock;
- private final DisplayStateListener mDisplayListener;
- private final File mFilesDir;
- private CarPowerManagementService mService;
- private boolean mDisplayStateSet;
- private List<Pair<Runnable, Duration>> mActionsList = new ArrayList<>();
- private ScheduledExecutorService mExecutorService;
- private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
- for (Pair<Runnable, Duration> action : mActionsList) {
- mExecutorService.schedule(action.first,
- action.second.toMillis(), TimeUnit.MILLISECONDS);
- }
- }
- }
- };
-
- private SystemInterfaceImpl(Context context) {
- mContext = context;
- mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
- mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- mFullWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK,
- CarLog.TAG_POWER);
- mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
- CarLog.TAG_POWER);
- mDisplayListener = new DisplayStateListener();
- mFilesDir = context.getFilesDir();
- }
-
- @Override
- public void startDisplayStateMonitoring(CarPowerManagementService service) {
- synchronized (this) {
- mService = service;
- mDisplayStateSet = isMainDisplayOn();
- }
- mDisplayManager.registerDisplayListener(mDisplayListener, service.getHandler());
- }
-
- @Override
- public void stopDisplayStateMonitoring() {
- mDisplayManager.unregisterDisplayListener(mDisplayListener);
- }
-
- @Override
- public void setDisplayState(boolean on) {
- synchronized (this) {
- mDisplayStateSet = on;
- }
- if (on) {
- switchToFullWakeLock();
- Log.i(CarLog.TAG_POWER, "on display");
- mPowerManager.wakeUp(SystemClock.uptimeMillis());
- } else {
- switchToPartialWakeLock();
- Log.i(CarLog.TAG_POWER, "off display");
- mPowerManager.goToSleep(SystemClock.uptimeMillis());
- }
- }
-
- private boolean isMainDisplayOn() {
- Display disp = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
- return disp.getState() == Display.STATE_ON;
- }
-
- @Override
- public void shutdown() {
- mPowerManager.shutdown(false /* no confirm*/, null, true /* true */);
- }
-
- @Override
- public void enterDeepSleep(int wakeupTimeSec) {
- //TODO set wake up time, bug: 32061842
- mPowerManager.goToSleep(SystemClock.uptimeMillis(),
- PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN,
- PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
- }
-
- @Override
- public void switchToPartialWakeLock() {
- if (!mPartialWakeLock.isHeld()) {
- mPartialWakeLock.acquire();
- }
- if (mFullWakeLock.isHeld()) {
- mFullWakeLock.release();
- }
- }
-
- @Override
- public void switchToFullWakeLock() {
- if (!mFullWakeLock.isHeld()) {
- mFullWakeLock.acquire();
- }
- if (mPartialWakeLock.isHeld()) {
- mPartialWakeLock.release();
- }
- }
-
- @Override
- public void releaseAllWakeLocks() {
- if (mPartialWakeLock.isHeld()) {
- mPartialWakeLock.release();
- }
- if (mFullWakeLock.isHeld()) {
- mFullWakeLock.release();
- }
- }
-
- @Override
- public File getFilesDir() {
- return mFilesDir;
- }
-
- @Override
- public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
- if (MIN_BOOT_COMPLETE_ACTION_DELAY.compareTo(delay) < 0) {
- // TODO: consider adding some degree of randomness here
- delay = MIN_BOOT_COMPLETE_ACTION_DELAY;
- }
- if (mActionsList.isEmpty()) {
- final int corePoolSize = 1;
- mExecutorService = Executors.newScheduledThreadPool(corePoolSize);
- IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
- mContext.registerReceiver(mBroadcastReceiver, intentFilter);
- }
- mActionsList.add(Pair.create(action, delay));
- }
-
- private void handleMainDisplayChanged() {
- boolean isOn = isMainDisplayOn();
- CarPowerManagementService service;
- synchronized (this) {
- if (mDisplayStateSet == isOn) { // same as what is set
- return;
- }
- service = mService;
- }
- service.handleMainDisplayChanged(isOn);
- }
-
- private class DisplayStateListener implements DisplayManager.DisplayListener {
-
- @Override
- public void onDisplayAdded(int displayId) {
- //ignore
- }
-
- @Override
- public void onDisplayChanged(int displayId) {
- if (displayId == Display.DEFAULT_DISPLAY) {
- handleMainDisplayChanged();
- }
- }
-
- @Override
- public void onDisplayRemoved(int displayId) {
- //ignore
- }
- }
- }
-} \ No newline at end of file
diff --git a/service/src/com/android/car/UptimeTracker.java b/service/src/com/android/car/UptimeTracker.java
index 1b8906fa54..2a1d26eae1 100644
--- a/service/src/com/android/car/UptimeTracker.java
+++ b/service/src/com/android/car/UptimeTracker.java
@@ -16,15 +16,13 @@
package com.android.car;
-import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-
-import android.annotation.Nullable;
-import android.os.SystemClock;
import android.util.JsonReader;
import android.util.JsonWriter;
import android.util.Log;
+import com.android.car.systeminterface.SystemInterface;
+
+import com.android.car.systeminterface.TimeInterface;
import com.android.internal.annotations.VisibleForTesting;
import java.io.File;
@@ -33,7 +31,6 @@ import java.io.FileWriter;
import java.io.IOException;
import java.util.Objects;
import java.util.Optional;
-import java.util.concurrent.ScheduledExecutorService;
/**
* A class that can keep track of how long its instances are alive for.
@@ -60,46 +57,6 @@ import java.util.concurrent.ScheduledExecutorService;
* ensure that crashes do not cause more than a certain amount of uptime to go untracked.
*/
public class UptimeTracker {
- @VisibleForTesting
- interface TimingProvider {
- long getCurrentRealtime();
- void schedule(Runnable r, long delay);
- void cancelAll();
- }
-
- private static final class DefaultTimingProvider implements TimingProvider {
- @Nullable
- private final SystemInterface mSystemInterface;
- private final ScheduledExecutorService mExecutor = newSingleThreadScheduledExecutor();
-
- DefaultTimingProvider() {
- this(null);
- }
-
- DefaultTimingProvider(SystemInterface systemInterface) {
- mSystemInterface = systemInterface;
- }
-
- @Override
- public long getCurrentRealtime() {
- if (mSystemInterface != null) {
- return mSystemInterface.getUptime(false);
- } else {
- return SystemClock.uptimeMillis();
- }
- }
-
- @Override
- public void schedule(Runnable r, long delay) {
- mExecutor.scheduleWithFixedDelay(r, delay, delay, MILLISECONDS);
- }
-
- @Override
- public void cancelAll() {
- mExecutor.shutdownNow();
- }
- }
-
/**
* In order to prevent excessive wear-out of the storage, do not allow snapshots to happen
* more frequently than this value
@@ -131,43 +88,42 @@ public class UptimeTracker {
/**
* The source of real-time and scheduling
*/
- private TimingProvider mTimingProvider;
+ private TimeInterface mTimeInterface;
public UptimeTracker(File file) {
this(file, DEFAULT_SNAPSHOT_INTERVAL_MS);
}
public UptimeTracker(File file, long snapshotInterval) {
- this(file, snapshotInterval, new DefaultTimingProvider());
+ this(file, snapshotInterval, new TimeInterface.DefaultImpl());
}
UptimeTracker(File file, long snapshotInterval, SystemInterface systemInterface) {
- this(file, snapshotInterval, new DefaultTimingProvider(systemInterface));
+ this(file, snapshotInterval, systemInterface.getTimeInterface());
}
- // By default, SystemClock::elapsedRealtime is used as the source of the uptime clock
- // and a ScheduledExecutorService provides snapshot synchronization. For testing purposes
- // this constructor allows using a controlled source of time information and scheduling.
+ // This constructor allows one to replace the source of time-based truths with
+ // a mock version. This is mostly useful for testing purposes.
@VisibleForTesting
UptimeTracker(File file,
long snapshotInterval,
- TimingProvider timingProvider) {
+ TimeInterface timeInterface) {
snapshotInterval = Math.max(snapshotInterval, MINIMUM_SNAPSHOT_INTERVAL_MS);
mUptimeFile = Objects.requireNonNull(file);
- mTimingProvider = timingProvider;
- mLastRealTimeSnapshot = mTimingProvider.getCurrentRealtime();
+ mTimeInterface = timeInterface;
+ mLastRealTimeSnapshot = mTimeInterface.getUptime(TimeInterface.EXCLUDE_DEEP_SLEEP_TIME);
mHistoricalUptime = Optional.empty();
- mTimingProvider.schedule(this::flushSnapshot, snapshotInterval);
+ mTimeInterface.scheduleAction(this::flushSnapshot, snapshotInterval);
}
void onDestroy() {
synchronized (mLock) {
- if (mTimingProvider != null) {
- mTimingProvider.cancelAll();
+ if (mTimeInterface != null) {
+ mTimeInterface.cancelAllActions();
}
flushSnapshot();
- mTimingProvider = null;
+ mTimeInterface = null;
mUptimeFile = null;
}
}
@@ -179,11 +135,12 @@ public class UptimeTracker {
*/
long getTotalUptime() {
synchronized (mLock) {
- if (mTimingProvider == null) {
+ if (mTimeInterface == null) {
return 0;
}
return getHistoricalUptimeLocked() + (
- mTimingProvider.getCurrentRealtime() - mLastRealTimeSnapshot);
+ mTimeInterface.getUptime(TimeInterface.EXCLUDE_DEEP_SLEEP_TIME)
+ - mLastRealTimeSnapshot);
}
}
@@ -216,7 +173,8 @@ public class UptimeTracker {
try {
long newUptime = getTotalUptime();
mHistoricalUptime = Optional.of(newUptime);
- mLastRealTimeSnapshot = mTimingProvider.getCurrentRealtime();
+ mLastRealTimeSnapshot = mTimeInterface.getUptime(
+ TimeInterface.EXCLUDE_DEEP_SLEEP_TIME);
JsonWriter writer = new JsonWriter(new FileWriter(mUptimeFile));
writer.beginObject();
diff --git a/service/src/com/android/car/systeminterface/DisplayInterface.java b/service/src/com/android/car/systeminterface/DisplayInterface.java
new file mode 100644
index 0000000000..f798b0d096
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/DisplayInterface.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.systeminterface;
+
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Log;
+import android.view.Display;
+import com.android.car.CarLog;
+import com.android.car.CarPowerManagementService;
+
+/**
+ * Interface that abstracts display operations
+ */
+public interface DisplayInterface {
+ void setDisplayState(boolean on);
+ void startDisplayStateMonitoring(CarPowerManagementService service);
+ void stopDisplayStateMonitoring();
+
+ class DefaultImpl implements DisplayInterface {
+ private final DisplayManager mDisplayManager;
+ private final PowerManager mPowerManager;
+ private final WakeLockInterface mWakeLockInterface;
+ private CarPowerManagementService mService;
+ private boolean mDisplayStateSet;
+ private final DisplayManager.DisplayListener mDisplayListener = new DisplayListener() {
+ @Override
+ public void onDisplayAdded(int displayId) {
+ //ignore
+ }
+
+ @Override
+ public void onDisplayRemoved(int displayId) {
+ //ignore
+ }
+
+ @Override
+ public void onDisplayChanged(int displayId) {
+ if (displayId == Display.DEFAULT_DISPLAY) {
+ handleMainDisplayChanged();
+ }
+ }
+ };
+
+ DefaultImpl(Context context, WakeLockInterface wakeLockInterface) {
+ mWakeLockInterface = wakeLockInterface;
+ mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
+ mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ }
+
+ private void handleMainDisplayChanged() {
+ boolean isOn = isMainDisplayOn();
+ CarPowerManagementService service;
+ synchronized (this) {
+ if (mDisplayStateSet == isOn) { // same as what is set
+ return;
+ }
+ service = mService;
+ }
+ service.handleMainDisplayChanged(isOn);
+ }
+
+ private boolean isMainDisplayOn() {
+ Display disp = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
+ return disp.getState() == Display.STATE_ON;
+ }
+
+ @Override
+ public void startDisplayStateMonitoring(CarPowerManagementService service) {
+ synchronized (this) {
+ mService = service;
+ mDisplayStateSet = isMainDisplayOn();
+ }
+ mDisplayManager.registerDisplayListener(mDisplayListener, service.getHandler());
+ }
+
+ @Override
+ public void stopDisplayStateMonitoring() {
+ mDisplayManager.unregisterDisplayListener(mDisplayListener);
+ }
+
+ @Override
+ public void setDisplayState(boolean on) {
+ synchronized (this) {
+ mDisplayStateSet = on;
+ }
+ if (on) {
+ mWakeLockInterface.switchToFullWakeLock();
+ Log.i(CarLog.TAG_POWER, "on display");
+ mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ } else {
+ mWakeLockInterface.switchToPartialWakeLock();
+ Log.i(CarLog.TAG_POWER, "off display");
+ mPowerManager.goToSleep(SystemClock.uptimeMillis());
+ }
+ }
+ }
+}
diff --git a/service/src/com/android/car/systeminterface/IOInterface.java b/service/src/com/android/car/systeminterface/IOInterface.java
new file mode 100644
index 0000000000..2ce917495b
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/IOInterface.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.systeminterface;
+
+import android.content.Context;
+import java.io.File;
+
+/**
+ * Interface that abstracts I/O operations
+ */
+public interface IOInterface {
+ File getFilesDir();
+
+ class DefaultImpl implements IOInterface {
+ private final File mFilesDir;
+
+ DefaultImpl(Context context) {
+ mFilesDir = context.getFilesDir();
+ }
+
+ @Override
+ public File getFilesDir() {
+ return mFilesDir;
+ }
+ }
+}
diff --git a/service/src/com/android/car/systeminterface/StorageMonitoringInterface.java b/service/src/com/android/car/systeminterface/StorageMonitoringInterface.java
new file mode 100644
index 0000000000..5825f8f250
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/StorageMonitoringInterface.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.systeminterface;
+
+import com.android.car.storagemonitoring.EMmcWearInformationProvider;
+import com.android.car.storagemonitoring.ProcfsUidIoStatsProvider;
+import com.android.car.storagemonitoring.UfsWearInformationProvider;
+import com.android.car.storagemonitoring.UidIoStatsProvider;
+import com.android.car.storagemonitoring.WearInformationProvider;
+
+/**
+ * Interface that abstracts storage monitoring operations
+ */
+public interface StorageMonitoringInterface {
+ default WearInformationProvider[] getFlashWearInformationProviders() {
+ return new WearInformationProvider[] {
+ new EMmcWearInformationProvider(),
+ new UfsWearInformationProvider()
+ };
+ }
+
+ default UidIoStatsProvider getUidIoStatsProvider() {
+ return new ProcfsUidIoStatsProvider();
+ }
+
+ class DefaultImpl implements StorageMonitoringInterface {}
+}
diff --git a/service/src/com/android/car/systeminterface/SystemInterface.java b/service/src/com/android/car/systeminterface/SystemInterface.java
new file mode 100644
index 0000000000..72a8a0ac57
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/SystemInterface.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.systeminterface;
+
+import android.content.Context;
+import com.android.car.CarPowerManagementService;
+import com.android.car.storagemonitoring.UidIoStatsProvider;
+import com.android.car.storagemonitoring.WearInformationProvider;
+import java.io.File;
+import java.time.Duration;
+import java.util.Objects;
+
+/**
+ * This class contains references to all the different wrapper interfaces between
+ * CarService and the Android OS APIs.
+ */
+public final class SystemInterface implements DisplayInterface, IOInterface,
+ StorageMonitoringInterface, SystemStateInterface, TimeInterface,
+ WakeLockInterface {
+ private final DisplayInterface mDisplayInterface;
+ private final IOInterface mIOInterface;
+ private final StorageMonitoringInterface mStorageMonitoringInterface;
+ private final SystemStateInterface mSystemStateInterface;
+ private final TimeInterface mTimeInterface;
+ private final WakeLockInterface mWakeLockInterface;
+
+ SystemInterface(DisplayInterface displayInterface,
+ IOInterface ioInterface,
+ StorageMonitoringInterface storageMonitoringInterface,
+ SystemStateInterface systemStateInterface,
+ TimeInterface timeInterface,
+ WakeLockInterface wakeLockInterface) {
+ mDisplayInterface = displayInterface;
+ mIOInterface = ioInterface;
+ mStorageMonitoringInterface = storageMonitoringInterface;
+ mSystemStateInterface = systemStateInterface;
+ mTimeInterface = timeInterface;
+ mWakeLockInterface = wakeLockInterface;
+ }
+
+ public DisplayInterface getDisplayInterface() { return mDisplayInterface; }
+ public IOInterface getIOInterface() { return mIOInterface; }
+ public SystemStateInterface getSystemStateInterface() { return mSystemStateInterface; }
+ public TimeInterface getTimeInterface() { return mTimeInterface; }
+ public WakeLockInterface getWakeLockInterface() { return mWakeLockInterface; }
+
+ @Override
+ public File getFilesDir() {
+ return mIOInterface.getFilesDir();
+ }
+
+ @Override
+ public void releaseAllWakeLocks() {
+ mWakeLockInterface.releaseAllWakeLocks();
+ }
+
+ @Override
+ public void switchToPartialWakeLock() {
+ mWakeLockInterface.switchToPartialWakeLock();
+ }
+
+ @Override
+ public void switchToFullWakeLock() {
+ mWakeLockInterface.switchToFullWakeLock();
+ }
+
+ @Override
+ public long getUptime() {
+ return mTimeInterface.getUptime();
+ }
+
+ @Override
+ public long getUptime(boolean includeDeepSleepTime) {
+ return mTimeInterface.getUptime(includeDeepSleepTime);
+ }
+
+ @Override
+ public void scheduleAction(Runnable r, long delayMs) {
+ mTimeInterface.scheduleAction(r, delayMs);
+ }
+
+ @Override
+ public void cancelAllActions() {
+ mTimeInterface.cancelAllActions();
+ }
+
+ @Override
+ public void setDisplayState(boolean on) {
+ mDisplayInterface.setDisplayState(on);
+ }
+
+ @Override
+ public void startDisplayStateMonitoring(CarPowerManagementService service) {
+ mDisplayInterface.startDisplayStateMonitoring(service);
+ }
+
+ @Override
+ public void stopDisplayStateMonitoring() {
+ mDisplayInterface.stopDisplayStateMonitoring();
+ }
+
+ @Override
+ public WearInformationProvider[] getFlashWearInformationProviders() {
+ return mStorageMonitoringInterface.getFlashWearInformationProviders();
+ }
+
+ @Override
+ public UidIoStatsProvider getUidIoStatsProvider() {
+ return mStorageMonitoringInterface.getUidIoStatsProvider();
+ }
+
+ @Override
+ public void shutdown() {
+ mSystemStateInterface.shutdown();
+ }
+
+ @Override
+ public void enterDeepSleep(int wakeupTimeSec) {
+ mSystemStateInterface.enterDeepSleep(wakeupTimeSec);
+ }
+
+ @Override
+ public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
+ mSystemStateInterface.scheduleActionForBootCompleted(action, delay);
+ }
+
+ @Override
+ public boolean isWakeupCausedByTimer() {
+ return mSystemStateInterface.isWakeupCausedByTimer();
+ }
+
+ @Override
+ public boolean isSystemSupportingDeepSleep() {
+ return mSystemStateInterface.isSystemSupportingDeepSleep();
+ }
+
+ public final static class Builder {
+ private DisplayInterface mDisplayInterface;
+ private IOInterface mIOInterface;
+ private StorageMonitoringInterface mStorageMonitoringInterface;
+ private SystemStateInterface mSystemStateInterface;
+ private TimeInterface mTimeInterface;
+ private WakeLockInterface mWakeLockInterface;
+
+ private Builder() {}
+
+ public static Builder newSystemInterface() {
+ return new Builder();
+ }
+
+ public static Builder defaultSystemInterface(Context context) {
+ context = Objects.requireNonNull(context);
+ Builder builder = newSystemInterface();
+ builder.withWakeLockInterface(new WakeLockInterface.DefaultImpl(context));
+ builder.withDisplayInterface(new DisplayInterface.DefaultImpl(context,
+ builder.mWakeLockInterface));
+ builder.withIOInterface(new IOInterface.DefaultImpl(context));
+ builder.withStorageMonitoringInterface(new StorageMonitoringInterface.DefaultImpl());
+ builder.withSystemStateInterface(new SystemStateInterface.DefaultImpl(context));
+ return builder.withTimeInterface(new TimeInterface.DefaultImpl());
+ }
+
+ public static Builder fromBuilder(Builder otherBuilder) {
+ return newSystemInterface()
+ .withDisplayInterface(otherBuilder.mDisplayInterface)
+ .withIOInterface(otherBuilder.mIOInterface)
+ .withStorageMonitoringInterface(otherBuilder.mStorageMonitoringInterface)
+ .withSystemStateInterface(otherBuilder.mSystemStateInterface)
+ .withTimeInterface(otherBuilder.mTimeInterface)
+ .withWakeLockInterface(otherBuilder.mWakeLockInterface);
+ }
+
+ public Builder withDisplayInterface(DisplayInterface displayInterface) {
+ mDisplayInterface = displayInterface;
+ return this;
+ }
+
+ public Builder withIOInterface(IOInterface ioInterface) {
+ mIOInterface = ioInterface;
+ return this;
+ }
+
+ public Builder withStorageMonitoringInterface(StorageMonitoringInterface
+ storageMonitoringInterface) {
+ mStorageMonitoringInterface = storageMonitoringInterface;
+ return this;
+ }
+
+ public Builder withSystemStateInterface(SystemStateInterface systemStateInterface) {
+ mSystemStateInterface = systemStateInterface;
+ return this;
+ }
+
+ public Builder withTimeInterface(TimeInterface timeInterface) {
+ mTimeInterface = timeInterface;
+ return this;
+ }
+
+ public Builder withWakeLockInterface(WakeLockInterface wakeLockInterface) {
+ mWakeLockInterface = wakeLockInterface;
+ return this;
+ }
+
+ public SystemInterface build() {
+ return new SystemInterface(Objects.requireNonNull(mDisplayInterface),
+ Objects.requireNonNull(mIOInterface),
+ Objects.requireNonNull(mStorageMonitoringInterface),
+ Objects.requireNonNull(mSystemStateInterface),
+ Objects.requireNonNull(mTimeInterface),
+ Objects.requireNonNull(mWakeLockInterface));
+ }
+ }
+}
diff --git a/service/src/com/android/car/systeminterface/SystemStateInterface.java b/service/src/com/android/car/systeminterface/SystemStateInterface.java
new file mode 100644
index 0000000000..bfb63b8554
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/SystemStateInterface.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.systeminterface;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Pair;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Interface that abstracts system status (booted, sleeping, ...) operations
+ */
+public interface SystemStateInterface {
+ void shutdown();
+ void enterDeepSleep(int wakeupTimeSec);
+ void scheduleActionForBootCompleted(Runnable action, Duration delay);
+
+ default boolean isWakeupCausedByTimer() {
+ //TODO bug: 32061842, check wake up reason and do necessary operation information should
+ // come from kernel. it can be either power on or wake up for maintenance
+ // power on will involve GPIO trigger from power controller
+ // its own wakeup will involve timer expiration.
+ return false;
+ }
+
+ default boolean isSystemSupportingDeepSleep() {
+ //TODO should return by checking some kernel suspend control sysfs, bug: 32061842
+ return false;
+ }
+
+ class DefaultImpl implements SystemStateInterface {
+ private final static Duration MIN_BOOT_COMPLETE_ACTION_DELAY = Duration.ofSeconds(10);
+
+ private final Context mContext;
+ private final PowerManager mPowerManager;
+ private List<Pair<Runnable, Duration>> mActionsList = new ArrayList<>();
+ private ScheduledExecutorService mExecutorService;
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) {
+ for (Pair<Runnable, Duration> action : mActionsList) {
+ mExecutorService.schedule(action.first,
+ action.second.toMillis(), TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+ };
+
+ DefaultImpl(Context context) {
+ mContext = context;
+ mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ }
+
+ @Override
+ public void shutdown() {
+ mPowerManager.shutdown(false /* no confirm*/, null, true /* true */);
+ }
+
+ @Override
+ public void enterDeepSleep(int wakeupTimeSec) {
+ //TODO set wake up time, bug: 32061842
+ mPowerManager.goToSleep(SystemClock.uptimeMillis(),
+ PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN,
+ PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+ }
+
+ @Override
+ public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
+ if (MIN_BOOT_COMPLETE_ACTION_DELAY.compareTo(delay) < 0) {
+ // TODO: consider adding some degree of randomness here
+ delay = MIN_BOOT_COMPLETE_ACTION_DELAY;
+ }
+ if (mActionsList.isEmpty()) {
+ final int corePoolSize = 1;
+ mExecutorService = Executors.newScheduledThreadPool(corePoolSize);
+ IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
+ mContext.registerReceiver(mBroadcastReceiver, intentFilter);
+ }
+ mActionsList.add(Pair.create(action, delay));
+ }
+
+ }
+}
diff --git a/service/src/com/android/car/systeminterface/TimeInterface.java b/service/src/com/android/car/systeminterface/TimeInterface.java
new file mode 100644
index 0000000000..dea1153050
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/TimeInterface.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.systeminterface;
+
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
+
+import android.os.SystemClock;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Interface that abstracts time operations
+ */
+public interface TimeInterface {
+ public static final boolean INCLUDE_DEEP_SLEEP_TIME = true;
+ public static final boolean EXCLUDE_DEEP_SLEEP_TIME = false;
+
+ default long getUptime() {
+ return getUptime(EXCLUDE_DEEP_SLEEP_TIME);
+ }
+ default long getUptime(boolean includeDeepSleepTime) {
+ return includeDeepSleepTime ?
+ SystemClock.elapsedRealtime() :
+ SystemClock.uptimeMillis();
+ }
+
+ void scheduleAction(Runnable r, long delayMs);
+ void cancelAllActions();
+
+ class DefaultImpl implements TimeInterface {
+ private final ScheduledExecutorService mExecutor = newSingleThreadScheduledExecutor();
+
+ @Override
+ public void scheduleAction(Runnable r, long delayMs) {
+ mExecutor.scheduleAtFixedRate(r, delayMs, delayMs, TimeUnit.MILLISECONDS);
+ }
+
+ @Override
+ public void cancelAllActions() {
+ mExecutor.shutdownNow();
+ }
+ }
+}
diff --git a/service/src/com/android/car/systeminterface/WakeLockInterface.java b/service/src/com/android/car/systeminterface/WakeLockInterface.java
new file mode 100644
index 0000000000..c7a5f8e3e3
--- /dev/null
+++ b/service/src/com/android/car/systeminterface/WakeLockInterface.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.car.systeminterface;
+
+import android.content.Context;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import com.android.car.CarLog;
+
+/**
+ * Interface that abstracts wake lock operations
+ */
+public interface WakeLockInterface {
+ void releaseAllWakeLocks();
+ void switchToPartialWakeLock();
+ void switchToFullWakeLock();
+
+ class DefaultImpl implements WakeLockInterface {
+ private final WakeLock mPartialWakeLock;
+ private final WakeLock mFullWakeLock;
+
+ DefaultImpl(Context context) {
+ PowerManager powerManager =
+ (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mFullWakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK,
+ CarLog.TAG_POWER);
+ mPartialWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ CarLog.TAG_POWER);
+ }
+
+ @Override
+ public void switchToPartialWakeLock() {
+ if (!mPartialWakeLock.isHeld()) {
+ mPartialWakeLock.acquire();
+ }
+ if (mFullWakeLock.isHeld()) {
+ mFullWakeLock.release();
+ }
+ }
+
+ @Override
+ public void switchToFullWakeLock() {
+ if (!mFullWakeLock.isHeld()) {
+ mFullWakeLock.acquire();
+ }
+ if (mPartialWakeLock.isHeld()) {
+ mPartialWakeLock.release();
+ }
+ }
+
+ @Override
+ public void releaseAllWakeLocks() {
+ if (mPartialWakeLock.isHeld()) {
+ mPartialWakeLock.release();
+ }
+ if (mFullWakeLock.isHeld()) {
+ mFullWakeLock.release();
+ }
+ }
+ }
+}
diff --git a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/CarEmulator.java b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/CarEmulator.java
index 474b3416a0..064d06d5f6 100644
--- a/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/CarEmulator.java
+++ b/tests/EmbeddedKitchenSinkApp/src/com/google/android/car/kitchensink/CarEmulator.java
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2015 The Android Open Source Project
*
@@ -35,7 +36,7 @@ import android.os.SystemClock;
import android.util.SparseIntArray;
import com.android.car.ICarImpl;
-import com.android.car.SystemInterface;
+import com.android.car.systeminterface.SystemInterface;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal;
import com.android.car.vehiclehal.test.MockedVehicleHal.VehicleHalPropertyHandler;
@@ -66,7 +67,8 @@ public class CarEmulator {
private CarEmulator(Context context) {
mHalEmulator = new MockedVehicleHal();
ICarImpl carService = new ICarImpl(context, mHalEmulator,
- SystemInterface.createDefault(context), null /* error notifier */);
+ SystemInterface.Builder.defaultSystemInterface(context).build(),
+ null /* error notifier */);
mCar = new Car(context, carService, null /* Handler */);
}
diff --git a/tests/carservice_test/src/com/android/car/CarPowerManagementTest.java b/tests/carservice_test/src/com/android/car/CarPowerManagementTest.java
index 64d9b826a4..b0ac2e793b 100644
--- a/tests/carservice_test/src/com/android/car/CarPowerManagementTest.java
+++ b/tests/carservice_test/src/com/android/car/CarPowerManagementTest.java
@@ -26,6 +26,8 @@ import android.hardware.automotive.vehicle.V2_0.VehicleProperty;
import android.os.SystemClock;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.car.systeminterface.DisplayInterface;
+import com.android.car.systeminterface.SystemInterface;
import com.google.android.collect.Lists;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
@@ -40,6 +42,13 @@ import java.util.concurrent.TimeUnit;
public class CarPowerManagementTest extends MockedCarTestBase {
private final PowerStatePropertyHandler mPowerStateHandler = new PowerStatePropertyHandler();
+ private final MockDisplayInterface mMockDisplayInterface = new MockDisplayInterface();
+
+ @Override
+ protected synchronized SystemInterface.Builder getSystemInterfaceBuilder() {
+ SystemInterface.Builder builder = super.getSystemInterfaceBuilder();
+ return builder.withDisplayInterface(mMockDisplayInterface);
+ }
private void setupPowerPropertyAndStart(boolean allowSleep) {
addProperty(VehicleProperty.AP_POWER_STATE, mPowerStateHandler)
@@ -70,9 +79,9 @@ public class CarPowerManagementTest extends MockedCarTestBase {
assertBootComplete();
for (int i = 0; i < 2; i++) {
mPowerStateHandler.sendPowerState(VehicleApPowerState.ON_DISP_OFF, 0);
- waitForFakeDisplayState(false);
+ mMockDisplayInterface.waitForDisplayState(false);
mPowerStateHandler.sendPowerState(VehicleApPowerState.ON_FULL, 0);
- waitForFakeDisplayState(true);
+ mMockDisplayInterface.waitForDisplayState(true);
}
}
@@ -107,6 +116,33 @@ public class CarPowerManagementTest extends MockedCarTestBase {
assertEquals(0, first[1]);
}
+ private final class MockDisplayInterface implements DisplayInterface {
+ private boolean mDisplayOn = true;
+ private final Semaphore mDisplayStateWait = new Semaphore(0);
+
+ @Override
+ public synchronized void setDisplayState(boolean on) {
+ mDisplayOn = on;
+ mDisplayStateWait.release();
+ }
+
+ boolean waitForDisplayState(boolean expectedState)
+ throws Exception {
+ if (expectedState == mDisplayOn) {
+ return true;
+ }
+ mDisplayStateWait.tryAcquire(MockedCarTestBase.SHORT_WAIT_TIMEOUT_MS,
+ TimeUnit.MILLISECONDS);
+ return expectedState == mDisplayOn;
+ }
+
+ @Override
+ public void startDisplayStateMonitoring(CarPowerManagementService service) {}
+
+ @Override
+ public void stopDisplayStateMonitoring() {}
+ }
+
private class PowerStatePropertyHandler implements VehicleHalPropertyHandler {
private int mPowerState = VehicleApPowerState.ON_FULL;
diff --git a/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java b/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
index 7d7387cbf1..53e3abbd21 100644
--- a/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
+++ b/tests/carservice_test/src/com/android/car/CarStorageMonitoringTest.java
@@ -25,13 +25,22 @@ import android.car.storagemonitoring.WearEstimateChange;
import android.test.suitebuilder.annotation.MediumTest;
import android.util.JsonWriter;
import android.util.Log;
+import android.util.Pair;
import com.android.car.storagemonitoring.WearEstimateRecord;
import com.android.car.storagemonitoring.WearHistory;
import com.android.car.storagemonitoring.WearInformation;
+import com.android.car.storagemonitoring.WearInformationProvider;
+import com.android.car.systeminterface.StorageMonitoringInterface;
+import com.android.car.systeminterface.SystemInterface;
+import com.android.car.systeminterface.SystemStateInterface;
+import com.android.car.systeminterface.TimeInterface;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.time.Duration;
import java.time.Instant;
+import java.util.ArrayList;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -123,17 +132,29 @@ public class CarStorageMonitoringTest extends MockedCarTestBase {
.atTimestamp(Instant.ofEpochMilli(17000)).build())));
}};
+ private final MockSystemStateInterface mMockSystemStateInterface =
+ new MockSystemStateInterface();
+ private final MockStorageMonitoringInterface mMockStorageMonitoringInterface =
+ new MockStorageMonitoringInterface();
+
private CarStorageMonitoringManager mCarStorageMonitoringManager;
@Override
+ protected synchronized SystemInterface.Builder getSystemInterfaceBuilder() {
+ SystemInterface.Builder builder = super.getSystemInterfaceBuilder();
+ return builder.withSystemStateInterface(mMockSystemStateInterface)
+ .withStorageMonitoringInterface(mMockStorageMonitoringInterface)
+ .withTimeInterface(new MockTimeInterface());
+ }
+
+ @Override
protected synchronized void configureFakeSystemInterface() {
try {
final String testName = getName();
final WearData wearData = PER_TEST_WEAR_DATA.getOrDefault(testName, WearData.DEFAULT);
final WearHistory wearHistory = wearData.wearHistory;
- setFlashWearInformation(wearData.wearInformation);
- setUptimeProvider( (boolean b) -> 0 );
+ mMockStorageMonitoringInterface.setWearInformation(wearData.wearInformation);
if (wearHistory != null) {
File wearHistoryFile = new File(getFakeSystemInterface().getFilesDir(),
@@ -145,7 +166,7 @@ public class CarStorageMonitoringTest extends MockedCarTestBase {
if (wearData.uptime > 0) {
File uptimeFile = new File(getFakeSystemInterface().getFilesDir(),
- CarStorageMonitoringService.UPTIME_TRACKER_FILENAME);
+ CarStorageMonitoringService.UPTIME_TRACKER_FILENAME);
try (JsonWriter jsonWriter = new JsonWriter(new FileWriter(uptimeFile))) {
jsonWriter.beginObject();
jsonWriter.name("uptime").value(wearData.uptime);
@@ -156,13 +177,14 @@ public class CarStorageMonitoringTest extends MockedCarTestBase {
Log.e(TAG, "failed to configure fake system interface", e);
fail("failed to configure fake system interface instance");
}
+
}
@Override
protected void setUp() throws Exception {
super.setUp();
- fakeBootCompletedEvent();
+ mMockSystemStateInterface.executeBootCompletedActions();
mCarStorageMonitoringManager =
(CarStorageMonitoringManager) getCar().getCarManager(Car.STORAGE_MONITORING_SERVICE);
@@ -226,4 +248,59 @@ public class CarStorageMonitoringTest extends MockedCarTestBase {
public void testAcceptableWearEvent() throws Exception {
checkLastWearEvent(true);
}
+
+ static final class MockStorageMonitoringInterface implements StorageMonitoringInterface,
+ WearInformationProvider {
+ private WearInformation mWearInformation = null;
+
+ void setWearInformation(WearInformation wearInformation) {
+ mWearInformation = wearInformation;
+ }
+
+ @Override
+ public WearInformation load() {
+ return mWearInformation;
+ }
+
+ @Override
+ public WearInformationProvider[] getFlashWearInformationProviders() {
+ return new WearInformationProvider[] {this};
+ }
+ }
+
+ static final class MockTimeInterface implements TimeInterface {
+
+ @Override
+ public long getUptime(boolean includeDeepSleepTime) {
+ return 0;
+ }
+
+ @Override
+ public void scheduleAction(Runnable r, long delayMs) {}
+
+ @Override
+ public void cancelAllActions() {}
+ }
+
+ static final class MockSystemStateInterface implements SystemStateInterface {
+ private final List<Pair<Runnable, Duration>> mActionsList = new ArrayList<>();
+
+ @Override
+ public void shutdown() {}
+
+ @Override
+ public void enterDeepSleep(int wakeupTimeSec) {}
+
+ @Override
+ public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
+ mActionsList.add(Pair.create(action, delay));
+ mActionsList.sort(Comparator.comparing(d -> d.second));
+ }
+
+ void executeBootCompletedActions() {
+ for (Pair<Runnable, Duration> action : mActionsList) {
+ action.first.run();
+ }
+ }
+ }
}
diff --git a/tests/carservice_test/src/com/android/car/MockedCarTestBase.java b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
index 1437e27df1..e6ed401260 100644
--- a/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
+++ b/tests/carservice_test/src/com/android/car/MockedCarTestBase.java
@@ -33,12 +33,16 @@ import android.os.Looper;
import android.test.AndroidTestCase;
import android.util.Log;
-import android.util.Pair;
import android.util.SparseArray;
-import com.android.car.MockedCarTestBase.FakeSystemInterface.UptimeProvider;
-import com.android.car.storagemonitoring.WearInformation;
-import com.android.car.storagemonitoring.WearInformationProvider;
+import com.android.car.systeminterface.DisplayInterface;
+import com.android.car.systeminterface.IOInterface;
+import com.android.car.systeminterface.StorageMonitoringInterface;
+import com.android.car.systeminterface.SystemInterface;
+import com.android.car.systeminterface.SystemInterface.Builder;
+import com.android.car.systeminterface.SystemStateInterface;
+import com.android.car.systeminterface.TimeInterface;
+import com.android.car.systeminterface.WakeLockInterface;
import com.android.car.test.utils.TemporaryDirectory;
import com.android.car.vehiclehal.VehiclePropValueBuilder;
import com.android.car.vehiclehal.test.MockedVehicleHal;
@@ -50,14 +54,10 @@ import com.android.car.vehiclehal.test.VehiclePropConfigBuilder;
import java.io.File;
import java.io.IOException;
import java.time.Duration;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Comparator;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
/**
* Base class for testing with mocked vehicle HAL (=car).
@@ -72,7 +72,8 @@ public class MockedCarTestBase extends AndroidTestCase {
private android.car.Car mCar;
private ICarImpl mCarImpl;
private MockedVehicleHal mMockedVehicleHal;
- private FakeSystemInterface mFakeSystemInterface;
+ private SystemInterface mFakeSystemInterface;
+ private final MockIOInterface mMockIOInterface = new MockIOInterface();
private final Semaphore mWaitForMain = new Semaphore(0);
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
@@ -92,27 +93,24 @@ public class MockedCarTestBase extends AndroidTestCase {
return mMockedVehicleHal;
}
- protected synchronized FakeSystemInterface getFakeSystemInterface() {
+ protected synchronized SystemInterface getFakeSystemInterface() {
return mFakeSystemInterface;
}
protected synchronized void configureMockedHal() {
}
- protected synchronized void configureFakeSystemInterface() {
+ protected synchronized SystemInterface.Builder getSystemInterfaceBuilder() {
+ return Builder.newSystemInterface()
+ .withSystemStateInterface(new MockSystemStateInterface())
+ .withDisplayInterface(new MockDisplayInterface())
+ .withIOInterface(mMockIOInterface)
+ .withStorageMonitoringInterface(new MockStorageMonitoringInterface())
+ .withTimeInterface(new MockTimeInterface())
+ .withWakeLockInterface(new MockWakeLockInterface());
}
- protected synchronized void setFlashWearInformation(WearInformation wearInformation) {
- mFakeSystemInterface.mWearInformationProvider.setWearInformation(wearInformation);
- }
-
- protected synchronized void setUptimeProvider(UptimeProvider uptimeProvider) {
- mFakeSystemInterface.mUptimeProvider = uptimeProvider;
- }
-
- protected synchronized void fakeBootCompletedEvent() {
- mFakeSystemInterface.executeBootCompletedActions();
- }
+ protected synchronized void configureFakeSystemInterface() {}
@Override
protected synchronized void setUp() throws Exception {
@@ -127,7 +125,7 @@ public class MockedCarTestBase extends AndroidTestCase {
.build());
configureMockedHal();
- mFakeSystemInterface = new FakeSystemInterface();
+ mFakeSystemInterface = getSystemInterfaceBuilder().build();
configureFakeSystemInterface();
Context context = getCarServiceContext();
@@ -146,7 +144,7 @@ public class MockedCarTestBase extends AndroidTestCase {
mCar.disconnect();
mCarImpl.release();
- mFakeSystemInterface.tearDown();
+ mMockIOInterface.tearDown();
}
protected Context getCarServiceContext() throws NameNotFoundException {
@@ -233,10 +231,6 @@ public class MockedCarTestBase extends AndroidTestCase {
mWaitForMain.acquire();
}
- protected boolean waitForFakeDisplayState(boolean expectedState) throws Exception {
- return mFakeSystemInterface.waitForDisplayState(expectedState, SHORT_WAIT_TIMEOUT_MS);
- }
-
public static <T> void assertArrayEquals(T[] expected, T[] actual) {
if (!Arrays.equals(expected, actual)) {
fail("expected:<" + Arrays.toString(expected) +
@@ -293,76 +287,20 @@ public class MockedCarTestBase extends AndroidTestCase {
}
}
- static class FakeSystemInterface implements SystemInterface {
- interface UptimeProvider {
- long getUptime(boolean includeDeepSleepTime);
- }
-
- private boolean mDisplayOn = true;
- private final Semaphore mDisplayStateWait = new Semaphore(0);
- private final class FakeWearInformationProvider implements WearInformationProvider {
- private WearInformation mWearInformation = null;
- public void setWearInformation(WearInformation wearInformation) {
- mWearInformation = wearInformation;
- }
-
- @Override
- public WearInformation load() {
- return mWearInformation;
- }
- }
- private final FakeWearInformationProvider mWearInformationProvider =
- new FakeWearInformationProvider();
- private final List<Pair<Runnable, Duration>> mActionsList = new ArrayList<>();
-
- private TemporaryDirectory mFilesDir = null;
- private UptimeProvider mUptimeProvider = null;
-
- @Override
- public synchronized void setDisplayState(boolean on) {
- mDisplayOn = on;
- mDisplayStateWait.release();
- }
-
- boolean waitForDisplayState(boolean expectedState, long timeoutMs)
- throws Exception {
- if (expectedState == mDisplayOn) {
- return true;
- }
- mDisplayStateWait.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS);
- return expectedState == mDisplayOn;
- }
-
- @Override
- public void releaseAllWakeLocks() {
- }
-
- @Override
- public void shutdown() { }
-
- @Override
- public void enterDeepSleep(int wakeupTimeSec) { }
+ static final class MockDisplayInterface implements DisplayInterface {
@Override
- public void switchToPartialWakeLock() {
- }
+ public void setDisplayState(boolean on) {}
@Override
- public void switchToFullWakeLock() {
- }
+ public void startDisplayStateMonitoring(CarPowerManagementService service) {}
@Override
- public void startDisplayStateMonitoring(CarPowerManagementService service) {
- }
-
- @Override
- public void stopDisplayStateMonitoring() {
- }
+ public void stopDisplayStateMonitoring() {}
+ }
- @Override
- public WearInformationProvider[] getFlashWearInformationProviders() {
- return new WearInformationProvider[] { mWearInformationProvider };
- }
+ static final class MockIOInterface implements IOInterface {
+ private TemporaryDirectory mFilesDir = null;
@Override
public File getFilesDir() {
@@ -377,27 +315,7 @@ public class MockedCarTestBase extends AndroidTestCase {
return mFilesDir.getDirectory();
}
- @Override
- public void scheduleActionForBootCompleted(Runnable action, Duration delay) {
- mActionsList.add(Pair.create(action, delay));
- mActionsList.sort(Comparator.comparing(d -> d.second));
- }
-
- @Override
- public long getUptime(boolean includeDeepSleepTime) {
- if (mUptimeProvider != null) {
- return mUptimeProvider.getUptime(includeDeepSleepTime);
- }
- return SystemInterface.super.getUptime(includeDeepSleepTime);
- }
-
- void executeBootCompletedActions() {
- for (Pair<Runnable, Duration> action : mActionsList) {
- action.first.run();
- }
- }
-
- void tearDown() {
+ public void tearDown() {
if (mFilesDir != null) {
try {
mFilesDir.close();
@@ -407,4 +325,39 @@ public class MockedCarTestBase extends AndroidTestCase {
}
}
}
+
+ static final class MockStorageMonitoringInterface implements StorageMonitoringInterface {}
+
+ static final class MockSystemStateInterface implements SystemStateInterface {
+ @Override
+ public void shutdown() {}
+
+ @Override
+ public void enterDeepSleep(int wakeupTimeSec) {}
+
+ @Override
+ public void scheduleActionForBootCompleted(Runnable action, Duration delay) {}
+ }
+
+ static final class MockTimeInterface implements TimeInterface {
+
+ @Override
+ public void scheduleAction(Runnable r, long delayMs) {}
+
+ @Override
+ public void cancelAllActions() {}
+ }
+
+ static final class MockWakeLockInterface implements WakeLockInterface {
+
+ @Override
+ public void releaseAllWakeLocks() {}
+
+ @Override
+ public void switchToPartialWakeLock() {}
+
+ @Override
+ public void switchToFullWakeLock() {}
+ }
+
}
diff --git a/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java b/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java
index 2ce1186ee7..db240490af 100644
--- a/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/CarPowerManagementServiceTest.java
@@ -16,7 +16,6 @@
package com.android.car;
-import android.os.SystemClock;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
@@ -26,7 +25,11 @@ import com.android.car.CarPowerManagementService.PowerServiceEventListener;
import com.android.car.hal.PowerHalService;
import com.android.car.hal.PowerHalService.PowerState;
-import com.android.car.storagemonitoring.WearInformationProvider;
+import com.android.car.systeminterface.DisplayInterface;
+import com.android.car.systeminterface.IOInterface;
+import com.android.car.systeminterface.SystemInterface;
+import com.android.car.systeminterface.SystemStateInterface;
+import com.android.car.systeminterface.WakeLockInterface;
import com.android.car.test.utils.TemporaryDirectory;
import java.io.File;
import java.io.IOException;
@@ -40,8 +43,13 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
private static final long WAIT_TIMEOUT_MS = 2000;
private static final long WAIT_TIMEOUT_LONG_MS = 5000;
+ private final MockDisplayInterface mDisplayInterface = new MockDisplayInterface();
+ private final MockSystemStateInterface mSystemStateInterface = new MockSystemStateInterface();
+ private final MockWakeLockInterface mWakeLockInterface = new MockWakeLockInterface();
+ private final MockIOInterface mIOInterface = new MockIOInterface();
+
private MockedPowerHalService mPowerHal;
- private SystemInterfaceImpl mSystemInterface;
+ private SystemInterface mSystemInterface;
private CarPowerManagementService mService;
private final PowerEventListener mPowerEventListener = new PowerEventListener();
private PowerEventProcessingHandlerImpl mPowerEventProcessingHandler;
@@ -51,7 +59,11 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
super.setUp();
mPowerHal = new MockedPowerHalService(true /*isPowerStateSupported*/,
true /*isDeepSleepAllowed*/, true /*isTimedWakeupAllowed*/);
- mSystemInterface = new SystemInterfaceImpl();
+ mSystemInterface = SystemInterface.Builder.defaultSystemInterface(getContext())
+ .withDisplayInterface(mDisplayInterface)
+ .withSystemStateInterface(mSystemStateInterface)
+ .withWakeLockInterface(mWakeLockInterface)
+ .withIOInterface(mIOInterface).build();
}
@Override
@@ -60,9 +72,7 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
if (mService != null) {
mService.release();
}
- if (mSystemInterface != null) {
- mSystemInterface.tearDown();
- }
+ mIOInterface.tearDown();
}
public void testBootComplete() throws Exception {
@@ -84,15 +94,15 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
// it will call display on for initial state
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_ON_DISP_OFF, 0));
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
}
public void testDisplayOn() throws Exception {
// start with display off
mSystemInterface.setDisplayState(false);
- mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS);
+ mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS);
mService = new CarPowerManagementService(mPowerHal, mSystemInterface);
mService.init();
mService.registerPowerEventListener(mPowerEventListener);
@@ -102,7 +112,7 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
// display should be turned on as it started with off state.
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
}
public void testShutdown() throws Exception {
@@ -114,14 +124,14 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
PowerHalService.FLAG_SHUTDOWN_IMMEDIATELY));
assertStateReceived(PowerHalService.SET_SHUTDOWN_START, wakeupTime);
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
- mSystemInterface.waitForShutdown(WAIT_TIMEOUT_MS);
+ mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
}
public void testShutdownWithProcessing() throws Exception {
@@ -135,15 +145,15 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE, 0));
mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_SHUTDOWN_START,
WAIT_TIMEOUT_LONG_MS, wakeupTime);
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
- mSystemInterface.waitForShutdown(WAIT_TIMEOUT_MS);
+ mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
}
public void testSleepEntryAndWakeup() throws Exception {
@@ -155,14 +165,14 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
PowerHalService.FLAG_SHUTDOWN_PARAM_CAN_SLEEP));
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
assertStateReceived(PowerHalService.SET_DEEP_SLEEP_ENTRY, 0);
mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
- int wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
+ int wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
assertEquals(wakeupTime, wakeupTimeReceived);
assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
@@ -180,19 +190,19 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
PowerHalService.FLAG_SHUTDOWN_PARAM_CAN_SLEEP));
mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
WAIT_TIMEOUT_LONG_MS, 0);
mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
// set power on here without notification. PowerManager should check the state after sleep
// exit
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_ON_DISP_OFF, 0), false);
- int wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
+ int wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
assertEquals(wakeupTime, wakeupTimeReceived);
assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
@@ -210,35 +220,35 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
mService.registerPowerEventProcessingHandler(mPowerEventProcessingHandler);
assertStateReceived(MockedPowerHalService.SET_BOOT_COMPLETE, 0);
mPowerEventProcessingHandler.waitForPowerOn(WAIT_TIMEOUT_MS);
- assertTrue(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertTrue(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
mPowerHal.setCurrentPowerState(new PowerState(PowerHalService.STATE_SHUTDOWN_PREPARE,
PowerHalService.FLAG_SHUTDOWN_PARAM_CAN_SLEEP));
mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
- assertFalse(mSystemInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
+ assertFalse(mDisplayInterface.waitForDisplayStateChange(WAIT_TIMEOUT_MS));
assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
WAIT_TIMEOUT_LONG_MS, 0);
mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
- mSystemInterface.setWakeupCausedByTimer(true);
- int wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
+ mSystemStateInterface.setWakeupCausedByTimer(true);
+ int wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
assertEquals(wakeupTime, wakeupTimeReceived);
assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
mPowerEventListener.waitForSleepExit(WAIT_TIMEOUT_MS);
// second processing after wakeup
- assertFalse(mSystemInterface.getDisplayState());
+ assertFalse(mDisplayInterface.getDisplayState());
mPowerEventProcessingHandler.waitForPrepareShutdown(WAIT_TIMEOUT_MS);
assertStateReceivedForShutdownOrSleepWithPostpone(PowerHalService.SET_DEEP_SLEEP_ENTRY,
WAIT_TIMEOUT_LONG_MS, 0);
mPowerEventListener.waitForSleepEntry(WAIT_TIMEOUT_MS);
// PM will shutdown system as it was not woken-up due to timer and it is not power on.
- mSystemInterface.setWakeupCausedByTimer(false);
- wakeupTimeReceived = mSystemInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
+ mSystemStateInterface.setWakeupCausedByTimer(false);
+ wakeupTimeReceived = mSystemStateInterface.waitForSleepEntryAndWakeup(WAIT_TIMEOUT_MS);
assertEquals(wakeupTime, wakeupTimeReceived);
assertStateReceived(PowerHalService.SET_DEEP_SLEEP_EXIT, 0);
assertStateReceived(PowerHalService.SET_SHUTDOWN_START, wakeupTime);
mPowerEventListener.waitForShutdown(WAIT_TIMEOUT_MS);
- mSystemInterface.waitForShutdown(WAIT_TIMEOUT_MS);
- assertFalse(mSystemInterface.getDisplayState());
+ mSystemStateInterface.waitForShutdown(WAIT_TIMEOUT_MS);
+ assertFalse(mDisplayInterface.getDisplayState());
}
private void assertStateReceived(int expectedState, int expectedParam) throws Exception {
@@ -268,16 +278,9 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
}
}
- private static class SystemInterfaceImpl implements SystemInterface {
-
+ private static final class MockDisplayInterface implements DisplayInterface {
private boolean mDisplayOn = true;
private final Semaphore mDisplayStateWait = new Semaphore(0);
- private final Semaphore mShutdownWait = new Semaphore(0);
- private final Semaphore mSleepWait = new Semaphore(0);
- private final Semaphore mSleepExitWait = new Semaphore(0);
- private TemporaryDirectory mFilesDir;
- private int mWakeupTime;
- private boolean mWakeupCausedByTimer = false;
@Override
public synchronized void setDisplayState(boolean on) {
@@ -295,8 +298,18 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
}
@Override
- public void releaseAllWakeLocks() {
- }
+ public void startDisplayStateMonitoring(CarPowerManagementService service) {}
+
+ @Override
+ public void stopDisplayStateMonitoring() {}
+ }
+
+ private static final class MockSystemStateInterface implements SystemStateInterface {
+ private final Semaphore mShutdownWait = new Semaphore(0);
+ private final Semaphore mSleepWait = new Semaphore(0);
+ private final Semaphore mSleepExitWait = new Semaphore(0);
+ private int mWakeupTime;
+ private boolean mWakeupCausedByTimer = false;
@Override
public void shutdown() {
@@ -317,11 +330,6 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
}
}
- @Override
- public boolean isSystemSupportingDeepSleep() {
- return true;
- }
-
public int waitForSleepEntryAndWakeup(long timeoutMs) throws Exception {
waitForSemaphore(mSleepWait, timeoutMs);
mSleepExitWait.release();
@@ -329,26 +337,38 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
}
@Override
- public void switchToPartialWakeLock() {
- }
+ public void scheduleActionForBootCompleted(Runnable action, Duration delay) {}
@Override
- public void switchToFullWakeLock() {
+ public boolean isWakeupCausedByTimer() {
+ Log.i(TAG, "isWakeupCausedByTimer:" + mWakeupCausedByTimer);
+ return mWakeupCausedByTimer;
}
- @Override
- public void startDisplayStateMonitoring(CarPowerManagementService service) {
+ public synchronized void setWakeupCausedByTimer(boolean set) {
+ mWakeupCausedByTimer = set;
}
@Override
- public void stopDisplayStateMonitoring() {
+ public boolean isSystemSupportingDeepSleep() {
+ return true;
}
+ }
+
+ private static final class MockWakeLockInterface implements WakeLockInterface {
@Override
- public synchronized boolean isWakeupCausedByTimer() {
- Log.i(TAG, "isWakeupCausedByTimer:" + mWakeupCausedByTimer);
- return mWakeupCausedByTimer;
- }
+ public void releaseAllWakeLocks() {}
+
+ @Override
+ public void switchToPartialWakeLock() {}
+
+ @Override
+ public void switchToFullWakeLock() {}
+ }
+
+ private static final class MockIOInterface implements IOInterface {
+ private TemporaryDirectory mFilesDir;
@Override
public File getFilesDir() {
@@ -363,10 +383,7 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
return mFilesDir.getDirectory();
}
- @Override
- public void scheduleActionForBootCompleted(Runnable action, Duration delay) {}
-
- void tearDown() {
+ public void tearDown() {
if (mFilesDir != null) {
try {
mFilesDir.close();
@@ -375,10 +392,6 @@ public class CarPowerManagementServiceTest extends AndroidTestCase {
}
}
}
-
- public synchronized void setWakeupCausedByTimer(boolean set) {
- mWakeupCausedByTimer = set;
- }
}
private class PowerEventListener implements PowerServiceEventListener {
diff --git a/tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java b/tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java
index a5f12dd159..1b46825e0d 100644
--- a/tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java
+++ b/tests/carservice_unit_test/src/com/android/car/UptimeTrackerTest.java
@@ -16,6 +16,7 @@
package com.android.car;
import android.test.suitebuilder.annotation.MediumTest;
+import com.android.car.systeminterface.TimeInterface;
import com.android.car.test.utils.TemporaryFile;
import junit.framework.TestCase;
@@ -24,16 +25,16 @@ import junit.framework.TestCase;
public class UptimeTrackerTest extends TestCase {
static final String TAG = UptimeTrackerTest.class.getSimpleName();
- static final class TestTimingProvider implements UptimeTracker.TimingProvider {
+ static final class MockTimeInterface implements TimeInterface {
private long mCurrentTime = 0;
private Runnable mRunnable = null;
- TestTimingProvider incrementTime(long by) {
+ MockTimeInterface incrementTime(long by) {
mCurrentTime += by;
return this;
}
- TestTimingProvider tick() {
+ MockTimeInterface tick() {
if (mRunnable != null) {
mRunnable.run();
}
@@ -41,12 +42,12 @@ public class UptimeTrackerTest extends TestCase {
}
@Override
- public long getCurrentRealtime() {
+ public long getUptime(boolean includeDeepSleepTime) {
return mCurrentTime;
}
@Override
- public void schedule(Runnable r, long delay) {
+ public void scheduleAction(Runnable r, long delayMs) {
if (mRunnable != null) {
throw new IllegalStateException("task already scheduled");
}
@@ -54,7 +55,7 @@ public class UptimeTrackerTest extends TestCase {
}
@Override
- public void cancelAll() {
+ public void cancelAllActions() {
mRunnable = null;
}
}
@@ -62,80 +63,80 @@ public class UptimeTrackerTest extends TestCase {
private static final long SNAPSHOT_INTERVAL = 0; // actual time doesn't matter for this test
public void testUptimeTrackerFromCleanSlate() throws Exception {
- TestTimingProvider timingProvider = new TestTimingProvider();
+ MockTimeInterface timeInterface = new MockTimeInterface();
try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
- SNAPSHOT_INTERVAL, timingProvider);
+ SNAPSHOT_INTERVAL, timeInterface);
assertEquals(0, uptimeTracker.getTotalUptime());
- timingProvider.incrementTime(5000).tick();
+ timeInterface.incrementTime(5000).tick();
assertEquals(5000, uptimeTracker.getTotalUptime());
- timingProvider.tick();
+ timeInterface.tick();
assertEquals(5000, uptimeTracker.getTotalUptime());
- timingProvider.incrementTime(1000).tick();
+ timeInterface.incrementTime(1000).tick();
assertEquals(6000, uptimeTracker.getTotalUptime());
- timingProvider.incrementTime(400).tick();
+ timeInterface.incrementTime(400).tick();
assertEquals(6400, uptimeTracker.getTotalUptime());
}
}
public void testUptimeTrackerWithHistoricalState() throws Exception {
- TestTimingProvider timingProvider = new TestTimingProvider();
+ MockTimeInterface timeInterface = new MockTimeInterface();
try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
uptimeFile.write("{\"uptime\" : 5000}");
UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
- SNAPSHOT_INTERVAL, timingProvider);
+ SNAPSHOT_INTERVAL, timeInterface);
assertEquals(5000, uptimeTracker.getTotalUptime());
- timingProvider.incrementTime(5000).tick();
+ timeInterface.incrementTime(5000).tick();
assertEquals(10000, uptimeTracker.getTotalUptime());
- timingProvider.incrementTime(1000).tick();
+ timeInterface.incrementTime(1000).tick();
assertEquals(11000, uptimeTracker.getTotalUptime());
}
}
public void testUptimeTrackerAcrossHistoricalState() throws Exception {
- TestTimingProvider timingProvider = new TestTimingProvider();
+ MockTimeInterface timeInterface = new MockTimeInterface();
try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
uptimeFile.write("{\"uptime\" : 5000}");
UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
- SNAPSHOT_INTERVAL, timingProvider);
+ SNAPSHOT_INTERVAL, timeInterface);
assertEquals(5000, uptimeTracker.getTotalUptime());
- timingProvider.incrementTime(5000).tick();
+ timeInterface.incrementTime(5000).tick();
assertEquals(10000, uptimeTracker.getTotalUptime());
- timingProvider.incrementTime(500).tick();
+ timeInterface.incrementTime(500).tick();
uptimeTracker.onDestroy();
- timingProvider.cancelAll();
+ timeInterface.cancelAllActions();
uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
- SNAPSHOT_INTERVAL, timingProvider);
+ SNAPSHOT_INTERVAL, timeInterface);
- timingProvider.incrementTime(3000).tick();
+ timeInterface.incrementTime(3000).tick();
assertEquals(13500, uptimeTracker.getTotalUptime());
}
}
public void testUptimeTrackerShutdown() throws Exception {
- TestTimingProvider timingProvider = new TestTimingProvider();
+ MockTimeInterface timeInterface = new MockTimeInterface();
try (TemporaryFile uptimeFile = new TemporaryFile(TAG)) {
UptimeTracker uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
- SNAPSHOT_INTERVAL, timingProvider);
+ SNAPSHOT_INTERVAL, timeInterface);
- timingProvider.incrementTime(6000);
+ timeInterface.incrementTime(6000);
uptimeTracker.onDestroy();
- timingProvider.cancelAll();
+ timeInterface.cancelAllActions();
uptimeTracker = new UptimeTracker(uptimeFile.getFile(),
- SNAPSHOT_INTERVAL, timingProvider);
+ SNAPSHOT_INTERVAL, timeInterface);
assertEquals(6000, uptimeTracker.getTotalUptime());
}
}