• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.internal.policy;
18 
19 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.BACK_GESTURE_EDGE_WIDTH;
20 
21 import android.content.ContentResolver;
22 import android.content.Context;
23 import android.content.res.Resources;
24 import android.database.ContentObserver;
25 import android.os.Handler;
26 import android.os.SystemProperties;
27 import android.os.UserHandle;
28 import android.provider.DeviceConfig;
29 import android.provider.Settings;
30 import android.util.DisplayMetrics;
31 import android.util.TypedValue;
32 
33 /**
34  * @hide
35  */
36 public class GestureNavigationSettingsObserver extends ContentObserver {
37     private Context mContext;
38     private Runnable mOnChangeRunnable;
39     private Handler mMainHandler;
40     private Handler mBgHandler;
41 
GestureNavigationSettingsObserver( Handler mainHandler, Handler bgHandler, Context context, Runnable onChangeRunnable)42     public GestureNavigationSettingsObserver(
43             Handler mainHandler, Handler bgHandler, Context context, Runnable onChangeRunnable) {
44         super(mainHandler);
45         mMainHandler = mainHandler;
46         mBgHandler = bgHandler;
47         mContext = context;
48         mOnChangeRunnable = onChangeRunnable;
49     }
50 
51     private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
52             new DeviceConfig.OnPropertiesChangedListener() {
53         @Override
54         public void onPropertiesChanged(DeviceConfig.Properties properties) {
55             if (DeviceConfig.NAMESPACE_SYSTEMUI.equals(properties.getNamespace())
56                             && mOnChangeRunnable != null) {
57                 mOnChangeRunnable.run();
58             }
59         }
60     };
61 
62     /**
63      * Registers the observer for all users.
64      */
register()65     public void register() {
66         mBgHandler.post(() -> {
67             ContentResolver r = mContext.getContentResolver();
68             r.registerContentObserver(
69                     Settings.Secure.getUriFor(Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT),
70                     false, this, UserHandle.USER_ALL);
71             r.registerContentObserver(
72                     Settings.Secure.getUriFor(Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT),
73                     false, this, UserHandle.USER_ALL);
74             r.registerContentObserver(
75                     Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE),
76                     false, this, UserHandle.USER_ALL);
77             DeviceConfig.addOnPropertiesChangedListener(
78                     DeviceConfig.NAMESPACE_SYSTEMUI,
79                     runnable -> mMainHandler.post(runnable),
80                     mOnPropertiesChangedListener);
81         });
82     }
83 
84     /**
85      * Registers the observer for the calling user.
86      */
registerForCallingUser()87     public void registerForCallingUser() {
88         mBgHandler.post(() -> {
89             ContentResolver r = mContext.getContentResolver();
90             r.registerContentObserver(
91                     Settings.Secure.getUriFor(Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT),
92                     false, this);
93             r.registerContentObserver(
94                     Settings.Secure.getUriFor(Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT),
95                     false, this);
96             r.registerContentObserver(
97                     Settings.Secure.getUriFor(Settings.Secure.USER_SETUP_COMPLETE),
98                     false, this);
99             DeviceConfig.addOnPropertiesChangedListener(
100                     DeviceConfig.NAMESPACE_SYSTEMUI,
101                     runnable -> mMainHandler.post(runnable),
102                     mOnPropertiesChangedListener);
103         });
104     }
105 
unregister()106     public void unregister() {
107         mBgHandler.post(() -> {
108             mContext.getContentResolver().unregisterContentObserver(this);
109             DeviceConfig.removeOnPropertiesChangedListener(mOnPropertiesChangedListener);
110         });
111     }
112 
113     @Override
onChange(boolean selfChange)114     public void onChange(boolean selfChange) {
115         super.onChange(selfChange);
116         if (mOnChangeRunnable != null) {
117             mOnChangeRunnable.run();
118         }
119     }
120 
121     /**
122      * Returns the left sensitivity for the current user.  To be used in code that runs primarily
123      * in one user's process.
124      */
getLeftSensitivity(Resources userRes)125     public int getLeftSensitivity(Resources userRes) {
126         final float scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
127                 Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT, 1.0f, UserHandle.USER_CURRENT);
128         return (int) (getUnscaledInset(userRes) * scale);
129     }
130 
131     /**
132      * Returns the left sensitivity for the calling user.  To be used in code that runs in a
133      * per-user process.
134      */
135     @SuppressWarnings("NonUserGetterCalled")
getLeftSensitivityForCallingUser(Resources userRes)136     public int getLeftSensitivityForCallingUser(Resources userRes) {
137         final float scale = Settings.Secure.getFloat(mContext.getContentResolver(),
138                 Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT, 1.0f);
139         return (int) (getUnscaledInset(userRes) * scale);
140     }
141 
142     /**
143      * Returns the right sensitivity for the current user.  To be used in code that runs primarily
144      * in one user's process.
145      */
getRightSensitivity(Resources userRes)146     public int getRightSensitivity(Resources userRes) {
147         final float scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
148                 Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT, 1.0f, UserHandle.USER_CURRENT);
149         return (int) (getUnscaledInset(userRes) * scale);
150     }
151 
152     /**
153      * Returns the right sensitivity for the calling user.  To be used in code that runs in a
154      * per-user process.
155      */
156     @SuppressWarnings("NonUserGetterCalled")
getRightSensitivityForCallingUser(Resources userRes)157     public int getRightSensitivityForCallingUser(Resources userRes) {
158         final float scale = Settings.Secure.getFloat(mContext.getContentResolver(),
159                 Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT, 1.0f);
160         return (int) (getUnscaledInset(userRes) * scale);
161     }
162 
areNavigationButtonForcedVisible()163     public boolean areNavigationButtonForcedVisible() {
164         String SUWTheme = SystemProperties.get("setupwizard.theme", "");
165         boolean isExpressiveThemeEnabled = SUWTheme.equals("glif_expressive")
166                 || SUWTheme.equals("glif_expressive_light");
167         // The back gesture is enabled if using the expressive theme
168         return !isExpressiveThemeEnabled
169                 && Settings.Secure.getIntForUser(mContext.getContentResolver(),
170                     Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) == 0;
171     }
172 
getUnscaledInset(Resources userRes)173     private float getUnscaledInset(Resources userRes) {
174         final DisplayMetrics dm = userRes.getDisplayMetrics();
175         final float defaultInset = userRes.getDimension(
176                 com.android.internal.R.dimen.config_backGestureInset) / dm.density;
177         // Only apply the back gesture config if there is an existing inset
178         final float backGestureInset = defaultInset > 0
179                 ? DeviceConfig.getFloat(DeviceConfig.NAMESPACE_SYSTEMUI,
180                         BACK_GESTURE_EDGE_WIDTH, defaultInset)
181                 : defaultInset;
182         final float inset = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, backGestureInset,
183                 dm);
184         return inset;
185     }
186 }
187