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 import android.provider.DeviceConfigInterface;
25 
26 import com.android.internal.annotations.VisibleForTesting;
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 
onAndroidPropertiesChanged(DeviceConfig.Properties properties)94     private void onAndroidPropertiesChanged(DeviceConfig.Properties properties) {
95         synchronized (mGlobalLock) {
96             boolean updateSystemGestureExclusionLimit = false;
97             for (String name : properties.getKeyset()) {
98                 if (name == null) {
99                     return;
100                 }
101                 switch (name) {
102                     case KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP:
103                         updateSystemGestureExclusionLimitDp();
104                         updateSystemGestureExclusionLimit = true;
105                         break;
106                     case KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE:
107                         updateSystemGestureExcludedByPreQStickyImmersive();
108                         updateSystemGestureExclusionLimit = true;
109                         break;
110                     default:
111                         break;
112                 }
113             }
114             if (updateSystemGestureExclusionLimit) {
115                 mUpdateSystemGestureExclusionCallback.run();
116             }
117         }
118     }
119 
onWindowPropertiesChanged(DeviceConfig.Properties properties)120     private void onWindowPropertiesChanged(DeviceConfig.Properties properties) {
121         synchronized (mGlobalLock) {
122             for (String name : properties.getKeyset()) {
123                 if (name == null) {
124                     return;
125                 }
126                 switch (name) {
127                     case KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS:
128                         updateSystemGestureExclusionLogDebounceMillis();
129                         break;
130                     default:
131                         break;
132                 }
133             }
134         }
135     }
136 
updateSystemGestureExclusionLogDebounceMillis()137     private void updateSystemGestureExclusionLogDebounceMillis() {
138         mSystemGestureExclusionLogDebounceTimeoutMillis =
139                 mDeviceConfig.getLong(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
140                         KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS, 0);
141     }
142 
updateSystemGestureExclusionLimitDp()143     private void updateSystemGestureExclusionLimitDp() {
144         mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
145                 mDeviceConfig.getInt(DeviceConfig.NAMESPACE_ANDROID,
146                         KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
147     }
148 
updateSystemGestureExcludedByPreQStickyImmersive()149     private void updateSystemGestureExcludedByPreQStickyImmersive() {
150         mSystemGestureExcludedByPreQStickyImmersive = mDeviceConfig.getBoolean(
151                 DeviceConfig.NAMESPACE_ANDROID,
152                 KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE, false);
153     }
154 
dump(PrintWriter pw)155     void dump(PrintWriter pw) {
156         pw.println("WINDOW MANAGER CONSTANTS (dumpsys window constants):");
157 
158         pw.print("  "); pw.print(KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS);
159         pw.print("="); pw.println(mSystemGestureExclusionLogDebounceTimeoutMillis);
160         pw.print("  "); pw.print(KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP);
161         pw.print("="); pw.println(mSystemGestureExclusionLimitDp);
162         pw.print("  "); pw.print(KEY_SYSTEM_GESTURES_EXCLUDED_BY_PRE_Q_STICKY_IMMERSIVE);
163         pw.print("="); pw.println(mSystemGestureExcludedByPreQStickyImmersive);
164         pw.println();
165     }
166 }
167