/* * Copyright (C) 2013 The CyanogenMod project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings; import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.os.RemoteException; import android.os.Handler; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceCategory; import android.preference.PreferenceManager; import android.preference.PreferenceScreen; import android.preference.SwitchPreference; import android.provider.Settings; import android.util.Log; import android.view.IWindowManager; import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.WindowManagerGlobal; import com.android.internal.logging.MetricsLogger; import com.android.settings.R; import com.android.settings.SettingsPreferenceFragment; import com.android.settings.Utils; import org.cyanogenmod.hardware.KeyDisabler; public class ButtonSettings extends SettingsPreferenceFragment implements Preference.OnPreferenceChangeListener { private static final String TAG = "SystemSettings"; private static final String KEY_HOME_LONG_PRESS = "hardware_keys_home_long_press"; private static final String KEY_HOME_DOUBLE_TAP = "hardware_keys_home_double_tap"; private static final String KEY_MENU_PRESS = "hardware_keys_menu_press"; private static final String KEY_MENU_LONG_PRESS = "hardware_keys_menu_long_press"; private static final String KEY_APP_SWITCH_PRESS = "hardware_keys_app_switch_press"; private static final String KEY_APP_SWITCH_LONG_PRESS = "hardware_keys_app_switch_long_press"; private static final String KEY_VOLUME_KEY_CURSOR_CONTROL = "volume_key_cursor_control"; private static final String DISABLE_NAV_KEYS = "disable_nav_keys"; private static final String KEY_POWER_END_CALL = "power_end_call"; private static final String KEY_HOME_ANSWER_CALL = "home_answer_call"; private static final String CATEGORY_POWER = "power_key"; private static final String CATEGORY_HOME = "home_key"; private static final String CATEGORY_BACK = "back_key"; private static final String CATEGORY_MENU = "menu_key"; private static final String CATEGORY_ASSIST = "assist_key"; private static final String CATEGORY_APPSWITCH = "app_switch_key"; private static final String CATEGORY_CAMERA = "camera_key"; private static final String CATEGORY_VOLUME = "volume_keys"; private static final String CATEGORY_BACKLIGHT = "key_backlight"; private static final String CATEGORY_NAVBAR = "navigation_bar"; // Available custom actions to perform on a key press. // Must match values for KEY_HOME_LONG_PRESS_ACTION in: // frameworks/base/core/java/android/provider/Settings.java private static final int ACTION_NOTHING = 0; private static final int ACTION_MENU = 1; private static final int ACTION_APP_SWITCH = 2; private static final int ACTION_SEARCH = 3; private static final int ACTION_VOICE_SEARCH = 4; private static final int ACTION_IN_APP_SEARCH = 5; private static final int ACTION_LAUNCH_CAMERA = 6; private static final int ACTION_SLEEP = 7; private static final int ACTION_LAST_APP = 8; // Masks for checking presence of hardware keys. // Must match values in frameworks/base/core/res/res/values/config.xml public static final int KEY_MASK_HOME = 0x01; public static final int KEY_MASK_BACK = 0x02; public static final int KEY_MASK_MENU = 0x04; public static final int KEY_MASK_ASSIST = 0x08; public static final int KEY_MASK_APP_SWITCH = 0x10; public static final int KEY_MASK_CAMERA = 0x20; public static final int KEY_MASK_VOLUME = 0x40; private ListPreference mHomeLongPressAction; private ListPreference mHomeDoubleTapAction; private ListPreference mMenuPressAction; private ListPreference mMenuLongPressAction; private ListPreference mAppSwitchPressAction; private ListPreference mAppSwitchLongPressAction; private ListPreference mVolumeKeyCursorControl; private SwitchPreference mDisableNavigationKeys; private SwitchPreference mPowerEndCall; private SwitchPreference mHomeAnswerCall; private PreferenceCategory mNavigationPreferencesCat; private Handler mHandler; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.button_settings); final Resources res = getResources(); final ContentResolver resolver = getActivity().getContentResolver(); final PreferenceScreen prefScreen = getPreferenceScreen(); final int deviceKeys = getResources().getInteger( com.android.internal.R.integer.config_deviceHardwareKeys); final int deviceWakeKeys = getResources().getInteger( com.android.internal.R.integer.config_deviceHardwareWakeKeys); final boolean hasPowerKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER); final boolean hasHomeKey = (deviceKeys & KEY_MASK_HOME) != 0; final boolean hasBackKey = (deviceKeys & KEY_MASK_BACK) != 0; final boolean hasMenuKey = (deviceKeys & KEY_MASK_MENU) != 0; final boolean hasAssistKey = (deviceKeys & KEY_MASK_ASSIST) != 0; final boolean hasAppSwitchKey = (deviceKeys & KEY_MASK_APP_SWITCH) != 0; final boolean hasVolumeKeys = (deviceKeys & KEY_MASK_VOLUME) != 0; final boolean showHomeWake = (deviceWakeKeys & KEY_MASK_HOME) != 0; final boolean showBackWake = (deviceWakeKeys & KEY_MASK_BACK) != 0; final boolean showMenuWake = (deviceWakeKeys & KEY_MASK_MENU) != 0; final boolean showVolumeWake = (deviceWakeKeys & KEY_MASK_VOLUME) != 0; boolean hasAnyBindableKey = false; final PreferenceCategory powerCategory = (PreferenceCategory) prefScreen.findPreference(CATEGORY_POWER); final PreferenceCategory homeCategory = (PreferenceCategory) prefScreen.findPreference(CATEGORY_HOME); final PreferenceCategory backCategory = (PreferenceCategory) prefScreen.findPreference(CATEGORY_BACK); final PreferenceCategory menuCategory = (PreferenceCategory) prefScreen.findPreference(CATEGORY_MENU); final PreferenceCategory appSwitchCategory = (PreferenceCategory) prefScreen.findPreference(CATEGORY_APPSWITCH); final PreferenceCategory volumeCategory = (PreferenceCategory) prefScreen.findPreference(CATEGORY_VOLUME); // Power button ends calls. mPowerEndCall = (SwitchPreference) findPreference(KEY_POWER_END_CALL); // Home button answers calls. mHomeAnswerCall = (SwitchPreference) findPreference(KEY_HOME_ANSWER_CALL); mHandler = new Handler(); // Force Navigation bar related options mDisableNavigationKeys = (SwitchPreference) findPreference(DISABLE_NAV_KEYS); // Only visible on devices that does not have a navigation bar already, // and don't even try unless the existing keys can be disabled boolean needsNavigationBar = false; if (KeyDisabler.isSupported()) { try { IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); needsNavigationBar = wm.needsNavigationBar(); } catch (RemoteException e) { } if (needsNavigationBar) { prefScreen.removePreference(mDisableNavigationKeys); } else { // Remove keys that can be provided by the navbar updateDisableNavkeysOption(); } } else { prefScreen.removePreference(mDisableNavigationKeys); } if (hasPowerKey) { if (!Utils.isVoiceCapable(getActivity())) { powerCategory.removePreference(mPowerEndCall); mPowerEndCall = null; prefScreen.removePreference(powerCategory); } } else { prefScreen.removePreference(powerCategory); } if (hasHomeKey) { if (!showHomeWake) { homeCategory.removePreference(findPreference(Settings.System.HOME_WAKE_SCREEN)); } if (!Utils.isVoiceCapable(getActivity())) { homeCategory.removePreference(mHomeAnswerCall); mHomeAnswerCall = null; } int defaultLongPressAction = res.getInteger( com.android.internal.R.integer.config_longPressOnHomeBehavior); if (defaultLongPressAction < ACTION_NOTHING || defaultLongPressAction > ACTION_LAST_APP) { defaultLongPressAction = ACTION_NOTHING; } int defaultDoubleTapAction = res.getInteger( com.android.internal.R.integer.config_doubleTapOnHomeBehavior); if (defaultDoubleTapAction < ACTION_NOTHING || defaultDoubleTapAction > ACTION_LAST_APP) { defaultDoubleTapAction = ACTION_NOTHING; } int longPressAction = Settings.System.getInt(resolver, Settings.System.KEY_HOME_LONG_PRESS_ACTION, defaultLongPressAction); mHomeLongPressAction = initActionList(KEY_HOME_LONG_PRESS, longPressAction); int doubleTapAction = Settings.System.getInt(resolver, Settings.System.KEY_HOME_DOUBLE_TAP_ACTION, defaultDoubleTapAction); mHomeDoubleTapAction = initActionList(KEY_HOME_DOUBLE_TAP, doubleTapAction); hasAnyBindableKey = true; } else { prefScreen.removePreference(homeCategory); } if (hasBackKey) { if (!showBackWake) { backCategory.removePreference(findPreference(Settings.System.BACK_WAKE_SCREEN)); prefScreen.removePreference(backCategory); } } else { prefScreen.removePreference(backCategory); } if (hasMenuKey) { if (!showMenuWake) { menuCategory.removePreference(findPreference(Settings.System.MENU_WAKE_SCREEN)); } int pressAction = Settings.System.getInt(resolver, Settings.System.KEY_MENU_ACTION, ACTION_MENU); mMenuPressAction = initActionList(KEY_MENU_PRESS, pressAction); int longPressAction = Settings.System.getInt(resolver, Settings.System.KEY_MENU_LONG_PRESS_ACTION, hasAssistKey ? ACTION_NOTHING : ACTION_SEARCH); mMenuLongPressAction = initActionList(KEY_MENU_LONG_PRESS, longPressAction); hasAnyBindableKey = true; } else { prefScreen.removePreference(menuCategory); } if (hasAppSwitchKey) { int pressAction = Settings.System.getInt(resolver, Settings.System.KEY_APP_SWITCH_ACTION, ACTION_APP_SWITCH); mAppSwitchPressAction = initActionList(KEY_APP_SWITCH_PRESS, pressAction); int longPressAction = Settings.System.getInt(resolver, Settings.System.KEY_APP_SWITCH_LONG_PRESS_ACTION, ACTION_NOTHING); mAppSwitchLongPressAction = initActionList(KEY_APP_SWITCH_LONG_PRESS, longPressAction); hasAnyBindableKey = true; } else { prefScreen.removePreference(appSwitchCategory); } if (Utils.hasVolumeRocker(getActivity())) { if (!showVolumeWake) { volumeCategory.removePreference(findPreference(Settings.System.VOLUME_WAKE_SCREEN)); } int cursorControlAction = Settings.System.getInt(resolver, Settings.System.VOLUME_KEY_CURSOR_CONTROL, 0); mVolumeKeyCursorControl = initActionList(KEY_VOLUME_KEY_CURSOR_CONTROL, cursorControlAction); } else { prefScreen.removePreference(volumeCategory); } } @Override public void onResume() { super.onResume(); // Power button ends calls. if (mPowerEndCall != null) { final int incallPowerBehavior = Settings.Secure.getInt(getContentResolver(), Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT); final boolean powerButtonEndsCall = (incallPowerBehavior == Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP); mPowerEndCall.setChecked(powerButtonEndsCall); } // Home button answers calls. if (mHomeAnswerCall != null) { final int incallHomeBehavior = Settings.Secure.getInt(getContentResolver(), Settings.Secure.RING_HOME_BUTTON_BEHAVIOR, Settings.Secure.RING_HOME_BUTTON_BEHAVIOR_DEFAULT); final boolean homeButtonAnswersCall = (incallHomeBehavior == Settings.Secure.RING_HOME_BUTTON_BEHAVIOR_ANSWER); mHomeAnswerCall.setChecked(homeButtonAnswersCall); } } private ListPreference initActionList(String key, int value) { ListPreference list = (ListPreference) getPreferenceScreen().findPreference(key); list.setValue(Integer.toString(value)); list.setSummary(list.getEntry()); list.setOnPreferenceChangeListener(this); return list; } private void handleActionListChange(ListPreference pref, Object newValue, String setting) { String value = (String) newValue; int index = pref.findIndexOfValue(value); pref.setSummary(pref.getEntries()[index]); Settings.System.putInt(getContentResolver(), setting, Integer.valueOf(value)); } @Override protected int getMetricsCategory() { return MetricsLogger.DONT_TRACK_ME_BRO; } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { if (preference == mHomeLongPressAction) { handleActionListChange(mHomeLongPressAction, newValue, Settings.System.KEY_HOME_LONG_PRESS_ACTION); return true; } else if (preference == mHomeDoubleTapAction) { handleActionListChange(mHomeDoubleTapAction, newValue, Settings.System.KEY_HOME_DOUBLE_TAP_ACTION); return true; } else if (preference == mMenuPressAction) { handleActionListChange(mMenuPressAction, newValue, Settings.System.KEY_MENU_ACTION); return true; } else if (preference == mMenuLongPressAction) { handleActionListChange(mMenuLongPressAction, newValue, Settings.System.KEY_MENU_LONG_PRESS_ACTION); return true; } else if (preference == mAppSwitchPressAction) { handleActionListChange(mAppSwitchPressAction, newValue, Settings.System.KEY_APP_SWITCH_ACTION); return true; } else if (preference == mAppSwitchLongPressAction) { handleActionListChange(mAppSwitchLongPressAction, newValue, Settings.System.KEY_APP_SWITCH_LONG_PRESS_ACTION); return true; } else if (preference == mVolumeKeyCursorControl) { handleActionListChange(mVolumeKeyCursorControl, newValue, Settings.System.VOLUME_KEY_CURSOR_CONTROL); return true; } return false; } private static void writeDisableNavkeysOption(Context context, boolean enabled) { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); final int defaultBrightness = context.getResources().getInteger( com.android.internal.R.integer.config_buttonBrightnessSettingDefault); Settings.System.putInt(context.getContentResolver(), Settings.System.DEV_FORCE_SHOW_NAVBAR, enabled ? 1 : 0); KeyDisabler.setActive(enabled); /* Save/restore button timeouts to disable them in softkey mode */ Editor editor = prefs.edit(); if (enabled) { int currentBrightness = Settings.System.getInt(context.getContentResolver(), Settings.System.BUTTON_BRIGHTNESS, defaultBrightness); if (!prefs.contains("pre_navbar_button_backlight")) { editor.putInt("pre_navbar_button_backlight", currentBrightness); } Settings.System.putInt(context.getContentResolver(), Settings.System.BUTTON_BRIGHTNESS, 0); } else { Settings.System.putInt(context.getContentResolver(), Settings.System.BUTTON_BRIGHTNESS, prefs.getInt("pre_navbar_button_backlight", defaultBrightness)); editor.remove("pre_navbar_button_backlight"); } editor.commit(); } private void updateDisableNavkeysOption() { boolean enabled = Settings.System.getInt(getActivity().getContentResolver(), Settings.System.DEV_FORCE_SHOW_NAVBAR, 0) != 0; mDisableNavigationKeys.setChecked(enabled); final PreferenceScreen prefScreen = getPreferenceScreen(); /* Disable hw-key options if they're disabled */ final PreferenceCategory homeCategory = (PreferenceCategory) prefScreen.findPreference(CATEGORY_HOME); final PreferenceCategory menuCategory = (PreferenceCategory) prefScreen.findPreference(CATEGORY_MENU); final PreferenceCategory assistCategory = (PreferenceCategory) prefScreen.findPreference(CATEGORY_ASSIST); final PreferenceCategory appSwitchCategory = (PreferenceCategory) prefScreen.findPreference(CATEGORY_APPSWITCH); /* Toggle hardkey control availability depending on navbar state */ if (homeCategory != null) { homeCategory.setEnabled(!enabled); } if (menuCategory != null) { menuCategory.setEnabled(!enabled); } if (assistCategory != null) { assistCategory.setEnabled(!enabled); } if (appSwitchCategory != null) { appSwitchCategory.setEnabled(!enabled); } } public static void restoreKeyDisabler(Context context) { if (!KeyDisabler.isSupported()) { return; } writeDisableNavkeysOption(context, Settings.System.getInt(context.getContentResolver(), Settings.System.DEV_FORCE_SHOW_NAVBAR, 0) != 0); } @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { if (preference == mDisableNavigationKeys) { writeDisableNavkeysOption(getActivity(), mDisableNavigationKeys.isChecked()); updateDisableNavkeysOption(); } else if (preference == mPowerEndCall) { handleTogglePowerButtonEndsCallPreferenceClick(); return true; } else if (preference == mHomeAnswerCall) { handleToggleHomeButtonAnswersCallPreferenceClick(); return true; } return super.onPreferenceTreeClick(preferenceScreen, preference); } private void handleTogglePowerButtonEndsCallPreferenceClick() { Settings.Secure.putInt(getContentResolver(), Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR, (mPowerEndCall.isChecked() ? Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP : Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF)); } private void handleToggleHomeButtonAnswersCallPreferenceClick() { Settings.Secure.putInt(getContentResolver(), Settings.Secure.RING_HOME_BUTTON_BEHAVIOR, (mHomeAnswerCall.isChecked() ? Settings.Secure.RING_HOME_BUTTON_BEHAVIOR_ANSWER : Settings.Secure.RING_HOME_BUTTON_BEHAVIOR_DO_NOTHING)); } }