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