summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt1
-rw-r--r--api/system-current.txt1
-rw-r--r--api/test-current.txt1
-rw-r--r--core/java/android/service/dreams/DreamService.java26
-rw-r--r--core/java/android/view/Display.java29
-rw-r--r--core/java/android/view/SurfaceControl.java6
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java3
-rw-r--r--core/res/res/layout/notification_material_action.xml1
-rw-r--r--core/res/res/layout/notification_material_action_tombstone.xml1
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java15
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_emergency_carrier_area.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml1
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java8
-rw-r--r--services/core/java/com/android/server/BatteryService.java79
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java21
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java6
-rw-r--r--services/core/java/com/android/server/policy/BurnInProtectionHelper.java3
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java11
-rw-r--r--services/tests/servicestests/src/com/android/server/BatteryServiceTest.java60
-rw-r--r--telephony/java/android/telephony/ims/ImsServiceProxy.java13
-rw-r--r--telephony/java/android/telephony/ims/ImsServiceProxyCompat.java13
24 files changed, 223 insertions, 87 deletions
diff --git a/api/current.txt b/api/current.txt
index f01e9317d59c..12a3f07febf7 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -44559,6 +44559,7 @@ package android.view {
field public static final int STATE_DOZE_SUSPEND = 4; // 0x4
field public static final int STATE_OFF = 1; // 0x1
field public static final int STATE_ON = 2; // 0x2
+ field public static final int STATE_ON_SUSPEND = 6; // 0x6
field public static final int STATE_UNKNOWN = 0; // 0x0
field public static final int STATE_VR = 5; // 0x5
}
diff --git a/api/system-current.txt b/api/system-current.txt
index e7af921382d1..0b34782dbbba 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -48294,6 +48294,7 @@ package android.view {
field public static final int STATE_DOZE_SUSPEND = 4; // 0x4
field public static final int STATE_OFF = 1; // 0x1
field public static final int STATE_ON = 2; // 0x2
+ field public static final int STATE_ON_SUSPEND = 6; // 0x6
field public static final int STATE_UNKNOWN = 0; // 0x0
field public static final int STATE_VR = 5; // 0x5
}
diff --git a/api/test-current.txt b/api/test-current.txt
index 9f02bc5b3668..4eba70cce70f 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -45171,6 +45171,7 @@ package android.view {
field public static final int STATE_DOZE_SUSPEND = 4; // 0x4
field public static final int STATE_OFF = 1; // 0x1
field public static final int STATE_ON = 2; // 0x2
+ field public static final int STATE_ON_SUSPEND = 6; // 0x6
field public static final int STATE_UNKNOWN = 0; // 0x0
field public static final int STATE_VR = 5; // 0x5
}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index 6a15adeda9ab..2a245d046486 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -680,8 +680,8 @@ public class DreamService extends Service implements Window.Callback {
*
* @return The screen state to use while dozing, such as {@link Display#STATE_ON},
* {@link Display#STATE_DOZE}, {@link Display#STATE_DOZE_SUSPEND},
- * or {@link Display#STATE_OFF}, or {@link Display#STATE_UNKNOWN} for the default
- * behavior.
+ * {@link Display#STATE_ON_SUSPEND}, {@link Display#STATE_OFF}, or {@link Display#STATE_UNKNOWN}
+ * for the default behavior.
*
* @see #setDozeScreenState
* @hide For use by system UI components only.
@@ -700,12 +700,18 @@ public class DreamService extends Service implements Window.Callback {
* perform transitions between states while dozing to conserve power and
* achieve various effects.
* </p><p>
- * It is recommended that the state be set to {@link Display#STATE_DOZE_SUSPEND}
- * once the dream has completely finished drawing and before it releases its wakelock
- * to allow the display hardware to be fully suspended. While suspended, the
- * display will preserve its on-screen contents or hand off control to dedicated
- * doze hardware if the devices supports it. If the doze suspend state is
- * used, the dream must make sure to set the mode back
+ * Some devices will have dedicated hardware ("Sidekick") to animate
+ * the display content while the CPU sleeps. If the dream and the hardware support
+ * this, {@link Display#STATE_ON_SUSPEND} or {@link Display#STATE_DOZE_SUSPEND}
+ * will switch control to the Sidekick.
+ * </p><p>
+ * If not using Sidekick, it is recommended that the state be set to
+ * {@link Display#STATE_DOZE_SUSPEND} once the dream has completely
+ * finished drawing and before it releases its wakelock
+ * to allow the display hardware to be fully suspended. While suspended,
+ * the display will preserve its on-screen contents.
+ * </p><p>
+ * If the doze suspend state is used, the dream must make sure to set the mode back
* to {@link Display#STATE_DOZE} or {@link Display#STATE_ON} before drawing again
* since the display updates may be ignored and not seen by the user otherwise.
* </p><p>
@@ -716,8 +722,8 @@ public class DreamService extends Service implements Window.Callback {
*
* @param state The screen state to use while dozing, such as {@link Display#STATE_ON},
* {@link Display#STATE_DOZE}, {@link Display#STATE_DOZE_SUSPEND},
- * or {@link Display#STATE_OFF}, or {@link Display#STATE_UNKNOWN} for the default
- * behavior.
+ * {@link Display#STATE_ON_SUSPEND}, {@link Display#STATE_OFF}, or {@link Display#STATE_UNKNOWN}
+ * for the default behavior.
*
* @hide For use by system UI components only.
*/
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index e7c3f92da830..6a44cdb9ee57 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -294,11 +294,10 @@ public final class Display {
/**
* Display state: The display is dozing in a suspended low power state; it is still
- * on but is optimized for showing static system-provided content while the device
- * is non-interactive. This mode may be used to conserve even more power by allowing
- * the hardware to stop applying frame buffer updates from the graphics subsystem or
- * to take over the display and manage it autonomously to implement low power always-on
- * display functionality.
+ * on but the CPU is not updating it. This may be used in one of two ways: to show
+ * static system-provided content while the device is non-interactive, or to allow
+ * a "Sidekick" compute resource to update the display. For this reason, the
+ * CPU must not control the display in this mode.
*
* @see #getState
* @see android.os.PowerManager#isInteractive
@@ -313,6 +312,18 @@ public final class Display {
*/
public static final int STATE_VR = 5;
+ /**
+ * Display state: The display is in a suspended full power state; it is still
+ * on but the CPU is not updating it. This may be used in one of two ways: to show
+ * static system-provided content while the device is non-interactive, or to allow
+ * a "Sidekick" compute resource to update the display. For this reason, the
+ * CPU must not control the display in this mode.
+ *
+ * @see #getState
+ * @see android.os.PowerManager#isInteractive
+ */
+ public static final int STATE_ON_SUSPEND = 6;
+
/* The color mode constants defined below must be kept in sync with the ones in
* system/core/include/system/graphics-base.h */
@@ -994,7 +1005,7 @@ public final class Display {
* Gets the state of the display, such as whether it is on or off.
*
* @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON},
- * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, or
+ * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, {@link #STATE_ON_SUSPEND}, or
* {@link #STATE_UNKNOWN}.
*/
public int getState() {
@@ -1113,6 +1124,8 @@ public final class Display {
return "DOZE_SUSPEND";
case STATE_VR:
return "VR";
+ case STATE_ON_SUSPEND:
+ return "ON_SUSPEND";
default:
return Integer.toString(state);
}
@@ -1120,11 +1133,11 @@ public final class Display {
/**
* Returns true if display updates may be suspended while in the specified
- * display power state.
+ * display power state. In SUSPEND states, updates are absolutely forbidden.
* @hide
*/
public static boolean isSuspendedState(int state) {
- return state == STATE_OFF || state == STATE_DOZE_SUSPEND;
+ return state == STATE_OFF || state == STATE_DOZE_SUSPEND || state == STATE_ON_SUSPEND;
}
/**
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index cd8414791acb..5641009c1320 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -295,6 +295,12 @@ public class SurfaceControl {
public static final int POWER_MODE_DOZE_SUSPEND = 3;
/**
+ * Display power mode on: used while putting the screen into a suspended
+ * full power mode. Use only with {@link SurfaceControl#setDisplayPowerMode}.
+ */
+ public static final int POWER_MODE_ON_SUSPEND = 4;
+
+ /**
* A value for windowType used to indicate that the window should be omitted from screenshots
* and display mirroring. A temporary workaround until we express such things with
* the hierarchy.
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 0535ebeb7615..2ec64a5ecdc4 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -9626,7 +9626,8 @@ public class BatteryStatsImpl extends BatteryStats {
}
public boolean isScreenOn(int state) {
- return state == Display.STATE_ON || state == Display.STATE_VR;
+ return state == Display.STATE_ON || state == Display.STATE_VR
+ || state == Display.STATE_ON_SUSPEND;
}
public boolean isScreenOff(int state) {
diff --git a/core/res/res/layout/notification_material_action.xml b/core/res/res/layout/notification_material_action.xml
index 548ee0561698..3c9f6eecc7d6 100644
--- a/core/res/res/layout/notification_material_action.xml
+++ b/core/res/res/layout/notification_material_action.xml
@@ -25,6 +25,7 @@
android:layout_marginStart="4dp"
android:textColor="@color/notification_default_color"
android:singleLine="true"
+ android:textAlignment="viewStart"
android:ellipsize="end"
android:background="@drawable/notification_material_action_background"
/>
diff --git a/core/res/res/layout/notification_material_action_tombstone.xml b/core/res/res/layout/notification_material_action_tombstone.xml
index 1f59ea02025b..817f298f0c6f 100644
--- a/core/res/res/layout/notification_material_action_tombstone.xml
+++ b/core/res/res/layout/notification_material_action_tombstone.xml
@@ -26,6 +26,7 @@
android:textColor="#555555"
android:singleLine="true"
android:ellipsize="end"
+ android:textAlignment="viewStart"
android:alpha="0.5"
android:enabled="false"
android:background="@drawable/notification_material_action_background"
diff --git a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
index 1cb255bf8973..a8262c8cc4c8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.XmlResourceParser;
import android.icu.text.TimeZoneFormat;
import android.icu.text.TimeZoneNames;
+import android.support.annotation.VisibleForTesting;
import android.support.v4.text.BidiFormatter;
import android.support.v4.text.TextDirectionHeuristicsCompat;
import android.text.SpannableString;
@@ -32,6 +33,8 @@ import android.view.View;
import com.android.settingslib.R;
+import libcore.util.TimeZoneFinder;
+
import org.xmlpull.v1.XmlPullParserException;
import java.util.ArrayList;
@@ -43,7 +46,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
-import libcore.util.TimeZoneFinder;
/**
* ZoneGetter is the utility class to get time zone and zone list, and both of them have display
@@ -350,7 +352,8 @@ public class ZoneGetter {
return gmtText;
}
- private static final class ZoneGetterData {
+ @VisibleForTesting
+ public static final class ZoneGetterData {
public final String[] olsonIdsToDisplay;
public final CharSequence[] gmtOffsetTexts;
public final TimeZone[] timeZones;
@@ -377,9 +380,13 @@ public class ZoneGetter {
}
// Create a lookup of local zone IDs.
- List<String> zoneIds =
- TimeZoneFinder.getInstance().lookupTimeZoneIdsByCountry(locale.getCountry());
+ final List<String> zoneIds = lookupTimeZoneIdsByCountry(locale.getCountry());
localZoneIds = new HashSet<>(zoneIds);
}
+
+ @VisibleForTesting
+ public List<String> lookupTimeZoneIdsByCountry(String country) {
+ return TimeZoneFinder.getInstance().lookupTimeZoneIdsByCountry(country);
+ }
}
}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_emergency_carrier_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_emergency_carrier_area.xml
index 39cba742d9b5..3018a022e763 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_emergency_carrier_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_emergency_carrier_area.xml
@@ -33,8 +33,10 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Keyguard.TextView"
+ android:singleLine="true"
android:ellipsize="marquee"
android:visibility="gone"
+ android:gravity="center"
androidprv:allCaps="@bool/kg_use_all_caps" />
<com.android.keyguard.EmergencyButton
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index 97c896591eb2..947f27deb84e 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -32,6 +32,7 @@
android:id="@+id/keyguard_sim"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:tint="@color/background_protected"
android:src="@drawable/ic_lockscreen_sim"/>
<include layout="@layout/keyguard_message_area"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index d4c5d7474aed..6f270b405c11 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -33,6 +33,7 @@
android:id="@+id/keyguard_sim"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:tint="@color/background_protected"
android:src="@drawable/ic_lockscreen_sim"/>
<include layout="@layout/keyguard_message_area"
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
index 5d0a9d70e99d..03b0082b96e7 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenStatePreventingAdapter.java
@@ -33,8 +33,10 @@ public class DozeScreenStatePreventingAdapter extends DozeMachine.Service.Delega
@Override
public void setDozeScreenState(int state) {
- if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) {
+ if (state == Display.STATE_DOZE) {
state = Display.STATE_ON;
+ } else if (state == Display.STATE_DOZE_SUSPEND) {
+ state = Display.STATE_ON_SUSPEND;
}
super.setDozeScreenState(state);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
index 720e9f0a62d5..a17a95f6543d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStatePreventingAdapterTest.java
@@ -70,7 +70,7 @@ public class DozeScreenStatePreventingAdapterTest extends SysuiTestCase {
@Test
public void forwards_setDozeScreenState_doze_suspend() throws Exception {
mWrapper.setDozeScreenState(Display.STATE_DOZE_SUSPEND);
- verify(mInner).setDozeScreenState(Display.STATE_ON);
+ verify(mInner).setDozeScreenState(Display.STATE_ON_SUSPEND);
}
@Test
@@ -95,4 +95,4 @@ public class DozeScreenStatePreventingAdapterTest extends SysuiTestCase {
assertSame(mInner, DozeScreenStatePreventingAdapter.wrapIfNeeded(mInner, params));
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java
index d78e739fce00..ed935619b2f6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSuspendScreenStatePreventingAdapterTest.java
@@ -74,6 +74,12 @@ public class DozeSuspendScreenStatePreventingAdapterTest extends SysuiTestCase {
}
@Test
+ public void forwards_setDozeScreenState_on_suspend() throws Exception {
+ mWrapper.setDozeScreenState(Display.STATE_ON_SUSPEND);
+ verify(mInner).setDozeScreenState(Display.STATE_ON_SUSPEND);
+ }
+
+ @Test
public void forwards_requestWakeUp() throws Exception {
mWrapper.requestWakeUp();
verify(mInner).requestWakeUp();
@@ -95,4 +101,4 @@ public class DozeSuspendScreenStatePreventingAdapterTest extends SysuiTestCase {
assertSame(mInner, DozeSuspendScreenStatePreventingAdapter.wrapIfNeeded(mInner, params));
}
-} \ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index 1b61866f81b6..7a60a5d1e11d 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -49,6 +49,7 @@ import android.os.BatteryProperty;
import android.os.Binder;
import android.os.FileUtils;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBatteryPropertiesListener;
import android.os.IBatteryPropertiesRegistrar;
import android.os.IBinder;
@@ -75,6 +76,7 @@ import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -176,6 +178,7 @@ public final class BatteryService extends SystemService {
private HealthServiceWrapper mHealthServiceWrapper;
private HealthHalCallback mHealthHalCallback;
private BatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
+ private HandlerThread mHandlerThread;
public BatteryService(Context context) {
super(context);
@@ -1195,14 +1198,13 @@ public final class BatteryService extends SystemService {
Arrays.asList(INSTANCE_VENDOR, INSTANCE_HEALTHD);
private final IServiceNotification mNotification = new Notification();
+ private final HandlerThread mHandlerThread = new HandlerThread("HealthServiceRefresh");
// These variables are fixed after init.
private Callback mCallback;
private IHealthSupplier mHealthSupplier;
private String mInstanceName;
- private final Object mLastServiceSetLock = new Object();
// Last IHealth service received.
- // set must be also be guarded with mLastServiceSetLock to ensure ordering.
private final AtomicReference<IHealth> mLastService = new AtomicReference<>();
/**
@@ -1220,6 +1222,10 @@ public final class BatteryService extends SystemService {
* Start monitoring registration of new IHealth services. Only instances that are in
* {@code sAllInstances} and in device / framework manifest are used. This function should
* only be called once.
+ *
+ * mCallback.onRegistration() is called synchronously (aka in init thread) before
+ * this method returns.
+ *
* @throws RemoteException transaction error when talking to IServiceManager
* @throws NoSuchElementException if one of the following cases:
* - No service manager;
@@ -1240,40 +1246,48 @@ public final class BatteryService extends SystemService {
mCallback = callback;
mHealthSupplier = healthSupplier;
- traceBegin("HealthInitGetManager");
- try {
- manager = managerSupplier.get();
- } finally {
- traceEnd();
- }
+ // Initialize mLastService and call callback for the first time (in init thread)
+ IHealth newService = null;
for (String name : sAllInstances) {
- traceBegin("HealthInitGetTransport_" + name);
+ traceBegin("HealthInitGetService_" + name);
try {
- if (manager.getTransport(IHealth.kInterfaceName, name) !=
- IServiceManager.Transport.EMPTY) {
- mInstanceName = name;
- break;
- }
+ newService = healthSupplier.get(name);
+ } catch (NoSuchElementException ex) {
+ /* ignored, handled below */
} finally {
traceEnd();
}
+ if (newService != null) {
+ mInstanceName = name;
+ mLastService.set(newService);
+ break;
+ }
}
- if (mInstanceName == null) {
+ if (mInstanceName == null || newService == null) {
throw new NoSuchElementException(String.format(
"No IHealth service instance among %s is available. Perhaps no permission?",
sAllInstances.toString()));
}
+ mCallback.onRegistration(null, newService, mInstanceName);
+ // Register for future service registrations
traceBegin("HealthInitRegisterNotification");
+ mHandlerThread.start();
try {
- manager.registerForNotifications(IHealth.kInterfaceName, mInstanceName, mNotification);
+ managerSupplier.get().registerForNotifications(
+ IHealth.kInterfaceName, mInstanceName, mNotification);
} finally {
traceEnd();
}
Slog.i(TAG, "health: HealthServiceWrapper listening to instance " + mInstanceName);
}
+ @VisibleForTesting
+ HandlerThread getHandlerThread() {
+ return mHandlerThread;
+ }
+
interface Callback {
/**
* This function is invoked asynchronously when a new and related IServiceNotification
@@ -1302,7 +1316,7 @@ public final class BatteryService extends SystemService {
*/
interface IHealthSupplier {
default IHealth get(String name) throws NoSuchElementException, RemoteException {
- return IHealth.getService(name);
+ return IHealth.getService(name, true /* retry */);
}
}
@@ -1312,18 +1326,27 @@ public final class BatteryService extends SystemService {
boolean preexisting) {
if (!IHealth.kInterfaceName.equals(interfaceName)) return;
if (!mInstanceName.equals(instanceName)) return;
- try {
- // ensures the order of multiple onRegistration on different threads.
- synchronized (mLastServiceSetLock) {
- IHealth newService = mHealthSupplier.get(instanceName);
- IHealth oldService = mLastService.getAndSet(newService);
- Slog.i(TAG, "health: new instance registered " + instanceName);
- mCallback.onRegistration(oldService, newService, instanceName);
+
+ // This runnable only runs on mHandlerThread and ordering is ensured, hence
+ // no locking is needed inside the runnable.
+ mHandlerThread.getThreadHandler().post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ IHealth newService = mHealthSupplier.get(mInstanceName);
+ IHealth oldService = mLastService.getAndSet(newService);
+
+ // preexisting may be inaccurate (race). Check for equality here.
+ if (Objects.equals(newService, oldService)) return;
+
+ Slog.i(TAG, "health: new instance registered " + mInstanceName);
+ mCallback.onRegistration(oldService, newService, mInstanceName);
+ } catch (NoSuchElementException | RemoteException ex) {
+ Slog.e(TAG, "health: Cannot get instance '" + mInstanceName
+ + "': " + ex.getMessage() + ". Perhaps no permission?");
+ }
}
- } catch (NoSuchElementException | RemoteException ex) {
- Slog.e(TAG, "health: Cannot get instance '" + instanceName + "': " +
- ex.getMessage() + ". Perhaps no permission?");
- }
+ });
}
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index f930b523e626..600bc42e970c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1120,6 +1120,27 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Dismiss the black surface without fanfare.
mPowerState.setColorFadeLevel(1.0f);
mPowerState.dismissColorFade();
+ } else if (target == Display.STATE_ON_SUSPEND) {
+ // Want screen full-power and suspended.
+ // Wait for brightness animation to complete beforehand unless already
+ // suspended because we may not be able to change it after suspension.
+ if (mScreenBrightnessRampAnimator.isAnimating()
+ && mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
+ return;
+ }
+
+ // If not already suspending, temporarily set the state to on until the
+ // screen on is unblocked, then suspend.
+ if (mPowerState.getScreenState() != Display.STATE_ON_SUSPEND) {
+ if (!setScreenState(Display.STATE_ON)) {
+ return;
+ }
+ setScreenState(Display.STATE_ON_SUSPEND);
+ }
+
+ // Dismiss the black surface without fanfare.
+ mPowerState.setColorFadeLevel(1.0f);
+ mPowerState.dismissColorFade();
} else {
// Want screen off.
mPendingScreenOff = true;
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 9fdc35f5c6b6..eb9ff589d5f6 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -148,6 +148,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
return SurfaceControl.POWER_MODE_DOZE;
case Display.STATE_DOZE_SUSPEND:
return SurfaceControl.POWER_MODE_DOZE_SUSPEND;
+ case Display.STATE_ON_SUSPEND:
+ return SurfaceControl.POWER_MODE_ON_SUSPEND;
default:
return SurfaceControl.POWER_MODE_NORMAL;
}
@@ -470,6 +472,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
|| oldState == Display.STATE_DOZE_SUSPEND) {
setDisplayState(Display.STATE_DOZE);
currentState = Display.STATE_DOZE;
+ } else if (state == Display.STATE_ON_SUSPEND
+ || oldState == Display.STATE_ON_SUSPEND) {
+ setDisplayState(Display.STATE_ON);
+ currentState = Display.STATE_ON;
} else {
return; // old state and new state is off
}
diff --git a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
index 92729dc08b63..6886985eec50 100644
--- a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
+++ b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java
@@ -253,7 +253,8 @@ public class BurnInProtectionHelper implements DisplayManager.DisplayListener,
public void onDisplayChanged(int displayId) {
if (displayId == mDisplay.getDisplayId()) {
if (mDisplay.getState() == Display.STATE_DOZE
- || mDisplay.getState() == Display.STATE_DOZE_SUSPEND) {
+ || mDisplay.getState() == Display.STATE_DOZE_SUSPEND
+ || mDisplay.getState() == Display.STATE_ON_SUSPEND) {
startBurnInProtection();
} else {
cancelBurnInProtection();
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 8f23cf829366..416a60665a7f 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2364,9 +2364,13 @@ public final class PowerManagerService extends SystemService
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
- if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND
- && (mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
- mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
+ if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
+ if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND) {
+ mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
+ }
+ if (mDisplayPowerRequest.dozeScreenState == Display.STATE_ON_SUSPEND) {
+ mDisplayPowerRequest.dozeScreenState = Display.STATE_ON;
+ }
}
mDisplayPowerRequest.dozeScreenBrightness =
mDozeScreenBrightnessOverrideFromDreamManager;
@@ -4676,6 +4680,7 @@ public final class PowerManagerService extends SystemService
case Display.STATE_OFF:
case Display.STATE_DOZE:
case Display.STATE_DOZE_SUSPEND:
+ case Display.STATE_ON_SUSPEND:
case Display.STATE_ON:
case Display.STATE_VR:
break;
diff --git a/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java b/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java
index daaad7a8c0b6..106f9e8c2705 100644
--- a/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/BatteryServiceTest.java
@@ -36,12 +36,14 @@ import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
+import org.mockito.invocation.InvocationOnMock;
public class BatteryServiceTest extends AndroidTestCase {
@Mock IServiceManager mMockedManager;
@Mock IHealth mMockedHal;
+ @Mock IHealth mMockedHal2;
@Mock BatteryService.HealthServiceWrapper.Callback mCallback;
@Mock BatteryService.HealthServiceWrapper.IServiceManagerSupplier mManagerSupplier;
@@ -56,6 +58,12 @@ public class BatteryServiceTest extends AndroidTestCase {
MockitoAnnotations.initMocks(this);
}
+ @Override
+ public void tearDown() {
+ if (mWrapper != null)
+ mWrapper.getHandlerThread().quitSafely();
+ }
+
public static <T> ArgumentMatcher<T> isOneOf(Collection<T> collection) {
return new ArgumentMatcher<T>() {
@Override public boolean matches(T e) {
@@ -70,42 +78,64 @@ public class BatteryServiceTest extends AndroidTestCase {
private void initForInstances(String... instanceNamesArr) throws Exception {
final Collection<String> instanceNames = Arrays.asList(instanceNamesArr);
doAnswer((invocation) -> {
- Slog.e("BatteryServiceTest", "health: onRegistration " + invocation.getArguments()[2]);
- ((IServiceNotification)invocation.getArguments()[2]).onRegistration(
- IHealth.kInterfaceName,
- (String)invocation.getArguments()[1],
- true /* preexisting */);
+ // technically, preexisting is ignored by
+ // BatteryService.HealthServiceWrapper.Notification, but still call it correctly.
+ sendNotification(invocation, true);
+ sendNotification(invocation, true);
+ sendNotification(invocation, false);
return null;
}).when(mMockedManager).registerForNotifications(
eq(IHealth.kInterfaceName),
argThat(isOneOf(instanceNames)),
any(IServiceNotification.class));
- doReturn(mMockedHal).when(mMockedManager)
- .get(eq(IHealth.kInterfaceName), argThat(isOneOf(instanceNames)));
-
- doReturn(IServiceManager.Transport.HWBINDER).when(mMockedManager)
- .getTransport(eq(IHealth.kInterfaceName), argThat(isOneOf(instanceNames)));
-
doReturn(mMockedManager).when(mManagerSupplier).get();
- doReturn(mMockedHal).when(mHealthServiceSupplier)
- .get(argThat(isOneOf(instanceNames)));
+ doReturn(mMockedHal) // init calls this
+ .doReturn(mMockedHal) // notification 1
+ .doReturn(mMockedHal) // notification 2
+ .doReturn(mMockedHal2) // notification 3
+ .doThrow(new RuntimeException("Should not call getService for more than 4 times"))
+ .when(mHealthServiceSupplier).get(argThat(isOneOf(instanceNames)));
mWrapper = new BatteryService.HealthServiceWrapper();
}
+ private void waitHandlerThreadFinish() throws Exception {
+ for (int i = 0; i < 5; i++) {
+ if (!mWrapper.getHandlerThread().getThreadHandler().hasMessagesOrCallbacks()) {
+ return;
+ }
+ Thread.sleep(300);
+ }
+ assertFalse(mWrapper.getHandlerThread().getThreadHandler().hasMessagesOrCallbacks());
+ }
+
+ private static void sendNotification(InvocationOnMock invocation, boolean preexisting)
+ throws Exception {
+ ((IServiceNotification)invocation.getArguments()[2]).onRegistration(
+ IHealth.kInterfaceName,
+ (String)invocation.getArguments()[1],
+ preexisting);
+ }
+
@SmallTest
public void testWrapPreferVendor() throws Exception {
initForInstances(VENDOR, HEALTHD);
mWrapper.init(mCallback, mManagerSupplier, mHealthServiceSupplier);
- verify(mCallback).onRegistration(same(null), same(mMockedHal), eq(VENDOR));
+ waitHandlerThreadFinish();
+ verify(mCallback, times(1)).onRegistration(same(null), same(mMockedHal), eq(VENDOR));
+ verify(mCallback, never()).onRegistration(same(mMockedHal), same(mMockedHal), anyString());
+ verify(mCallback, times(1)).onRegistration(same(mMockedHal), same(mMockedHal2), eq(VENDOR));
}
@SmallTest
public void testUseHealthd() throws Exception {
initForInstances(HEALTHD);
mWrapper.init(mCallback, mManagerSupplier, mHealthServiceSupplier);
- verify(mCallback).onRegistration(same(null), same(mMockedHal), eq(HEALTHD));
+ waitHandlerThreadFinish();
+ verify(mCallback, times(1)).onRegistration(same(null), same(mMockedHal), eq(HEALTHD));
+ verify(mCallback, never()).onRegistration(same(mMockedHal), same(mMockedHal), anyString());
+ verify(mCallback, times(1)).onRegistration(same(mMockedHal), same(mMockedHal2), eq(HEALTHD));
}
@SmallTest
diff --git a/telephony/java/android/telephony/ims/ImsServiceProxy.java b/telephony/java/android/telephony/ims/ImsServiceProxy.java
index 038e295d8822..31d3db44d6fe 100644
--- a/telephony/java/android/telephony/ims/ImsServiceProxy.java
+++ b/telephony/java/android/telephony/ims/ImsServiceProxy.java
@@ -305,19 +305,6 @@ public class ImsServiceProxy extends ImsServiceProxyCompat implements IRcsFeatur
mStatusCallback = c;
}
- /**
- * @return Returns true if the ImsService is ready to take commands, false otherwise. If this
- * method returns false, it doesn't mean that the Binder connection is not available (use
- * {@link #isBinderReady()} to check that), but that the ImsService is not accepting commands
- * at this time.
- *
- * For example, for DSDS devices, only one slot can be {@link ImsFeature#STATE_READY} to take
- * commands at a time, so the other slot must stay at {@link ImsFeature#STATE_NOT_AVAILABLE}.
- */
- public boolean isBinderReady() {
- return isBinderAlive() && getFeatureStatus() == ImsFeature.STATE_READY;
- }
-
@Override
public boolean isBinderAlive() {
return mIsAvailable && mBinder != null && mBinder.isBinderAlive();
diff --git a/telephony/java/android/telephony/ims/ImsServiceProxyCompat.java b/telephony/java/android/telephony/ims/ImsServiceProxyCompat.java
index bbd5f0279913..7ec92296448f 100644
--- a/telephony/java/android/telephony/ims/ImsServiceProxyCompat.java
+++ b/telephony/java/android/telephony/ims/ImsServiceProxyCompat.java
@@ -171,6 +171,19 @@ public class ImsServiceProxyCompat implements IMMTelFeature {
return mBinder != null && mBinder.isBinderAlive();
}
+ /**
+ * @return Returns true if the ImsService is ready to take commands, false otherwise. If this
+ * method returns false, it doesn't mean that the Binder connection is not available (use
+ * {@link #isBinderReady()} to check that), but that the ImsService is not accepting commands
+ * at this time.
+ *
+ * For example, for DSDS devices, only one slot can be {@link ImsFeature#STATE_READY} to take
+ * commands at a time, so the other slot must stay at {@link ImsFeature#STATE_NOT_AVAILABLE}.
+ */
+ public boolean isBinderReady() {
+ return isBinderAlive() && getFeatureStatus() == ImsFeature.STATE_READY;
+ }
+
private IImsService getServiceInterface(IBinder b) {
return IImsService.Stub.asInterface(b);
}