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.server.wm;
18 
19 import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE;
20 import static android.provider.AndroidDeviceConfig.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
21 
22 import android.provider.AndroidDeviceConfig;
23 import android.provider.DeviceConfig;
24 
25 import com.android.internal.annotations.VisibleForTesting;
26 import com.android.server.wm.utils.DeviceConfigInterface;
27 
28 import java.io.PrintWriter;
29 import java.util.Objects;
30 import java.util.concurrent.Executor;
31 
32 /**
33  * Settings constants that can modify the window manager's behavior.
34  */
35 final class WindowManagerConstants {
36 
37     /**
38      * The minimum duration between gesture exclusion logging for a given window in
39      * milliseconds.
40      *
41      * Events that happen in-between will be silently dropped.
42      *
43      * A non-positive value disables logging.
44      *
45      * <p>Note: On Devices running Q, this key is in the "android:window_manager" namespace.
46      *
47      * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
48      */
49     static final String KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS =
50             "system_gesture_exclusion_log_debounce_millis";
51 
52     private static final int MIN_GESTURE_EXCLUSION_LIMIT_DP = 200;
53 
54     /** @see #KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS */
55     long mSystemGestureExclusionLogDebounceTimeoutMillis;
56     /** @see AndroidDeviceConfig#KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP */
57     int mSystemGestureExclusionLimitDp;
58     /** @see AndroidDeviceConfig#KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE */
59     boolean mSystemGestureExcludedByPreQStickyImmersive;
60 
61     private final WindowManagerGlobalLock mGlobalLock;
62     private final Runnable mUpdateSystemGestureExclusionCallback;
63     private final DeviceConfigInterface mDeviceConfig;
64     private final DeviceConfig.OnPropertiesChangedListener mListenerAndroid;
65     private final DeviceConfig.OnPropertiesChangedListener mListenerWindowManager;
66 
WindowManagerConstants(WindowManagerService service, DeviceConfigInterface deviceConfig)67     WindowManagerConstants(WindowManagerService service, DeviceConfigInterface deviceConfig) {
68         this(service.mGlobalLock, () -> service.mRoot.forAllDisplays(
69                 DisplayContent::updateSystemGestureExclusionLimit), deviceConfig);
70     }
71 
72     @VisibleForTesting
WindowManagerConstants(WindowManagerGlobalLock globalLock, Runnable updateSystemGestureExclusionCallback, DeviceConfigInterface deviceConfig)73     WindowManagerConstants(WindowManagerGlobalLock globalLock,
74             Runnable updateSystemGestureExclusionCallback,
75             DeviceConfigInterface deviceConfig) {
76         mGlobalLock = Objects.requireNonNull(globalLock);
77         mUpdateSystemGestureExclusionCallback = Objects.requireNonNull(updateSystemGestureExclusionCallback);
78         mDeviceConfig = deviceConfig;
79         mListenerAndroid = this::onAndroidPropertiesChanged;
80         mListenerWindowManager = this::onWindowPropertiesChanged;
81     }
82 
start(Executor executor)83     void start(Executor executor) {
84         mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ANDROID, executor,
85                 mListenerAndroid);
86         mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
87                 executor, mListenerWindowManager);
88 
89         updateSystemGestureExclusionLogDebounceMillis();
90         updateSystemGestureExclusionLimitDp();
91         updateSystemGestureExcludedByPreQStickyImmersive();
92     }
93 
94     @VisibleForTesting
dispose()95     void dispose() {
96         mDeviceConfig.removeOnPropertiesChangedListener(mListenerAndroid);
97         mDeviceConfig.removeOnPropertiesChangedListener(mListenerWindowManager);
98     }
99 
onAndroidPropertiesChanged(DeviceConfig.Properties properties)100     private void onAndroidPropertiesChanged(DeviceConfig.Properties properties) {
101         synchronized (mGlobalLock) {
102             boolean updateSystemGestureExclusionLimit = false;
103             for (String name : properties.getKeyset()) {
104                 if (name == null) {
105                     return;
106                 }
107                 switch (name) {
108                     case KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP:
109                         updateSystemGestureExclusionLimitDp();
110                         updateSystemGestureExclusionLimit = true;
111                         break;
112                     case KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE:
113                         updateSystemGestureExcludedByPreQStickyImmersive();
114                         updateSystemGestureExclusionLimit = true;
115                         break;
116                     default:
117                         break;
118                 }
119             }
120             if (updateSystemGestureExclusionLimit) {
121                 mUpdateSystemGestureExclusionCallback.run();
122             }
123         }
124     }
125 
onWindowPropertiesChanged(DeviceConfig.Properties properties)126     private void onWindowPropertiesChanged(DeviceConfig.Properties properties) {
127         synchronized (mGlobalLock) {
128             for (String name : properties.getKeyset()) {
129                 if (name == null) {
130                     return;
131                 }
132                 switch (name) {
133                     case KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS:
134                         updateSystemGestureExclusionLogDebounceMillis();
135                         break;
136                     default:
137                         break;
138                 }
139             }
140         }
141     }
142 
updateSystemGestureExclusionLogDebounceMillis()143     private void updateSystemGestureExclusionLogDebounceMillis() {
144         mSystemGestureExclusionLogDebounceTimeoutMillis =
145                 mDeviceConfig.getLong(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
146                         KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
147     }
148 
updateSystemGestureExclusionLimitDp()149     private void updateSystemGestureExclusionLimitDp() {
150         mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
151                 mDeviceConfig.getInt(DeviceConfig.NAMESPACE_ANDROID,
152                         KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
153     }
154 
updateSystemGestureExcludedByPreQStickyImmersive()155     private void updateSystemGestureExcludedByPreQStickyImmersive() {
156         mSystemGestureExcludedByPreQStickyImmersive = mDeviceConfig.getBoolean(
157                 DeviceConfig.NAMESPACE_ANDROID,
158                 KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
159     }
160 
dump(PrintWriter pw)161     void dump(PrintWriter pw) {
162         pw.println("WINDOW MANAGER CONSTANTS (dumpsys window constants):");
163 
164         pw.print("  "); pw.print(KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS);
165         pw.print("="); pw.println(mSystemGestureExclusionLogDebounceTimeoutMillis);
166         pw.print("  "); pw.print(KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP);
167         pw.print("="); pw.println(mSystemGestureExclusionLimitDp);
168         pw.print("  "); pw.print(KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE);
169         pw.print("="); pw.println(mSystemGestureExcludedByPreQStickyImmersive);
170         pw.println();
171     }
172 }
173