Add APIs in PowerManager for suppressing ambient display.

Added 4 methods:
boolean isAmbientDisplayAvailable()
void suppressAmbientDisplay(String token, boolean suppress)
boolean isAmbientDisplaySuppressedForToken(String token)
boolean isAmbientDisplaySuppressed()

This CL simply adds the API to toggle SUPPRESS_DOZE. The code for
actually turning off doze when the secure setting is updated will be
implemented in a follow-up CL.

Test: manual, atest FrameworksServicesTests:PowerManagerServiceTest
Bug: 147584235, 147587449
Change-Id: I54f46f75fb84aae2ae806690e73eeb427ad8e8e1
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index c1b71aa..41fc9c6 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -72,6 +72,7 @@
 import android.service.dreams.DreamManagerInternal;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
+import android.util.ArraySet;
 import android.util.KeyValueListParser;
 import android.util.PrintWriterPrinter;
 import android.util.Slog;
@@ -109,6 +110,7 @@
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 
 /**
  * The power manager service is responsible for coordinating power management
@@ -565,6 +567,9 @@
     // but the DreamService has not yet been told to start (it's an async process).
     private boolean mDozeStartInProgress;
 
+    // Set of all tokens suppressing ambient display.
+    private final Set<String> mAmbientDisplaySuppressionTokens = new ArraySet<>();
+
     private final class ForegroundProfileObserver extends SynchronousUserSwitchObserver {
         @Override
         public void onUserSwitching(@UserIdInt int newUserId) throws RemoteException {
@@ -3357,6 +3362,26 @@
         }
     }
 
+    private void suppressAmbientDisplayInternal(String token, boolean suppress) {
+        if (DEBUG_SPEW) {
+            Slog.d(TAG, "Suppress ambient display for token " + token + ": " + suppress);
+        }
+
+        if (suppress) {
+            mAmbientDisplaySuppressionTokens.add(token);
+        } else {
+            mAmbientDisplaySuppressionTokens.remove(token);
+        }
+
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.SUPPRESS_DOZE,
+                Math.min(mAmbientDisplaySuppressionTokens.size(), 1));
+    }
+
+    private String createAmbientDisplayToken(String token, int callingUid) {
+        return callingUid + "_" + token;
+    }
+
     private void boostScreenBrightnessInternal(long eventTime, int uid) {
         synchronized (mLock) {
             if (!mSystemReady || mWakefulness == WAKEFULNESS_ASLEEP
@@ -5007,6 +5032,61 @@
         }
 
         @Override // Binder call
+        public boolean isAmbientDisplayAvailable() {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_DREAM_STATE, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return mAmbientDisplayConfiguration.ambientDisplayAvailable();
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public void suppressAmbientDisplay(@NonNull String token, boolean suppress) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.WRITE_DREAM_STATE, null);
+
+            final int uid = Binder.getCallingUid();
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                suppressAmbientDisplayInternal(createAmbientDisplayToken(token, uid), suppress);
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public boolean isAmbientDisplaySuppressedForToken(@NonNull String token) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_DREAM_STATE, null);
+
+            final int uid = Binder.getCallingUid();
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return mAmbientDisplaySuppressionTokens.contains(
+                        createAmbientDisplayToken(token, uid));
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
+        public boolean isAmbientDisplaySuppressed() {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.READ_DREAM_STATE, null);
+
+            final long ident = Binder.clearCallingIdentity();
+            try {
+                return mAmbientDisplaySuppressionTokens.size() > 0;
+            } finally {
+                Binder.restoreCallingIdentity(ident);
+            }
+        }
+
+        @Override // Binder call
         public void boostScreenBrightness(long eventTime) {
             if (eventTime > SystemClock.uptimeMillis()) {
                 throw new IllegalArgumentException("event time must not be in the future");