diff options
| author | 2025-03-10 16:35:18 +0000 | |
|---|---|---|
| committer | 2025-03-17 12:03:00 +0000 | |
| commit | c5fbad940870f1d3f343cee91b766f57b850aef6 (patch) | |
| tree | 64e0f2f388579a7f8ca4a05af3092fa41556852a | |
| parent | 88ab7d2ac1c08005e8f4cdd12299fbc4ba01c992 (diff) | |
Make StatusBarManagerService#disableForUser methods work on all
displays.
This ensures DevicePolicyManager#setStatusBarDisabled works for all displays
This reverts commit 917ca3da519bcf364257610a4ab0163d77ea5379 and fixes the issue where previous disable tasks were removed without checking the display id.
NO_IFTTT=No changes to flag list
Bug: 382031216
Test: atest com.android.server.statusbar.StatusBarManagerServiceTest
Test: atest AndroidAutomotiveHomeTests
Flag: com.android.systemui.shared.status_bar_connected_displays
Change-Id: I3e10c55f75d44f39ac8549e628b8552f203b389a
9 files changed, 409 insertions, 15 deletions
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java index 01868cc601fe..927d46999284 100644 --- a/core/java/android/app/StatusBarManager.java +++ b/core/java/android/app/StatusBarManager.java @@ -58,8 +58,10 @@ import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.IUndoMediaTransferCallback; import com.android.internal.statusbar.NotificationVisibility; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -119,6 +121,7 @@ public class StatusBarManager { | DISABLE_SEARCH | DISABLE_ONGOING_CALL_CHIP; /** @hide */ + @Target(ElementType.TYPE_USE) @IntDef(flag = true, prefix = {"DISABLE_"}, value = { DISABLE_NONE, DISABLE_EXPAND, @@ -161,6 +164,7 @@ public class StatusBarManager { | DISABLE2_NOTIFICATION_SHADE | DISABLE2_GLOBAL_ACTIONS | DISABLE2_ROTATE_SUGGESTIONS; /** @hide */ + @Target(ElementType.TYPE_USE) @IntDef(flag = true, prefix = { "DISABLE2_" }, value = { DISABLE2_NONE, DISABLE2_MASK, diff --git a/core/java/com/android/internal/statusbar/DisableStates.aidl b/core/java/com/android/internal/statusbar/DisableStates.aidl new file mode 100644 index 000000000000..fd9882f0f7c2 --- /dev/null +++ b/core/java/com/android/internal/statusbar/DisableStates.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2025 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.internal.statusbar; + +parcelable DisableStates; diff --git a/core/java/com/android/internal/statusbar/DisableStates.java b/core/java/com/android/internal/statusbar/DisableStates.java new file mode 100644 index 000000000000..ca2fd6c03558 --- /dev/null +++ b/core/java/com/android/internal/statusbar/DisableStates.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2025 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.internal.statusbar; + +import android.app.StatusBarManager.Disable2Flags; +import android.app.StatusBarManager.DisableFlags; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Pair; + +import java.util.HashMap; +import java.util.Map; + +/** + * Holds display ids with their disable flags. + */ +public class DisableStates implements Parcelable { + + /** + * A map of display IDs (integers) with corresponding disable flags. + */ + public Map<Integer, Pair<@DisableFlags Integer, @Disable2Flags Integer>> displaysWithStates; + + /** + * Whether the disable state change should be animated. + */ + public boolean animate; + + public DisableStates( + Map<Integer, Pair<@DisableFlags Integer, @Disable2Flags Integer>> displaysWithStates, + boolean animate) { + this.displaysWithStates = displaysWithStates; + this.animate = animate; + } + + public DisableStates( + Map<Integer, Pair<@DisableFlags Integer, @Disable2Flags Integer>> displaysWithStates) { + this(displaysWithStates, true); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(displaysWithStates.size()); // Write the size of the map + for (Map.Entry<Integer, Pair<Integer, Integer>> entry : displaysWithStates.entrySet()) { + dest.writeInt(entry.getKey()); + dest.writeInt(entry.getValue().first); + dest.writeInt(entry.getValue().second); + } + dest.writeBoolean(animate); + } + + /** + * Used to make this class parcelable. + */ + public static final Parcelable.Creator<DisableStates> CREATOR = new Parcelable.Creator<>() { + @Override + public DisableStates createFromParcel(Parcel source) { + int size = source.readInt(); // Read the size of the map + Map<Integer, Pair<Integer, Integer>> displaysWithStates = new HashMap<>(size); + for (int i = 0; i < size; i++) { + int key = source.readInt(); + int first = source.readInt(); + int second = source.readInt(); + displaysWithStates.put(key, new Pair<>(first, second)); + } + final boolean animate = source.readBoolean(); + return new DisableStates(displaysWithStates, animate); + } + + @Override + public DisableStates[] newArray(int size) { + return new DisableStates[size]; + } + }; +} + diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl index 5a180d7358dd..ce9b036f2fd7 100644 --- a/core/java/com/android/internal/statusbar/IStatusBar.aidl +++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl @@ -32,6 +32,7 @@ import android.os.UserHandle; import android.view.KeyEvent; import android.service.notification.StatusBarNotification; +import com.android.internal.statusbar.DisableStates; import com.android.internal.statusbar.IAddTileResultCallback; import com.android.internal.statusbar.IUndoMediaTransferCallback; import com.android.internal.statusbar.LetterboxDetails; @@ -44,6 +45,7 @@ oneway interface IStatusBar void setIcon(String slot, in StatusBarIcon icon); void removeIcon(String slot); void disable(int displayId, int state1, int state2); + void disableForAllDisplays(in DisableStates disableStates); void animateExpandNotificationsPanel(); void animateExpandSettingsPanel(String subPanel); void animateCollapsePanels(); diff --git a/core/tests/coretests/src/com/android/internal/statusbar/DisableStatesTest.java b/core/tests/coretests/src/com/android/internal/statusbar/DisableStatesTest.java new file mode 100644 index 000000000000..5b82696b81c3 --- /dev/null +++ b/core/tests/coretests/src/com/android/internal/statusbar/DisableStatesTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2025 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.internal.statusbar; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import android.os.Parcel; +import android.util.Pair; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.HashMap; +import java.util.Map; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class DisableStatesTest { + + @Test + public void testParcelable() { + Map<Integer, Pair<Integer, Integer>> displaysWithStates = new HashMap<>(); + displaysWithStates.put(1, new Pair<>(10, 20)); + displaysWithStates.put(2, new Pair<>(30, 40)); + boolean animate = true; + DisableStates original = new DisableStates(displaysWithStates, animate); + + Parcel parcel = Parcel.obtain(); + original.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + DisableStates restored = DisableStates.CREATOR.createFromParcel(parcel); + + assertNotNull(restored); + assertEquals(original.displaysWithStates.size(), restored.displaysWithStates.size()); + for (Map.Entry<Integer, Pair<Integer, Integer>> entry : + original.displaysWithStates.entrySet()) { + int displayId = entry.getKey(); + Pair<Integer, Integer> originalDisplayStates = entry.getValue(); + Pair<Integer, Integer> restoredDisplayStates = restored.displaysWithStates.get( + displayId); + assertEquals(originalDisplayStates.first, restoredDisplayStates.first); + assertEquals(originalDisplayStates.second, restoredDisplayStates.second); + } + assertEquals(original.animate, restored.animate); + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java index 70df82d95008..c26f18f5ab6d 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/CommandQueueTest.java @@ -36,7 +36,9 @@ import android.hardware.biometrics.IBiometricSysuiReceiver; import android.hardware.biometrics.PromptInfo; import android.hardware.fingerprint.IUdfpsRefreshRateRequestCallback; import android.os.Bundle; +import android.os.RemoteException; import android.platform.test.annotations.EnableFlags; +import android.util.Pair; import android.view.KeyEvent; import android.view.WindowInsets; import android.view.WindowInsets.Type.InsetsType; @@ -46,6 +48,7 @@ import android.view.WindowInsetsController.Behavior; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; +import com.android.internal.statusbar.DisableStates; import com.android.internal.statusbar.LetterboxDetails; import com.android.internal.statusbar.StatusBarIcon; import com.android.internal.view.AppearanceRegion; @@ -58,11 +61,14 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import java.util.HashMap; +import java.util.Map; + @SmallTest @RunWith(AndroidJUnit4.class) public class CommandQueueTest extends SysuiTestCase { - private static final LetterboxDetails[] TEST_LETTERBOX_DETAILS = new LetterboxDetails[] { + private static final LetterboxDetails[] TEST_LETTERBOX_DETAILS = new LetterboxDetails[]{ new LetterboxDetails( /* letterboxInnerBounds= */ new Rect(100, 0, 200, 500), /* letterboxFullBounds= */ new Rect(0, 0, 500, 100), @@ -119,6 +125,27 @@ public class CommandQueueTest extends SysuiTestCase { } @Test + public void testDisableForAllDisplays() throws RemoteException { + int state1 = 14; + int state2 = 42; + int secondaryDisplayState1 = 16; + int secondaryDisplayState2 = 44; + Map<Integer, Pair<Integer, Integer>> displaysWithStates = new HashMap<>(); + displaysWithStates.put(DEFAULT_DISPLAY, new Pair<>(state1, state2)); // Example values + displaysWithStates.put(SECONDARY_DISPLAY, + new Pair<>(secondaryDisplayState1, secondaryDisplayState2)); // Example values + DisableStates expectedDisableStates = new DisableStates(displaysWithStates, true); + + mCommandQueue.disableForAllDisplays(expectedDisableStates); + waitForIdleSync(); + + verify(mCallbacks).disable(eq(DEFAULT_DISPLAY), eq(state1), eq(state2), eq(true)); + verify(mCallbacks).disable(eq(SECONDARY_DISPLAY), eq(secondaryDisplayState1), + eq(secondaryDisplayState2), eq(true)); + } + + + @Test public void testExpandNotifications() { mCommandQueue.animateExpandNotificationsPanel(); waitForIdleSync(); @@ -475,7 +502,8 @@ public class CommandQueueTest extends SysuiTestCase { final long requestId = 10; mCommandQueue.showAuthenticationDialog(promptInfo, receiver, sensorIds, - credentialAllowed, requireConfirmation, userId, operationId, packageName, requestId); + credentialAllowed, requireConfirmation, userId, operationId, packageName, + requestId); waitForIdleSync(); verify(mCallbacks).showAuthenticationDialog(eq(promptInfo), eq(receiver), eq(sensorIds), eq(credentialAllowed), eq(requireConfirmation), eq(userId), eq(operationId), diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index e44701dba87c..4daf61a895c7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -64,6 +64,7 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.annotations.KeepForWeakReference; import com.android.internal.os.SomeArgs; +import com.android.internal.statusbar.DisableStates; import com.android.internal.statusbar.IAddTileResultCallback; import com.android.internal.statusbar.IStatusBar; import com.android.internal.statusbar.IUndoMediaTransferCallback; @@ -85,6 +86,7 @@ import java.io.FileOutputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Map; /** * This class takes the functions from IStatusBar that come in on @@ -184,6 +186,8 @@ public class CommandQueue extends IStatusBar.Stub implements private static final int MSG_TOGGLE_QUICK_SETTINGS_PANEL = 82 << MSG_SHIFT; private static final int MSG_WALLET_ACTION_LAUNCH_GESTURE = 83 << MSG_SHIFT; private static final int MSG_DISPLAY_REMOVE_SYSTEM_DECORATIONS = 85 << MSG_SHIFT; + private static final int MSG_DISABLE_ALL = 86 << MSG_SHIFT; + public static final int FLAG_EXCLUDE_NONE = 0; public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0; public static final int FLAG_EXCLUDE_RECENTS_PANEL = 1 << 1; @@ -654,7 +658,8 @@ public class CommandQueue extends IStatusBar.Stub implements /** * Called to notify that disable flags are updated. - * @see Callbacks#disable(int, int, int, boolean). + * @see Callbacks#disable(int, int, int, boolean) + * @see Callbacks#disableForAllDisplays(DisableStates) */ public void disable(int displayId, @DisableFlags int state1, @Disable2Flags int state2, boolean animate) { @@ -682,6 +687,27 @@ public class CommandQueue extends IStatusBar.Stub implements disable(displayId, state1, state2, true); } + @Override + public void disableForAllDisplays(DisableStates disableStates) throws RemoteException { + synchronized (mLock) { + for (Map.Entry<Integer, Pair<Integer, Integer>> displaysWithStates : + disableStates.displaysWithStates.entrySet()) { + int displayId = displaysWithStates.getKey(); + Pair<Integer, Integer> states = displaysWithStates.getValue(); + setDisabled(displayId, states.first, states.second); + } + mHandler.removeMessages(MSG_DISABLE_ALL); + Message msg = mHandler.obtainMessage(MSG_DISABLE_ALL, disableStates); + if (Looper.myLooper() == mHandler.getLooper()) { + // If its the right looper execute immediately so hides can be handled quickly. + mHandler.handleMessage(msg); + msg.recycle(); + } else { + msg.sendToTarget(); + } + } + } + /** * Apply current disable flags by {@link CommandQueue#disable(int, int, int, boolean)}. * @@ -1552,6 +1578,21 @@ public class CommandQueue extends IStatusBar.Stub implements args.argi4 != 0 /* animate */); } break; + case MSG_DISABLE_ALL: + DisableStates disableStates = (DisableStates) msg.obj; + boolean animate = disableStates.animate; + Map<Integer, Pair<Integer, Integer>> displaysWithDisableStates = + disableStates.displaysWithStates; + for (Map.Entry<Integer, Pair<Integer, Integer>> displayWithDisableStates : + displaysWithDisableStates.entrySet()) { + int displayId = displayWithDisableStates.getKey(); + Pair<Integer, Integer> states = displayWithDisableStates.getValue(); + for (int i = 0; i < mCallbacks.size(); i++) { + mCallbacks.get(i).disable(displayId, states.first, states.second, + animate); + } + } + break; case MSG_EXPAND_NOTIFICATIONS: for (int i = 0; i < mCallbacks.size(); i++) { mCallbacks.get(i).animateExpandNotificationsPanel(); diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index 798c794edaf5..0f6cc24f1fc9 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -87,6 +87,7 @@ import android.service.quicksettings.TileService; import android.text.TextUtils; import android.util.ArrayMap; import android.util.IndentingPrintWriter; +import android.util.IntArray; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; @@ -102,6 +103,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.inputmethod.SoftInputShowHideReason; import com.android.internal.logging.InstanceId; import com.android.internal.os.TransferPipe; +import com.android.internal.statusbar.DisableStates; import com.android.internal.statusbar.IAddTileResultCallback; import com.android.internal.statusbar.ISessionListener; import com.android.internal.statusbar.IStatusBar; @@ -124,6 +126,7 @@ import com.android.server.policy.GlobalActionsProvider; import com.android.server.power.ShutdownCheckPoints; import com.android.server.power.ShutdownThread; import com.android.server.wm.ActivityTaskManagerInternal; +import com.android.systemui.shared.Flags; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -1344,48 +1347,76 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D return mTracingEnabled; } - // TODO(b/117478341): make it aware of multi-display if needed. + /** + * Disable status bar features. Pass the bitwise-or of the {@code #DISABLE_*} flags. + * To re-enable everything, pass {@code #DISABLE_NONE}. + * + * Warning: Only pass {@code #DISABLE_*} flags into this function, do not use + * {@code #DISABLE2_*} flags. + */ @Override public void disable(int what, IBinder token, String pkg) { disableForUser(what, token, pkg, mCurrentUserId); } - // TODO(b/117478341): make it aware of multi-display if needed. + /** + * Disable status bar features for a given user. Pass the bitwise-or of the + * {@code #DISABLE_*} flags. To re-enable everything, pass {@code #DISABLE_NONE}. + * + * Warning: Only pass {@code #DISABLE_*} flags into this function, do not use + * {@code #DISABLE2_*} flags. + */ @Override public void disableForUser(int what, IBinder token, String pkg, int userId) { enforceStatusBar(); enforceValidCallingUser(); synchronized (mLock) { - disableLocked(DEFAULT_DISPLAY, userId, what, token, pkg, 1); + if (Flags.statusBarConnectedDisplays()) { + IntArray displayIds = new IntArray(); + for (int i = 0; i < mDisplayUiState.size(); i++) { + displayIds.add(mDisplayUiState.keyAt(i)); + } + disableAllDisplaysLocked(displayIds, userId, what, token, pkg, /* whichFlag= */ 1); + } else { + disableLocked(DEFAULT_DISPLAY, userId, what, token, pkg, /* whichFlag= */ 1); + } } } - // TODO(b/117478341): make it aware of multi-display if needed. /** - * Disable additional status bar features. Pass the bitwise-or of the DISABLE2_* flags. - * To re-enable everything, pass {@link #DISABLE2_NONE}. + * Disable additional status bar features. Pass the bitwise-or of the {@code #DISABLE2_*} flags. + * To re-enable everything, pass {@code #DISABLE2_NONE}. * - * Warning: Only pass DISABLE2_* flags into this function, do not use DISABLE_* flags. + * Warning: Only pass {@code #DISABLE2_*} flags into this function, do not use + * {@code #DISABLE_*} flags. */ @Override public void disable2(int what, IBinder token, String pkg) { disable2ForUser(what, token, pkg, mCurrentUserId); } - // TODO(b/117478341): make it aware of multi-display if needed. /** - * Disable additional status bar features for a given user. Pass the bitwise-or of the - * DISABLE2_* flags. To re-enable everything, pass {@link #DISABLE_NONE}. + * Disable additional status bar features for a given user. Pass the bitwise-or + * of the {@code #DISABLE2_*} flags. To re-enable everything, pass {@code #DISABLE2_NONE}. * - * Warning: Only pass DISABLE2_* flags into this function, do not use DISABLE_* flags. + * Warning: Only pass {@code #DISABLE2_*} flags into this function, do not use + * {@code #DISABLE_*} flags. */ @Override public void disable2ForUser(int what, IBinder token, String pkg, int userId) { enforceStatusBar(); synchronized (mLock) { - disableLocked(DEFAULT_DISPLAY, userId, what, token, pkg, 2); + if (Flags.statusBarConnectedDisplays()) { + IntArray displayIds = new IntArray(); + for (int i = 0; i < mDisplayUiState.size(); i++) { + displayIds.add(mDisplayUiState.keyAt(i)); + } + disableAllDisplaysLocked(displayIds, userId, what, token, pkg, /* whichFlag= */ 2); + } else { + disableLocked(DEFAULT_DISPLAY, userId, what, token, pkg, /* whichFlag= */ 2); + } } } @@ -1414,6 +1445,42 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D } } + // This method batches disable state across all displays into a single remote call + // (IStatusBar#disableForAllDisplays) for efficiency and calls + // NotificationDelegate#onSetDisabled only if any display's disable state changes. + private void disableAllDisplaysLocked(IntArray displayIds, int userId, int what, IBinder token, + String pkg, int whichFlag) { + // It's important that the the callback and the call to mBar get done + // in the same order when multiple threads are calling this function + // so they are paired correctly. The messages on the handler will be + // handled in the order they were enqueued, but will be outside the lock. + manageDisableListLocked(userId, what, token, pkg, whichFlag); + + // Ensure state for the current user is applied, even if passed a non-current user. + final int net1 = gatherDisableActionsLocked(mCurrentUserId, 1); + final int net2 = gatherDisableActionsLocked(mCurrentUserId, 2); + + IStatusBar bar = mBar; + Map<Integer, Pair<Integer, Integer>> displaysWithNewDisableStates = new HashMap<>(); + for (int displayId : displayIds.toArray()) { + final UiState state = getUiState(displayId); + if (!state.disableEquals(net1, net2)) { + state.setDisabled(net1, net2); + displaysWithNewDisableStates.put(displayId, new Pair(net1, net2)); + } + } + if (bar != null) { + try { + bar.disableForAllDisplays(new DisableStates(displaysWithNewDisableStates)); + } catch (RemoteException ex) { + Slog.e(TAG, "Unable to disable Status bar.", ex); + } + } + if (!displaysWithNewDisableStates.isEmpty()) { + mHandler.post(() -> mNotificationDelegate.onSetDisabled(net1)); + } + } + /** * Get the currently applied disable flags, in the form of one Pair<Integer, Integer>. * diff --git a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java index 148c96850d34..6d682ccef98d 100644 --- a/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/statusbar/StatusBarManagerServiceTest.java @@ -36,6 +36,7 @@ import static android.app.StatusBarManager.DISABLE_SYSTEM_INFO; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertThrows; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.nullable; @@ -69,16 +70,20 @@ import android.os.Binder; import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; +import android.platform.test.annotations.EnableFlags; import android.service.quicksettings.TileService; import android.testing.TestableContext; +import android.util.Pair; import androidx.test.InstrumentationRegistry; +import com.android.internal.statusbar.DisableStates; import com.android.internal.statusbar.IAddTileResultCallback; import com.android.internal.statusbar.IStatusBar; import com.android.server.LocalServices; import com.android.server.policy.GlobalActionsProvider; import com.android.server.wm.ActivityTaskManagerInternal; +import com.android.systemui.shared.Flags; import libcore.junit.util.compat.CoreCompatChangeRule; @@ -105,6 +110,7 @@ public class StatusBarManagerServiceTest { TEST_SERVICE); private static final CharSequence APP_NAME = "AppName"; private static final CharSequence TILE_LABEL = "Tile label"; + private static final int SECONDARY_DISPLAY_ID = 2; @Rule public final TestableContext mContext = @@ -749,6 +755,40 @@ public class StatusBarManagerServiceTest { } @Test + @EnableFlags(Flags.FLAG_STATUS_BAR_CONNECTED_DISPLAYS) + public void testDisableForAllDisplays() throws Exception { + int user1Id = 0; + mockUidCheck(); + mockCurrentUserCheck(user1Id); + + mStatusBarManagerService.onDisplayAdded(SECONDARY_DISPLAY_ID); + + int expectedFlags = DISABLE_MASK & DISABLE_BACK; + String pkg = mContext.getPackageName(); + + // before disabling + assertEquals(DISABLE_NONE, + mStatusBarManagerService.getDisableFlags(mMockStatusBar, user1Id)[0]); + + // disable + mStatusBarManagerService.disable(expectedFlags, mMockStatusBar, pkg); + + ArgumentCaptor<DisableStates> disableStatesCaptor = ArgumentCaptor.forClass( + DisableStates.class); + verify(mMockStatusBar).disableForAllDisplays(disableStatesCaptor.capture()); + DisableStates capturedDisableStates = disableStatesCaptor.getValue(); + assertTrue(capturedDisableStates.animate); + assertEquals(capturedDisableStates.displaysWithStates.size(), 2); + Pair<Integer, Integer> display0States = capturedDisableStates.displaysWithStates.get(0); + assertEquals((int) display0States.first, expectedFlags); + assertEquals((int) display0States.second, 0); + Pair<Integer, Integer> display2States = capturedDisableStates.displaysWithStates.get( + SECONDARY_DISPLAY_ID); + assertEquals((int) display2States.first, expectedFlags); + assertEquals((int) display2States.second, 0); + } + + @Test public void testSetHomeDisabled() throws Exception { int expectedFlags = DISABLE_MASK & DISABLE_HOME; String pkg = mContext.getPackageName(); @@ -851,6 +891,40 @@ public class StatusBarManagerServiceTest { } @Test + @EnableFlags(Flags.FLAG_STATUS_BAR_CONNECTED_DISPLAYS) + public void testDisable2ForAllDisplays() throws Exception { + int user1Id = 0; + mockUidCheck(); + mockCurrentUserCheck(user1Id); + + mStatusBarManagerService.onDisplayAdded(SECONDARY_DISPLAY_ID); + + int expectedFlags = DISABLE2_MASK & DISABLE2_NOTIFICATION_SHADE; + String pkg = mContext.getPackageName(); + + // before disabling + assertEquals(DISABLE_NONE, + mStatusBarManagerService.getDisableFlags(mMockStatusBar, user1Id)[0]); + + // disable + mStatusBarManagerService.disable2(expectedFlags, mMockStatusBar, pkg); + + ArgumentCaptor<DisableStates> disableStatesCaptor = ArgumentCaptor.forClass( + DisableStates.class); + verify(mMockStatusBar).disableForAllDisplays(disableStatesCaptor.capture()); + DisableStates capturedDisableStates = disableStatesCaptor.getValue(); + assertTrue(capturedDisableStates.animate); + assertEquals(capturedDisableStates.displaysWithStates.size(), 2); + Pair<Integer, Integer> display0States = capturedDisableStates.displaysWithStates.get(0); + assertEquals((int) display0States.first, 0); + assertEquals((int) display0States.second, expectedFlags); + Pair<Integer, Integer> display2States = capturedDisableStates.displaysWithStates.get( + SECONDARY_DISPLAY_ID); + assertEquals((int) display2States.first, 0); + assertEquals((int) display2States.second, expectedFlags); + } + + @Test public void testSetQuickSettingsDisabled2() throws Exception { int expectedFlags = DISABLE2_MASK & DISABLE2_QUICK_SETTINGS; String pkg = mContext.getPackageName(); |