• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.settings.gestures;
18 
19 import android.app.settings.SettingsEnums;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.res.Resources;
23 import android.content.res.TypedArray;
24 import android.os.Bundle;
25 import android.provider.Settings;
26 import android.view.WindowManager;
27 
28 import com.android.settings.R;
29 import com.android.settings.dashboard.DashboardFragment;
30 import com.android.settings.search.BaseSearchIndexProvider;
31 import com.android.settings.widget.LabeledSeekBarPreference;
32 import com.android.settings.widget.SeekBarPreference;
33 import com.android.settingslib.search.SearchIndexable;
34 import com.android.settingslib.widget.ButtonPreference;
35 
36 /**
37  * A fragment to include all the settings related to Gesture Navigation mode.
38  */
39 @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
40 public class GestureNavigationSettingsFragment extends DashboardFragment {
41 
42     public static final String TAG = "GestureNavigationSettingsFragment";
43 
44     public static final String GESTURE_NAVIGATION_SETTINGS =
45             "com.android.settings.GESTURE_NAVIGATION_SETTINGS";
46     static final String ACTION_GESTURE_SANDBOX = "com.android.quickstep.action.GESTURE_SANDBOX";
47 
48     private static final String LEFT_EDGE_SEEKBAR_KEY = "gesture_left_back_sensitivity";
49     private static final String RIGHT_EDGE_SEEKBAR_KEY = "gesture_right_back_sensitivity";
50     private static final String GESTURE_TUTORIAL_KEY = "assistant_gesture_navigation_tutorial";
51     final Intent mLaunchTutorialIntent =  new Intent(ACTION_GESTURE_SANDBOX)
52             .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
53             .putExtra("use_tutorial_menu", true);
54 
55     private WindowManager mWindowManager;
56     private BackGestureIndicatorView mIndicatorView;
57 
58     private float[] mBackGestureInsetScales;
59     private float mDefaultBackGestureInset;
60 
GestureNavigationSettingsFragment()61     public GestureNavigationSettingsFragment() {
62         super();
63     }
64 
65     @Override
onCreate(Bundle savedInstanceState)66     public void onCreate(Bundle savedInstanceState) {
67         super.onCreate(savedInstanceState);
68 
69         mIndicatorView = new BackGestureIndicatorView(getActivity());
70         mWindowManager = (WindowManager) getActivity().getSystemService(Context.WINDOW_SERVICE);
71     }
72 
73     @Override
onCreatePreferences(Bundle savedInstanceState, String rootKey)74     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
75         super.onCreatePreferences(savedInstanceState, rootKey);
76 
77         final Resources res = getActivity().getResources();
78         mDefaultBackGestureInset = res.getDimensionPixelSize(
79                 com.android.internal.R.dimen.config_backGestureInset);
80         mBackGestureInsetScales = getFloatArray(res.obtainTypedArray(
81                 com.android.internal.R.array.config_backGestureInsetScales));
82 
83         initSeekBarPreference(LEFT_EDGE_SEEKBAR_KEY);
84         initSeekBarPreference(RIGHT_EDGE_SEEKBAR_KEY);
85         initTutorialButton();
86     }
87 
88     @Override
onResume()89     public void onResume() {
90         super.onResume();
91 
92         mWindowManager.addView(mIndicatorView, mIndicatorView.getLayoutParams(
93                 getActivity().getWindow().getAttributes()));
94     }
95 
96     @Override
onPause()97     public void onPause() {
98         super.onPause();
99 
100         mWindowManager.removeView(mIndicatorView);
101     }
102 
103     @Override
getPreferenceScreenResId()104     protected int getPreferenceScreenResId() {
105         return R.xml.gesture_navigation_settings;
106     }
107 
108     @Override
getHelpResource()109     public int getHelpResource() {
110         // TODO(b/146001201): Replace with gesture navigation help page when ready.
111         return R.string.help_uri_default;
112     }
113 
114     @Override
getLogTag()115     protected String getLogTag() {
116         return TAG;
117     }
118 
119     @Override
getMetricsCategory()120     public int getMetricsCategory() {
121         return SettingsEnums.SETTINGS_GESTURE_NAV_BACK_SENSITIVITY_DLG;
122     }
123 
initTutorialButton()124     private void initTutorialButton() {
125         final ButtonPreference pref = getPreferenceScreen().findPreference(GESTURE_TUTORIAL_KEY);
126         if (pref == null) {
127             return;
128         }
129         if (!isGestureTutorialAvailable()) {
130             pref.setVisible(false);
131             return;
132         }
133         pref.setOnClickListener(preference -> {
134             startActivity(mLaunchTutorialIntent);
135         });
136     }
137 
isGestureTutorialAvailable()138     private boolean isGestureTutorialAvailable() {
139         Context context = getContext();
140         return context != null
141                 && mLaunchTutorialIntent.resolveActivity(context.getPackageManager()) != null;
142     }
143 
initSeekBarPreference(final String key)144     private void initSeekBarPreference(final String key) {
145         final LabeledSeekBarPreference pref = getPreferenceScreen().findPreference(key);
146         pref.setContinuousUpdates(true);
147         pref.setHapticFeedbackMode(SeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_TICKS);
148 
149         final String settingsKey = key == LEFT_EDGE_SEEKBAR_KEY
150                 ? Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT
151                 : Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT;
152         final float initScale = Settings.Secure.getFloat(
153                 getContext().getContentResolver(), settingsKey, 1.0f);
154 
155         // Find the closest value to initScale
156         float minDistance = Float.MAX_VALUE;
157         int minDistanceIndex = -1;
158         for (int i = 0; i < mBackGestureInsetScales.length; i++) {
159             float d = Math.abs(mBackGestureInsetScales[i] - initScale);
160             if (d < minDistance) {
161                 minDistance = d;
162                 minDistanceIndex = i;
163             }
164         }
165         pref.setProgress(minDistanceIndex);
166 
167         pref.setOnPreferenceChangeListener((p, v) -> {
168             final int width = (int) (mDefaultBackGestureInset * mBackGestureInsetScales[(int) v]);
169             mIndicatorView.setIndicatorWidth(width, key == LEFT_EDGE_SEEKBAR_KEY);
170             return true;
171         });
172 
173         pref.setOnPreferenceChangeStopListener((p, v) -> {
174             mIndicatorView.setIndicatorWidth(0, key == LEFT_EDGE_SEEKBAR_KEY);
175             final float scale = mBackGestureInsetScales[(int) v];
176             Settings.Secure.putFloat(getContext().getContentResolver(), settingsKey, scale);
177             return true;
178         });
179     }
180 
getFloatArray(TypedArray array)181     private static float[] getFloatArray(TypedArray array) {
182         int length = array.length();
183         float[] floatArray = new float[length];
184         for (int i = 0; i < length; i++) {
185             floatArray[i] = array.getFloat(i, 1.0f);
186         }
187         array.recycle();
188         return floatArray;
189     }
190 
191     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
192             new BaseSearchIndexProvider(R.xml.gesture_navigation_settings) {
193 
194                 @Override
195                 protected boolean isPageSearchEnabled(Context context) {
196                     return SystemNavigationPreferenceController.isGestureAvailable(context);
197                 }
198             };
199 
200 }
201