• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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;
18 
19 import com.android.internal.logging.MetricsLogger;
20 import com.android.internal.view.RotationPolicy;
21 import com.android.settings.DropDownPreference.Callback;
22 import com.android.settings.search.BaseSearchIndexProvider;
23 import com.android.settings.search.Indexable;
24 
25 import static android.provider.Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED;
26 import static android.provider.Settings.Secure.CAMERA_GESTURE_DISABLED;
27 import static android.provider.Settings.Secure.DOUBLE_TAP_TO_WAKE;
28 import static android.provider.Settings.Secure.DOZE_ENABLED;
29 import static android.provider.Settings.Secure.WAKE_GESTURE_ENABLED;
30 import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
31 import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
32 import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL;
33 import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
34 
35 import android.app.Activity;
36 import android.app.ActivityManagerNative;
37 import android.app.Dialog;
38 import android.app.UiModeManager;
39 import android.app.admin.DevicePolicyManager;
40 import android.content.ContentResolver;
41 import android.content.Context;
42 import android.content.res.Configuration;
43 import android.content.res.Resources;
44 import android.hardware.Sensor;
45 import android.hardware.SensorManager;
46 import android.os.Build;
47 import android.os.Bundle;
48 import android.os.RemoteException;
49 import android.os.SystemProperties;
50 import android.preference.ListPreference;
51 import android.preference.Preference;
52 import android.preference.Preference.OnPreferenceClickListener;
53 import android.preference.PreferenceScreen;
54 import android.preference.SwitchPreference;
55 import android.provider.SearchIndexableResource;
56 import android.provider.Settings;
57 import android.text.TextUtils;
58 import android.util.Log;
59 
60 import java.util.ArrayList;
61 import java.util.List;
62 
63 public class DisplaySettings extends SettingsPreferenceFragment implements
64         Preference.OnPreferenceChangeListener, OnPreferenceClickListener, Indexable {
65     private static final String TAG = "DisplaySettings";
66 
67     /** If there is no setting in the provider, use this. */
68     private static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000;
69 
70     private static final String KEY_SCREEN_TIMEOUT = "screen_timeout";
71     private static final String KEY_FONT_SIZE = "font_size";
72     private static final String KEY_SCREEN_SAVER = "screensaver";
73     private static final String KEY_LIFT_TO_WAKE = "lift_to_wake";
74     private static final String KEY_DOZE = "doze";
75     private static final String KEY_TAP_TO_WAKE = "tap_to_wake";
76     private static final String KEY_AUTO_BRIGHTNESS = "auto_brightness";
77     private static final String KEY_AUTO_ROTATE = "auto_rotate";
78     private static final String KEY_NIGHT_MODE = "night_mode";
79     private static final String KEY_CAMERA_GESTURE = "camera_gesture";
80     private static final String KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE
81             = "camera_double_tap_power_gesture";
82 
83     private static final int DLG_GLOBAL_CHANGE_WARNING = 1;
84 
85     private WarnedListPreference mFontSizePref;
86 
87     private final Configuration mCurConfig = new Configuration();
88 
89     private ListPreference mScreenTimeoutPreference;
90     private ListPreference mNightModePreference;
91     private Preference mScreenSaverPreference;
92     private SwitchPreference mLiftToWakePreference;
93     private SwitchPreference mDozePreference;
94     private SwitchPreference mTapToWakePreference;
95     private SwitchPreference mAutoBrightnessPreference;
96     private SwitchPreference mCameraGesturePreference;
97     private SwitchPreference mCameraDoubleTapPowerGesturePreference;
98 
99     @Override
getMetricsCategory()100     protected int getMetricsCategory() {
101         return MetricsLogger.DISPLAY;
102     }
103 
104     @Override
onCreate(Bundle savedInstanceState)105     public void onCreate(Bundle savedInstanceState) {
106         super.onCreate(savedInstanceState);
107         final Activity activity = getActivity();
108         final ContentResolver resolver = activity.getContentResolver();
109 
110         addPreferencesFromResource(R.xml.display_settings);
111 
112         mScreenSaverPreference = findPreference(KEY_SCREEN_SAVER);
113         if (mScreenSaverPreference != null
114                 && getResources().getBoolean(
115                         com.android.internal.R.bool.config_dreamsSupported) == false) {
116             getPreferenceScreen().removePreference(mScreenSaverPreference);
117         }
118 
119         mScreenTimeoutPreference = (ListPreference) findPreference(KEY_SCREEN_TIMEOUT);
120         final long currentTimeout = Settings.System.getLong(resolver, SCREEN_OFF_TIMEOUT,
121                 FALLBACK_SCREEN_TIMEOUT_VALUE);
122         mScreenTimeoutPreference.setValue(String.valueOf(currentTimeout));
123         mScreenTimeoutPreference.setOnPreferenceChangeListener(this);
124         disableUnusableTimeouts(mScreenTimeoutPreference);
125         updateTimeoutPreferenceDescription(currentTimeout);
126 
127         mFontSizePref = (WarnedListPreference) findPreference(KEY_FONT_SIZE);
128         mFontSizePref.setOnPreferenceChangeListener(this);
129         mFontSizePref.setOnPreferenceClickListener(this);
130 
131         if (isAutomaticBrightnessAvailable(getResources())) {
132             mAutoBrightnessPreference = (SwitchPreference) findPreference(KEY_AUTO_BRIGHTNESS);
133             mAutoBrightnessPreference.setOnPreferenceChangeListener(this);
134         } else {
135             removePreference(KEY_AUTO_BRIGHTNESS);
136         }
137 
138         if (isLiftToWakeAvailable(activity)) {
139             mLiftToWakePreference = (SwitchPreference) findPreference(KEY_LIFT_TO_WAKE);
140             mLiftToWakePreference.setOnPreferenceChangeListener(this);
141         } else {
142             removePreference(KEY_LIFT_TO_WAKE);
143         }
144 
145         if (isDozeAvailable(activity)) {
146             mDozePreference = (SwitchPreference) findPreference(KEY_DOZE);
147             mDozePreference.setOnPreferenceChangeListener(this);
148         } else {
149             removePreference(KEY_DOZE);
150         }
151 
152         if (isTapToWakeAvailable(getResources())) {
153             mTapToWakePreference = (SwitchPreference) findPreference(KEY_TAP_TO_WAKE);
154             mTapToWakePreference.setOnPreferenceChangeListener(this);
155         } else {
156             removePreference(KEY_TAP_TO_WAKE);
157         }
158 
159         if (isCameraGestureAvailable(getResources())) {
160             mCameraGesturePreference = (SwitchPreference) findPreference(KEY_CAMERA_GESTURE);
161             mCameraGesturePreference.setOnPreferenceChangeListener(this);
162         } else {
163             removePreference(KEY_CAMERA_GESTURE);
164         }
165 
166         if (isCameraDoubleTapPowerGestureAvailable(getResources())) {
167             mCameraDoubleTapPowerGesturePreference
168                     = (SwitchPreference) findPreference(KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE);
169             mCameraDoubleTapPowerGesturePreference.setOnPreferenceChangeListener(this);
170         } else {
171             removePreference(KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE);
172         }
173 
174         if (RotationPolicy.isRotationLockToggleVisible(activity)) {
175             DropDownPreference rotatePreference =
176                     (DropDownPreference) findPreference(KEY_AUTO_ROTATE);
177             rotatePreference.addItem(activity.getString(R.string.display_auto_rotate_rotate),
178                     false);
179             int rotateLockedResourceId;
180             // The following block sets the string used when rotation is locked.
181             // If the device locks specifically to portrait or landscape (rather than current
182             // rotation), then we use a different string to include this information.
183             if (allowAllRotations(activity)) {
184                 rotateLockedResourceId = R.string.display_auto_rotate_stay_in_current;
185             } else {
186                 if (RotationPolicy.getRotationLockOrientation(activity)
187                         == Configuration.ORIENTATION_PORTRAIT) {
188                     rotateLockedResourceId =
189                             R.string.display_auto_rotate_stay_in_portrait;
190                 } else {
191                     rotateLockedResourceId =
192                             R.string.display_auto_rotate_stay_in_landscape;
193                 }
194             }
195             rotatePreference.addItem(activity.getString(rotateLockedResourceId), true);
196             rotatePreference.setSelectedItem(RotationPolicy.isRotationLocked(activity) ?
197                     1 : 0);
198             rotatePreference.setCallback(new Callback() {
199                 @Override
200                 public boolean onItemSelected(int pos, Object value) {
201                     final boolean locked = (Boolean) value;
202                     MetricsLogger.action(getActivity(), MetricsLogger.ACTION_ROTATION_LOCK,
203                             locked);
204                     RotationPolicy.setRotationLock(activity, locked);
205                     return true;
206                 }
207             });
208         } else {
209             removePreference(KEY_AUTO_ROTATE);
210         }
211 
212         mNightModePreference = (ListPreference) findPreference(KEY_NIGHT_MODE);
213         if (mNightModePreference != null) {
214             final UiModeManager uiManager = (UiModeManager) getSystemService(
215                     Context.UI_MODE_SERVICE);
216             final int currentNightMode = uiManager.getNightMode();
217             mNightModePreference.setValue(String.valueOf(currentNightMode));
218             mNightModePreference.setOnPreferenceChangeListener(this);
219         }
220     }
221 
allowAllRotations(Context context)222     private static boolean allowAllRotations(Context context) {
223         return Resources.getSystem().getBoolean(
224                 com.android.internal.R.bool.config_allowAllRotations);
225     }
226 
isLiftToWakeAvailable(Context context)227     private static boolean isLiftToWakeAvailable(Context context) {
228         SensorManager sensors = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
229         return sensors != null && sensors.getDefaultSensor(Sensor.TYPE_WAKE_GESTURE) != null;
230     }
231 
isDozeAvailable(Context context)232     private static boolean isDozeAvailable(Context context) {
233         String name = Build.IS_DEBUGGABLE ? SystemProperties.get("debug.doze.component") : null;
234         if (TextUtils.isEmpty(name)) {
235             name = context.getResources().getString(
236                     com.android.internal.R.string.config_dozeComponent);
237         }
238         return !TextUtils.isEmpty(name);
239     }
240 
isTapToWakeAvailable(Resources res)241     private static boolean isTapToWakeAvailable(Resources res) {
242         return res.getBoolean(com.android.internal.R.bool.config_supportDoubleTapWake);
243     }
244 
isAutomaticBrightnessAvailable(Resources res)245     private static boolean isAutomaticBrightnessAvailable(Resources res) {
246         return res.getBoolean(com.android.internal.R.bool.config_automatic_brightness_available);
247     }
248 
isCameraGestureAvailable(Resources res)249     private static boolean isCameraGestureAvailable(Resources res) {
250         boolean configSet = res.getInteger(
251                 com.android.internal.R.integer.config_cameraLaunchGestureSensorType) != -1;
252         return configSet &&
253                 !SystemProperties.getBoolean("gesture.disable_camera_launch", false);
254     }
255 
isCameraDoubleTapPowerGestureAvailable(Resources res)256     private static boolean isCameraDoubleTapPowerGestureAvailable(Resources res) {
257         return res.getBoolean(
258                 com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled);
259     }
260 
updateTimeoutPreferenceDescription(long currentTimeout)261     private void updateTimeoutPreferenceDescription(long currentTimeout) {
262         ListPreference preference = mScreenTimeoutPreference;
263         String summary;
264         if (currentTimeout < 0) {
265             // Unsupported value
266             summary = "";
267         } else {
268             final CharSequence[] entries = preference.getEntries();
269             final CharSequence[] values = preference.getEntryValues();
270             if (entries == null || entries.length == 0) {
271                 summary = "";
272             } else {
273                 int best = 0;
274                 for (int i = 0; i < values.length; i++) {
275                     long timeout = Long.parseLong(values[i].toString());
276                     if (currentTimeout >= timeout) {
277                         best = i;
278                     }
279                 }
280                 summary = preference.getContext().getString(R.string.screen_timeout_summary,
281                         entries[best]);
282             }
283         }
284         preference.setSummary(summary);
285     }
286 
disableUnusableTimeouts(ListPreference screenTimeoutPreference)287     private void disableUnusableTimeouts(ListPreference screenTimeoutPreference) {
288         final DevicePolicyManager dpm =
289                 (DevicePolicyManager) getActivity().getSystemService(
290                 Context.DEVICE_POLICY_SERVICE);
291         final long maxTimeout = dpm != null ? dpm.getMaximumTimeToLock(null) : 0;
292         if (maxTimeout == 0) {
293             return; // policy not enforced
294         }
295         final CharSequence[] entries = screenTimeoutPreference.getEntries();
296         final CharSequence[] values = screenTimeoutPreference.getEntryValues();
297         ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>();
298         ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>();
299         for (int i = 0; i < values.length; i++) {
300             long timeout = Long.parseLong(values[i].toString());
301             if (timeout <= maxTimeout) {
302                 revisedEntries.add(entries[i]);
303                 revisedValues.add(values[i]);
304             }
305         }
306         if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) {
307             final int userPreference = Integer.parseInt(screenTimeoutPreference.getValue());
308             screenTimeoutPreference.setEntries(
309                     revisedEntries.toArray(new CharSequence[revisedEntries.size()]));
310             screenTimeoutPreference.setEntryValues(
311                     revisedValues.toArray(new CharSequence[revisedValues.size()]));
312             if (userPreference <= maxTimeout) {
313                 screenTimeoutPreference.setValue(String.valueOf(userPreference));
314             } else if (revisedValues.size() > 0
315                     && Long.parseLong(revisedValues.get(revisedValues.size() - 1).toString())
316                     == maxTimeout) {
317                 // If the last one happens to be the same as the max timeout, select that
318                 screenTimeoutPreference.setValue(String.valueOf(maxTimeout));
319             } else {
320                 // There will be no highlighted selection since nothing in the list matches
321                 // maxTimeout. The user can still select anything less than maxTimeout.
322                 // TODO: maybe append maxTimeout to the list and mark selected.
323             }
324         }
325         screenTimeoutPreference.setEnabled(revisedEntries.size() > 0);
326     }
327 
floatToIndex(float val)328     int floatToIndex(float val) {
329         String[] indices = getResources().getStringArray(R.array.entryvalues_font_size);
330         float lastVal = Float.parseFloat(indices[0]);
331         for (int i=1; i<indices.length; i++) {
332             float thisVal = Float.parseFloat(indices[i]);
333             if (val < (lastVal + (thisVal-lastVal)*.5f)) {
334                 return i-1;
335             }
336             lastVal = thisVal;
337         }
338         return indices.length-1;
339     }
340 
readFontSizePreference(ListPreference pref)341     public void readFontSizePreference(ListPreference pref) {
342         try {
343             mCurConfig.updateFrom(ActivityManagerNative.getDefault().getConfiguration());
344         } catch (RemoteException e) {
345             Log.w(TAG, "Unable to retrieve font size");
346         }
347 
348         // mark the appropriate item in the preferences list
349         int index = floatToIndex(mCurConfig.fontScale);
350         pref.setValueIndex(index);
351 
352         // report the current size in the summary text
353         final Resources res = getResources();
354         String[] fontSizeNames = res.getStringArray(R.array.entries_font_size);
355         pref.setSummary(String.format(res.getString(R.string.summary_font_size),
356                 fontSizeNames[index]));
357     }
358 
359     @Override
onResume()360     public void onResume() {
361         super.onResume();
362         updateState();
363     }
364 
365     @Override
onCreateDialog(int dialogId)366     public Dialog onCreateDialog(int dialogId) {
367         if (dialogId == DLG_GLOBAL_CHANGE_WARNING) {
368             return Utils.buildGlobalChangeWarningDialog(getActivity(),
369                     R.string.global_font_change_title,
370                     new Runnable() {
371                         public void run() {
372                             mFontSizePref.click();
373                         }
374                     });
375         }
376         return null;
377     }
378 
379     private void updateState() {
380         readFontSizePreference(mFontSizePref);
381         updateScreenSaverSummary();
382 
383         // Update auto brightness if it is available.
384         if (mAutoBrightnessPreference != null) {
385             int brightnessMode = Settings.System.getInt(getContentResolver(),
386                     SCREEN_BRIGHTNESS_MODE, SCREEN_BRIGHTNESS_MODE_MANUAL);
387             mAutoBrightnessPreference.setChecked(brightnessMode != SCREEN_BRIGHTNESS_MODE_MANUAL);
388         }
389 
390         // Update lift-to-wake if it is available.
391         if (mLiftToWakePreference != null) {
392             int value = Settings.Secure.getInt(getContentResolver(), WAKE_GESTURE_ENABLED, 0);
393             mLiftToWakePreference.setChecked(value != 0);
394         }
395 
396         // Update doze if it is available.
397         if (mDozePreference != null) {
398             int value = Settings.Secure.getInt(getContentResolver(), DOZE_ENABLED, 1);
399             mDozePreference.setChecked(value != 0);
400         }
401 
402         // Update tap to wake if it is available.
403         if (mTapToWakePreference != null) {
404             int value = Settings.Secure.getInt(getContentResolver(), DOUBLE_TAP_TO_WAKE, 0);
405             mTapToWakePreference.setChecked(value != 0);
406         }
407 
408         // Update camera gesture #1 if it is available.
409         if (mCameraGesturePreference != null) {
410             int value = Settings.Secure.getInt(getContentResolver(), CAMERA_GESTURE_DISABLED, 0);
411             mCameraGesturePreference.setChecked(value == 0);
412         }
413 
414         // Update camera gesture #2 if it is available.
415         if (mCameraDoubleTapPowerGesturePreference != null) {
416             int value = Settings.Secure.getInt(
417                     getContentResolver(), CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0);
418             mCameraDoubleTapPowerGesturePreference.setChecked(value == 0);
419         }
420     }
421 
422     private void updateScreenSaverSummary() {
423         if (mScreenSaverPreference != null) {
424             mScreenSaverPreference.setSummary(
425                     DreamSettings.getSummaryTextWithDreamName(getActivity()));
426         }
427     }
428 
429     public void writeFontSizePreference(Object objValue) {
430         try {
431             mCurConfig.fontScale = Float.parseFloat(objValue.toString());
432             ActivityManagerNative.getDefault().updatePersistentConfiguration(mCurConfig);
433         } catch (RemoteException e) {
434             Log.w(TAG, "Unable to save font size");
435         }
436     }
437 
438     @Override
439     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
440         return super.onPreferenceTreeClick(preferenceScreen, preference);
441     }
442 
443     @Override
444     public boolean onPreferenceChange(Preference preference, Object objValue) {
445         final String key = preference.getKey();
446         if (KEY_SCREEN_TIMEOUT.equals(key)) {
447             try {
448                 int value = Integer.parseInt((String) objValue);
449                 Settings.System.putInt(getContentResolver(), SCREEN_OFF_TIMEOUT, value);
450                 updateTimeoutPreferenceDescription(value);
451             } catch (NumberFormatException e) {
452                 Log.e(TAG, "could not persist screen timeout setting", e);
453             }
454         }
455         if (KEY_FONT_SIZE.equals(key)) {
456             writeFontSizePreference(objValue);
457         }
458         if (preference == mAutoBrightnessPreference) {
459             boolean auto = (Boolean) objValue;
460             Settings.System.putInt(getContentResolver(), SCREEN_BRIGHTNESS_MODE,
461                     auto ? SCREEN_BRIGHTNESS_MODE_AUTOMATIC : SCREEN_BRIGHTNESS_MODE_MANUAL);
462         }
463         if (preference == mLiftToWakePreference) {
464             boolean value = (Boolean) objValue;
465             Settings.Secure.putInt(getContentResolver(), WAKE_GESTURE_ENABLED, value ? 1 : 0);
466         }
467         if (preference == mDozePreference) {
468             boolean value = (Boolean) objValue;
469             Settings.Secure.putInt(getContentResolver(), DOZE_ENABLED, value ? 1 : 0);
470         }
471         if (preference == mTapToWakePreference) {
472             boolean value = (Boolean) objValue;
473             Settings.Secure.putInt(getContentResolver(), DOUBLE_TAP_TO_WAKE, value ? 1 : 0);
474         }
475         if (preference == mCameraGesturePreference) {
476             boolean value = (Boolean) objValue;
477             Settings.Secure.putInt(getContentResolver(), CAMERA_GESTURE_DISABLED,
478                     value ? 0 : 1 /* Backwards because setting is for disabling */);
479         }
480         if (preference == mCameraDoubleTapPowerGesturePreference) {
481             boolean value = (Boolean) objValue;
482             Settings.Secure.putInt(getContentResolver(), CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED,
483                     value ? 0 : 1 /* Backwards because setting is for disabling */);
484         }
485         if (preference == mNightModePreference) {
486             try {
487                 final int value = Integer.parseInt((String) objValue);
488                 final UiModeManager uiManager = (UiModeManager) getSystemService(
489                         Context.UI_MODE_SERVICE);
490                 uiManager.setNightMode(value);
491             } catch (NumberFormatException e) {
492                 Log.e(TAG, "could not persist night mode setting", e);
493             }
494         }
495         return true;
496     }
497 
498     @Override
499     public boolean onPreferenceClick(Preference preference) {
500         if (preference == mFontSizePref) {
501             if (Utils.hasMultipleUsers(getActivity())) {
502                 showDialog(DLG_GLOBAL_CHANGE_WARNING);
503                 return true;
504             } else {
505                 mFontSizePref.click();
506             }
507         }
508         return false;
509     }
510 
511     @Override
512     protected int getHelpResource() {
513         return R.string.help_uri_display;
514     }
515 
516     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
517             new BaseSearchIndexProvider() {
518                 @Override
519                 public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
520                         boolean enabled) {
521                     ArrayList<SearchIndexableResource> result =
522                             new ArrayList<SearchIndexableResource>();
523 
524                     SearchIndexableResource sir = new SearchIndexableResource(context);
525                     sir.xmlResId = R.xml.display_settings;
526                     result.add(sir);
527 
528                     return result;
529                 }
530 
531                 @Override
532                 public List<String> getNonIndexableKeys(Context context) {
533                     ArrayList<String> result = new ArrayList<String>();
534                     if (!context.getResources().getBoolean(
535                             com.android.internal.R.bool.config_dreamsSupported)) {
536                         result.add(KEY_SCREEN_SAVER);
537                     }
538                     if (!isAutomaticBrightnessAvailable(context.getResources())) {
539                         result.add(KEY_AUTO_BRIGHTNESS);
540                     }
541                     if (!isLiftToWakeAvailable(context)) {
542                         result.add(KEY_LIFT_TO_WAKE);
543                     }
544                     if (!isDozeAvailable(context)) {
545                         result.add(KEY_DOZE);
546                     }
547                     if (!RotationPolicy.isRotationLockToggleVisible(context)) {
548                         result.add(KEY_AUTO_ROTATE);
549                     }
550                     if (!isTapToWakeAvailable(context.getResources())) {
551                         result.add(KEY_TAP_TO_WAKE);
552                     }
553                     if (!isCameraGestureAvailable(context.getResources())) {
554                         result.add(KEY_CAMERA_GESTURE);
555                     }
556                     if (!isCameraDoubleTapPowerGestureAvailable(context.getResources())) {
557                         result.add(KEY_CAMERA_DOUBLE_TAP_POWER_GESTURE);
558                     }
559                     return result;
560                 }
561             };
562 }
563