summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2022-04-13 22:55:36 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-04-13 22:55:36 +0000
commitb89dd9bc78be5d34d768e2ea9853208e06de801a (patch)
tree7d6c165670a6de2c03082d3d2564a09419eca884
parent601853b582e700577fb70c5438db23995170ab2e (diff)
parent241f728308a869fb61069a5384b9665596cba622 (diff)
Merge "Play charging feedback on a background thread" into tm-dev
-rw-r--r--services/core/java/com/android/server/power/Notifier.java52
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java9
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/power/NotifierTest.java43
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java4
5 files changed, 89 insertions, 24 deletions
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index aede4b1e2f5d..685b744c8062 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -64,6 +64,8 @@ import com.android.server.policy.WindowManagerPolicy;
import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.PrintWriter;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Sends broadcasts about important power state changes.
@@ -133,6 +135,7 @@ public class Notifier {
private final DisplayManagerInternal mDisplayManagerInternal;
private final NotifierHandler mHandler;
+ private final Executor mBackgroundExecutor;
private final Intent mScreenOnIntent;
private final Intent mScreenOffIntent;
@@ -169,9 +172,12 @@ public class Notifier {
// True if a user activity message should be sent.
private boolean mUserActivityPending;
+ private final AtomicBoolean mIsPlayingChargingStartedFeedback = new AtomicBoolean(false);
+
public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
- FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) {
+ FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector,
+ Executor backgroundExecutor) {
mContext = context;
mBatteryStats = batteryStats;
mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -188,6 +194,7 @@ public class Notifier {
mVibrator = mContext.getSystemService(Vibrator.class);
mHandler = new NotifierHandler(looper);
+ mBackgroundExecutor = backgroundExecutor;
mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
mScreenOnIntent.addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND
@@ -824,25 +831,36 @@ public class Notifier {
return;
}
- // vibrate
- final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(),
- Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0;
- if (vibrate) {
- mVibrator.vibrate(CHARGING_VIBRATION_EFFECT, HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
+ if (!mIsPlayingChargingStartedFeedback.compareAndSet(false, true)) {
+ // there's already a charging started feedback Runnable scheduled to run on the
+ // background thread, so let's not execute another
+ return;
}
- // play sound
- final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
- wireless ? Settings.Global.WIRELESS_CHARGING_STARTED_SOUND
- : Settings.Global.CHARGING_STARTED_SOUND);
- final Uri soundUri = Uri.parse("file://" + soundPath);
- if (soundUri != null) {
- final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
- if (sfx != null) {
- sfx.setStreamType(AudioManager.STREAM_SYSTEM);
- sfx.play();
+ // vibrate & play sound on a background thread
+ mBackgroundExecutor.execute(() -> {
+ // vibrate
+ final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+ Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0;
+ if (vibrate) {
+ mVibrator.vibrate(CHARGING_VIBRATION_EFFECT,
+ HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
}
- }
+
+ // play sound
+ final String soundPath = Settings.Global.getString(mContext.getContentResolver(),
+ wireless ? Settings.Global.WIRELESS_CHARGING_STARTED_SOUND
+ : Settings.Global.CHARGING_STARTED_SOUND);
+ final Uri soundUri = Uri.parse("file://" + soundPath);
+ if (soundUri != null) {
+ final Ringtone sfx = RingtoneManager.getRingtone(mContext, soundUri);
+ if (sfx != null) {
+ sfx.setStreamType(AudioManager.STREAM_SYSTEM);
+ sfx.play();
+ }
+ }
+ mIsPlayingChargingStartedFeedback.set(false);
+ });
}
private void showWirelessChargingStarted(int batteryLevel, @UserIdInt int userId) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 6e78ecb83005..e0da0e8bdf35 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -140,6 +140,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
+import java.util.concurrent.Executor;
/**
* The power manager service is responsible for coordinating power management
@@ -905,10 +906,11 @@ public final class PowerManagerService extends SystemService
static class Injector {
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
- FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) {
+ FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector,
+ Executor backgroundExecutor) {
return new Notifier(
looper, context, batteryStats, suspendBlocker, policy, faceDownDetector,
- screenUndimDetector);
+ screenUndimDetector, backgroundExecutor);
}
SuspendBlocker createSuspendBlocker(PowerManagerService service, String name) {
@@ -1227,7 +1229,8 @@ public final class PowerManagerService extends SystemService
mBatteryStats = BatteryStatsService.getService();
mNotifier = mInjector.createNotifier(Looper.getMainLooper(), mContext, mBatteryStats,
mInjector.createSuspendBlocker(this, "PowerManagerService.Broadcasts"),
- mPolicy, mFaceDownDetector, mScreenUndimDetector);
+ mPolicy, mFaceDownDetector, mScreenUndimDetector,
+ BackgroundThread.getExecutor());
mPowerGroups.append(Display.DEFAULT_DISPLAY_GROUP,
new PowerGroup(WAKEFULNESS_AWAKE, mPowerGroupWakefulnessChangeListener,
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java b/services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java
index 9cf6c0325024..5c4657fb0027 100644
--- a/services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/power/PowerManagerServiceMockingTest.java
@@ -67,6 +67,8 @@ import com.android.server.power.batterysaver.BatterySaverStateMachine;
import com.android.server.power.batterysaver.BatterySavingStats;
import com.android.server.testutils.OffsettableClock;
+import java.util.concurrent.Executor;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -164,7 +166,8 @@ public class PowerManagerServiceMockingTest {
@Override
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
- FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) {
+ FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector,
+ Executor executor) {
return mNotifierMock;
}
diff --git a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
index a3223d6d2b7b..8f5f0e6fe131 100644
--- a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
@@ -16,6 +16,8 @@
package com.android.server.power;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
@@ -56,6 +58,8 @@ import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.concurrent.Executor;
+
/**
* Tests for {@link com.android.server.power.Notifier}
*/
@@ -79,6 +83,7 @@ public class NotifierTest {
private Context mContextSpy;
private Resources mResourcesSpy;
private TestLooper mTestLooper = new TestLooper();
+ private FakeExecutor mTestExecutor = new FakeExecutor();
private Notifier mNotifier;
@Before
@@ -107,6 +112,7 @@ public class NotifierTest {
// WHEN wired charging starts
mNotifier.onWiredChargingStarted(USER_ID);
mTestLooper.dispatchAll();
+ mTestExecutor.simulateAsyncExecutionOfLastCommand();
// THEN the device vibrates once
verify(mVibrator, times(1)).vibrate(any(), any(VibrationAttributes.class));
@@ -122,6 +128,7 @@ public class NotifierTest {
// WHEN wired charging starts
mNotifier.onWiredChargingStarted(USER_ID);
mTestLooper.dispatchAll();
+ mTestExecutor.simulateAsyncExecutionOfLastCommand();
// THEN the device doesn't vibrate
verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class));
@@ -137,6 +144,7 @@ public class NotifierTest {
// WHEN wireless charging starts
mNotifier.onWirelessChargingStarted(5, USER_ID);
mTestLooper.dispatchAll();
+ mTestExecutor.simulateAsyncExecutionOfLastCommand();
// THEN the device vibrates once
verify(mVibrator, times(1)).vibrate(any(), any(VibrationAttributes.class));
@@ -152,6 +160,7 @@ public class NotifierTest {
// WHEN wireless charging starts
mNotifier.onWirelessChargingStarted(5, USER_ID);
mTestLooper.dispatchAll();
+ mTestExecutor.simulateAsyncExecutionOfLastCommand();
// THEN the device doesn't vibrate
verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class));
@@ -170,6 +179,7 @@ public class NotifierTest {
// WHEN wired charging starts
mNotifier.onWiredChargingStarted(USER_ID);
mTestLooper.dispatchAll();
+ mTestExecutor.simulateAsyncExecutionOfLastCommand();
// THEN the device doesn't vibrate
verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class));
@@ -186,6 +196,7 @@ public class NotifierTest {
// WHEN wireless charging starts
mNotifier.onWirelessChargingStarted(5, USER_ID);
mTestLooper.dispatchAll();
+ mTestExecutor.simulateAsyncExecutionOfLastCommand();
// THEN the charging animation is triggered
verify(mStatusBarManagerInternal, times(1)).showChargingAnimation(5);
@@ -202,6 +213,7 @@ public class NotifierTest {
// WHEN wireless charging starts
mNotifier.onWirelessChargingStarted(5, USER_ID);
mTestLooper.dispatchAll();
+ mTestExecutor.simulateAsyncExecutionOfLastCommand();
// THEN the charging animation never gets called
verify(mStatusBarManagerInternal, never()).showChargingAnimation(anyInt());
@@ -211,7 +223,8 @@ public class NotifierTest {
@Override
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
- FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) {
+ FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector,
+ Executor backgroundExecutor) {
return mNotifierMock;
}
@@ -300,6 +313,32 @@ public class NotifierTest {
mInjector.createSuspendBlocker(mService, "testBlocker"),
null,
null,
- null);
+ null,
+ mTestExecutor);
+ }
+
+ private static class FakeExecutor implements Executor {
+ private Runnable mLastCommand;
+
+ @Override
+ public void execute(Runnable command) {
+ assertNull(mLastCommand);
+ assertNotNull(command);
+ mLastCommand = command;
+ }
+
+ public Runnable getAndResetLastCommand() {
+ Runnable toReturn = mLastCommand;
+ mLastCommand = null;
+ return toReturn;
+ }
+
+ public void simulateAsyncExecutionOfLastCommand() {
+ Runnable toRun = getAndResetLastCommand();
+ if (toRun != null) {
+ toRun.run();
+ }
+ }
}
+
}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index c9721dbecdb4..fbcad62988be 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -109,6 +109,7 @@ import org.mockito.stubbing.Answer;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -220,7 +221,8 @@ public class PowerManagerServiceTest {
@Override
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
- FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector) {
+ FaceDownDetector faceDownDetector, ScreenUndimDetector screenUndimDetector,
+ Executor executor) {
return mNotifierMock;
}