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