1 /*
2  * Copyright (C) 2019 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.systemui.statusbar.notification;
18 
19 import android.util.ArraySet;
20 
21 import androidx.annotation.VisibleForTesting;
22 
23 import com.android.systemui.dagger.SysUISingleton;
24 import com.android.systemui.plugins.statusbar.StatusBarStateController;
25 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
26 import com.android.systemui.statusbar.StatusBarState;
27 import com.android.systemui.statusbar.policy.KeyguardStateController;
28 
29 import javax.inject.Inject;
30 
31 /**
32  * A controller which dynamically controls the visibility of Notification content
33  */
34 @SysUISingleton
35 public class DynamicPrivacyController implements KeyguardStateController.Callback {
36 
37     private final KeyguardStateController mKeyguardStateController;
38     private final NotificationLockscreenUserManager mLockscreenUserManager;
39     private final StatusBarStateController mStateController;
40     private final ArraySet<Listener> mListeners = new ArraySet<>();
41 
42     private boolean mLastDynamicUnlocked;
43     private boolean mCacheInvalid;
44 
45     @Inject
DynamicPrivacyController(NotificationLockscreenUserManager notificationLockscreenUserManager, KeyguardStateController keyguardStateController, StatusBarStateController stateController)46     DynamicPrivacyController(NotificationLockscreenUserManager notificationLockscreenUserManager,
47             KeyguardStateController keyguardStateController,
48             StatusBarStateController stateController) {
49         mLockscreenUserManager = notificationLockscreenUserManager;
50         mStateController = stateController;
51         mKeyguardStateController = keyguardStateController;
52         mKeyguardStateController.addCallback(this);
53         mLastDynamicUnlocked = isDynamicallyUnlocked();
54     }
55 
56     @Override
onKeyguardFadingAwayChanged()57     public void onKeyguardFadingAwayChanged() {
58         onUnlockedChanged();
59     }
60 
61     @Override
onUnlockedChanged()62     public void onUnlockedChanged() {
63         if (isDynamicPrivacyEnabled()) {
64             // We only want to notify our listeners if dynamic privacy is actually enabled
65             boolean dynamicallyUnlocked = isDynamicallyUnlocked();
66             if (dynamicallyUnlocked != mLastDynamicUnlocked || mCacheInvalid) {
67                 mLastDynamicUnlocked = dynamicallyUnlocked;
68                 for (Listener listener : mListeners) {
69                     listener.onDynamicPrivacyChanged();
70                 }
71             }
72             mCacheInvalid = false;
73         } else {
74             mCacheInvalid = true;
75         }
76     }
77 
78     @VisibleForTesting
isDynamicPrivacyEnabled()79     boolean isDynamicPrivacyEnabled() {
80         return mLockscreenUserManager.userAllowsNotificationsInPublic(
81                 mLockscreenUserManager.getCurrentUserId());
82     }
83 
isDynamicallyUnlocked()84     public boolean isDynamicallyUnlocked() {
85         return (mKeyguardStateController.canDismissLockScreen()
86                 || mKeyguardStateController.isKeyguardGoingAway()
87                 || mKeyguardStateController.isKeyguardFadingAway())
88                 && isDynamicPrivacyEnabled();
89     }
90 
addListener(Listener listener)91     public void addListener(Listener listener) {
92         mListeners.add(listener);
93     }
94 
95     /**
96      * Is the notification shade currently in a locked down mode where it's fully showing but the
97      * contents aren't revealed yet?
98      */
isInLockedDownShade()99     public boolean isInLockedDownShade() {
100         if (!mKeyguardStateController.isShowing() || !mKeyguardStateController.isMethodSecure()) {
101             return false;
102         }
103         int state = mStateController.getState();
104         if (state != StatusBarState.SHADE && state != StatusBarState.SHADE_LOCKED) {
105             return false;
106         }
107         if (!isDynamicPrivacyEnabled() || isDynamicallyUnlocked()) {
108             return false;
109         }
110         return true;
111     }
112 
113     public interface Listener {
onDynamicPrivacyChanged()114         void onDynamicPrivacyChanged();
115     }
116 }
117