blob: 2c31e2cfea2ecd14be036f222da9e1c0fe757d59 [file] [log] [blame]
Matthew Ng1cf6eac2018-11-27 15:06:55 -08001/*
2 * Copyright (C) 2008 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
17package com.android.systemui.statusbar.phone;
18
19import android.annotation.IntDef;
20import android.content.Context;
Matthew Ngb831fb42019-01-30 11:20:48 -080021import android.content.res.Resources;
Matthew Ng1cf6eac2018-11-27 15:06:55 -080022import android.database.ContentObserver;
Matthew Ngb55c02c2019-02-15 16:20:31 -080023import android.graphics.Point;
Matthew Ng1cf6eac2018-11-27 15:06:55 -080024import android.net.Uri;
25import android.os.Handler;
26import android.provider.Settings;
Matthew Ng1cf6eac2018-11-27 15:06:55 -080027
Matthew Ng1cf6eac2018-11-27 15:06:55 -080028import java.lang.annotation.Retention;
29import java.lang.annotation.RetentionPolicy;
30
31/**
32 * Coordinates with the prototype settings plugin app that uses Settings.Global to allow different
33 * prototypes to run in the system. The class will handle communication changes from the settings
34 * app and call back to listeners.
35 */
36public class NavigationPrototypeController extends ContentObserver {
37 private static final String HIDE_BACK_BUTTON_SETTING = "quickstepcontroller_hideback";
Matthew Ngb8c30bb2018-12-21 15:25:48 -080038 private static final String HIDE_HOME_BUTTON_SETTING = "quickstepcontroller_hidehome";
Matthew Ngb831fb42019-01-30 11:20:48 -080039 private static final String PROTOTYPE_ENABLED = "prototype_enabled";
Matthew Ng1cf6eac2018-11-27 15:06:55 -080040
Matthew Ngb831fb42019-01-30 11:20:48 -080041 public static final String EDGE_SENSITIVITY_WIDTH_SETTING =
42 "quickstepcontroller_edge_width_sensitivity";
Matthew Ng1cf6eac2018-11-27 15:06:55 -080043 private final String GESTURE_MATCH_SETTING = "quickstepcontroller_gesture_match_map";
Matthew Ng355fe212018-12-14 17:42:38 -080044 public static final String NAV_COLOR_ADAPT_ENABLE_SETTING = "navbar_color_adapt_enable";
Matthew Ngb55c02c2019-02-15 16:20:31 -080045 public static final String SHOW_HOME_HANDLE_SETTING = "quickstepcontroller_showhandle";
Matthew Ng1cf6eac2018-11-27 15:06:55 -080046
47 @Retention(RetentionPolicy.SOURCE)
Matthew Ng0548fbc2019-01-11 12:24:13 -080048 @IntDef({ACTION_DEFAULT, ACTION_QUICKSTEP, ACTION_QUICKSCRUB, ACTION_BACK,
Matthew Ngf8869462019-01-18 13:31:47 -080049 ACTION_QUICKSWITCH, ACTION_NOTHING, ACTION_ASSISTANT, ACTION_EXPAND_NOTIFICATION})
Matthew Ng1cf6eac2018-11-27 15:06:55 -080050 @interface GestureAction {}
51 static final int ACTION_DEFAULT = 0;
52 static final int ACTION_QUICKSTEP = 1;
53 static final int ACTION_QUICKSCRUB = 2;
54 static final int ACTION_BACK = 3;
Matthew Ngb9c84282018-12-06 17:15:27 -080055 static final int ACTION_QUICKSWITCH = 4;
Matthew Ng0548fbc2019-01-11 12:24:13 -080056 static final int ACTION_NOTHING = 5;
57 static final int ACTION_ASSISTANT = 6;
Matthew Ngf8869462019-01-18 13:31:47 -080058 static final int ACTION_EXPAND_NOTIFICATION = 7;
Matthew Ng1cf6eac2018-11-27 15:06:55 -080059
60 private OnPrototypeChangedListener mListener;
61
62 /**
63 * Each index corresponds to a different action set in QuickStepController
64 * {@see updateSwipeLTRBackSetting}
65 */
Matthew Ngb9c84282018-12-06 17:15:27 -080066 private int[] mActionMap = new int[6];
Matthew Ng1cf6eac2018-11-27 15:06:55 -080067
68 private final Context mContext;
69
70 public NavigationPrototypeController(Handler handler, Context context) {
71 super(handler);
72 mContext = context;
73 updateSwipeLTRBackSetting();
74 }
75
76 public void setOnPrototypeChangedListener(OnPrototypeChangedListener listener) {
77 mListener = listener;
78 }
79
80 /**
81 * Observe all the settings to react to from prototype settings
82 */
83 public void register() {
84 registerObserver(HIDE_BACK_BUTTON_SETTING);
Matthew Ngb8c30bb2018-12-21 15:25:48 -080085 registerObserver(HIDE_HOME_BUTTON_SETTING);
Matthew Ng1cf6eac2018-11-27 15:06:55 -080086 registerObserver(GESTURE_MATCH_SETTING);
Matthew Ng355fe212018-12-14 17:42:38 -080087 registerObserver(NAV_COLOR_ADAPT_ENABLE_SETTING);
Matthew Ngb831fb42019-01-30 11:20:48 -080088 registerObserver(EDGE_SENSITIVITY_WIDTH_SETTING);
Matthew Ngb55c02c2019-02-15 16:20:31 -080089 registerObserver(SHOW_HOME_HANDLE_SETTING);
Matthew Ng1cf6eac2018-11-27 15:06:55 -080090 }
91
92 /**
93 * Disable observing settings to react to from prototype settings
94 */
95 public void unregister() {
96 mContext.getContentResolver().unregisterContentObserver(this);
97 }
98
99 @Override
100 public void onChange(boolean selfChange, Uri uri) {
101 super.onChange(selfChange, uri);
102 if (!selfChange && mListener != null) {
Matthew Ngb8c30bb2018-12-21 15:25:48 -0800103 final String path = uri.getPath();
104 if (path.endsWith(GESTURE_MATCH_SETTING)) {
105 // Get the settings gesture map corresponding to each action
106 // {@see updateSwipeLTRBackSetting}
107 updateSwipeLTRBackSetting();
108 mListener.onGestureRemap(mActionMap);
109 } else if (path.endsWith(HIDE_BACK_BUTTON_SETTING)) {
110 mListener.onBackButtonVisibilityChanged(
111 !getGlobalBool(HIDE_BACK_BUTTON_SETTING, false));
112 } else if (path.endsWith(HIDE_HOME_BUTTON_SETTING)) {
113 mListener.onHomeButtonVisibilityChanged(!hideHomeButton());
114 } else if (path.endsWith(NAV_COLOR_ADAPT_ENABLE_SETTING)) {
115 mListener.onColorAdaptChanged(
116 NavBarTintController.isEnabled(mContext));
Matthew Ngb55c02c2019-02-15 16:20:31 -0800117 } else if (path.endsWith(EDGE_SENSITIVITY_WIDTH_SETTING)) {
Matthew Ngb831fb42019-01-30 11:20:48 -0800118 mListener.onEdgeSensitivityChanged(getEdgeSensitivityWidth(),
119 getEdgeSensitivityHeight());
Matthew Ngb55c02c2019-02-15 16:20:31 -0800120 } else if (path.endsWith(SHOW_HOME_HANDLE_SETTING)) {
121 mListener.onHomeHandleVisiblilityChanged(showHomeHandle());
Matthew Ng1cf6eac2018-11-27 15:06:55 -0800122 }
123 }
124 }
125
Matthew Ngb55c02c2019-02-15 16:20:31 -0800126 /**
127 * @return the width for edge swipe
128 */
Matthew Ngb831fb42019-01-30 11:20:48 -0800129 public int getEdgeSensitivityWidth() {
130 return convertDpToPixel(getGlobalInt(EDGE_SENSITIVITY_WIDTH_SETTING, 0));
131 }
132
Matthew Ngb55c02c2019-02-15 16:20:31 -0800133 /**
134 * @return full screen height
135 */
Matthew Ngb831fb42019-01-30 11:20:48 -0800136 public int getEdgeSensitivityHeight() {
Matthew Ngb55c02c2019-02-15 16:20:31 -0800137 final Point size = new Point();
138 mContext.getDisplay().getRealSize(size);
139 return size.y;
Matthew Ngb831fb42019-01-30 11:20:48 -0800140 }
141
142 public boolean isEnabled() {
143 return getGlobalBool(PROTOTYPE_ENABLED, false);
144 }
145
Matthew Ng1cf6eac2018-11-27 15:06:55 -0800146 /**
147 * Retrieve the action map to apply to the quick step controller
148 * @return an action map
149 */
150 int[] getGestureActionMap() {
151 return mActionMap;
152 }
153
154 /**
Matthew Ngb8c30bb2018-12-21 15:25:48 -0800155 * @return if home button should be invisible
156 */
157 boolean hideHomeButton() {
158 return getGlobalBool(HIDE_HOME_BUTTON_SETTING, false /* default */);
159 }
160
Matthew Ngb55c02c2019-02-15 16:20:31 -0800161 boolean showHomeHandle() {
162 return getGlobalBool(SHOW_HOME_HANDLE_SETTING, false /* default */);
163 }
164
Matthew Ngb8c30bb2018-12-21 15:25:48 -0800165 /**
Matthew Ng1cf6eac2018-11-27 15:06:55 -0800166 * Since Settings.Global cannot pass arrays, use a string to represent each character as a
167 * gesture map to actions corresponding to {@see GestureAction}. The number is represented as:
168 * Number: [up] [down] [left] [right]
169 */
170 private void updateSwipeLTRBackSetting() {
171 String value = Settings.Global.getString(mContext.getContentResolver(),
172 GESTURE_MATCH_SETTING);
173 if (value != null) {
174 for (int i = 0; i < mActionMap.length; ++i) {
175 mActionMap[i] = Character.getNumericValue(value.charAt(i));
176 }
177 }
178 }
179
Matthew Ngb8c30bb2018-12-21 15:25:48 -0800180 private boolean getGlobalBool(String name, boolean defaultVal) {
181 return Settings.Global.getInt(mContext.getContentResolver(), name, defaultVal ? 1 : 0) == 1;
Matthew Ng1cf6eac2018-11-27 15:06:55 -0800182 }
183
Matthew Ngb831fb42019-01-30 11:20:48 -0800184 private int getGlobalInt(String name, int defaultVal) {
185 return Settings.Global.getInt(mContext.getContentResolver(), name, defaultVal);
186 }
187
Matthew Ng1cf6eac2018-11-27 15:06:55 -0800188 private void registerObserver(String name) {
189 mContext.getContentResolver()
190 .registerContentObserver(Settings.Global.getUriFor(name), false, this);
191 }
192
Matthew Ngb831fb42019-01-30 11:20:48 -0800193 private static int convertDpToPixel(float dp) {
194 return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
195 }
196
Matthew Ng1cf6eac2018-11-27 15:06:55 -0800197 public interface OnPrototypeChangedListener {
198 void onGestureRemap(@GestureAction int[] actions);
199 void onBackButtonVisibilityChanged(boolean visible);
Matthew Ngb8c30bb2018-12-21 15:25:48 -0800200 void onHomeButtonVisibilityChanged(boolean visible);
Matthew Ngb55c02c2019-02-15 16:20:31 -0800201 void onHomeHandleVisiblilityChanged(boolean visible);
Matthew Ng355fe212018-12-14 17:42:38 -0800202 void onColorAdaptChanged(boolean enabled);
Matthew Ngb831fb42019-01-30 11:20:48 -0800203 void onEdgeSensitivityChanged(int width, int height);
Matthew Ng1cf6eac2018-11-27 15:06:55 -0800204 }
205}