1 /** 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.power; 18 19 import static java.util.Objects.requireNonNull; 20 21 import android.annotation.NonNull; 22 import android.content.Context; 23 import android.os.RemoteException; 24 import android.os.ServiceManager; 25 import android.util.ArraySet; 26 import android.util.Pair; 27 import android.util.Slog; 28 29 import com.android.internal.statusbar.IStatusBarService; 30 31 import java.io.PrintWriter; 32 import java.util.ArrayList; 33 import java.util.Collections; 34 import java.util.List; 35 import java.util.Set; 36 37 /** 38 * Communicates with System UI to suppress the ambient display. 39 */ 40 public class AmbientDisplaySuppressionController { 41 private static final String TAG = "AmbientDisplaySuppressionController"; 42 43 private final Set<Pair<String, Integer>> mSuppressionTokens; 44 private final AmbientDisplaySuppressionChangedCallback mCallback; 45 private IStatusBarService mStatusBarService; 46 47 /** Interface to get a list of available logical devices. */ 48 interface AmbientDisplaySuppressionChangedCallback { 49 /** 50 * Called when the suppression state changes. 51 * 52 * @param isSuppressed Whether ambient is suppressed. 53 */ onSuppressionChanged(boolean isSuppressed)54 void onSuppressionChanged(boolean isSuppressed); 55 } 56 AmbientDisplaySuppressionController( @onNull AmbientDisplaySuppressionChangedCallback callback)57 AmbientDisplaySuppressionController( 58 @NonNull AmbientDisplaySuppressionChangedCallback callback) { 59 mSuppressionTokens = Collections.synchronizedSet(new ArraySet<>()); 60 mCallback = requireNonNull(callback); 61 } 62 63 /** 64 * Suppresses ambient display. 65 * 66 * @param token A persistible identifier for the ambient display suppression. 67 * @param callingUid The uid of the calling application. 68 * @param suppress If true, suppresses the ambient display. Otherwise, unsuppresses it. 69 */ suppress(@onNull String token, int callingUid, boolean suppress)70 public void suppress(@NonNull String token, int callingUid, boolean suppress) { 71 Pair<String, Integer> suppressionToken = Pair.create(requireNonNull(token), callingUid); 72 final boolean wasSuppressed = isSuppressed(); 73 74 if (suppress) { 75 mSuppressionTokens.add(suppressionToken); 76 } else { 77 mSuppressionTokens.remove(suppressionToken); 78 } 79 80 final boolean isSuppressed = isSuppressed(); 81 if (isSuppressed != wasSuppressed) { 82 mCallback.onSuppressionChanged(isSuppressed); 83 } 84 85 try { 86 synchronized (mSuppressionTokens) { 87 getStatusBar().suppressAmbientDisplay(isSuppressed); 88 } 89 } catch (RemoteException e) { 90 Slog.e(TAG, "Failed to suppress ambient display", e); 91 } 92 } 93 94 /** 95 * Returns the tokens used to suppress ambient display through 96 * {@link #suppress(String, int, boolean)}. 97 * 98 * @param callingUid The uid of the calling application. 99 */ getSuppressionTokens(int callingUid)100 List<String> getSuppressionTokens(int callingUid) { 101 List<String> result = new ArrayList<>(); 102 synchronized (mSuppressionTokens) { 103 for (Pair<String, Integer> token : mSuppressionTokens) { 104 if (token.second == callingUid) { 105 result.add(token.first); 106 } 107 } 108 } 109 return result; 110 } 111 112 /** 113 * Returns whether ambient display is suppressed for the given token. 114 * 115 * @param token A persistible identifier for the ambient display suppression. 116 * @param callingUid The uid of the calling application. 117 */ isSuppressed(@onNull String token, int callingUid)118 public boolean isSuppressed(@NonNull String token, int callingUid) { 119 return mSuppressionTokens.contains(Pair.create(requireNonNull(token), callingUid)); 120 } 121 122 /** 123 * Returns whether ambient display is suppressed. 124 */ isSuppressed()125 public boolean isSuppressed() { 126 return !mSuppressionTokens.isEmpty(); 127 } 128 129 /** 130 * Dumps the state of ambient display suppression and the list of suppression tokens into 131 * {@code pw}. 132 */ dump(PrintWriter pw)133 public void dump(PrintWriter pw) { 134 pw.println("AmbientDisplaySuppressionController:"); 135 pw.println(" ambientDisplaySuppressed=" + isSuppressed()); 136 pw.println(" mSuppressionTokens=" + mSuppressionTokens); 137 } 138 getStatusBar()139 private synchronized IStatusBarService getStatusBar() { 140 if (mStatusBarService == null) { 141 mStatusBarService = IStatusBarService.Stub.asInterface( 142 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 143 } 144 return mStatusBarService; 145 } 146 } 147