| /* |
| * Copyright (C) 2015 The Android Open Source 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.phone.settings; |
| |
| import android.content.Context; |
| import android.media.AudioManager; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.os.HandlerExecutor; |
| import android.os.Looper; |
| import android.os.PersistableBundle; |
| import android.preference.Preference; |
| import android.preference.PreferenceFragment; |
| import android.preference.PreferenceScreen; |
| import android.preference.SwitchPreference; |
| import android.provider.Settings; |
| import android.telephony.AccessNetworkConstants; |
| import android.telephony.CarrierConfigManager; |
| import android.telephony.SubscriptionManager; |
| import android.telephony.TelephonyCallback; |
| import android.telephony.TelephonyManager; |
| import android.text.TextUtils; |
| import android.util.Log; |
| |
| import com.android.ims.ImsManager; |
| import com.android.internal.telephony.Phone; |
| import com.android.internal.telephony.PhoneFactory; |
| import com.android.internal.telephony.SubscriptionController; |
| import com.android.internal.telephony.subscription.SubscriptionManagerService; |
| import com.android.phone.PhoneGlobals; |
| import com.android.phone.R; |
| |
| import java.util.concurrent.Executor; |
| import java.util.concurrent.Executors; |
| import java.util.concurrent.LinkedBlockingQueue; |
| import java.util.concurrent.TimeUnit; |
| |
| public class AccessibilitySettingsFragment extends PreferenceFragment { |
| private static final String LOG_TAG = AccessibilitySettingsFragment.class.getSimpleName(); |
| private static final boolean DBG = (PhoneGlobals.DBG_LEVEL >= 2); |
| |
| private static final String BUTTON_TTY_KEY = "button_tty_mode_key"; |
| private static final String BUTTON_HAC_KEY = "button_hac_key"; |
| private static final String BUTTON_RTT_KEY = "button_rtt_key"; |
| private static final String RTT_INFO_PREF = "button_rtt_more_information_key"; |
| |
| private static final int WFC_QUERY_TIMEOUT_MILLIS = 20; |
| |
| private final TelephonyCallback mTelephonyCallback = new AccessibilityTelephonyCallback(); |
| |
| private final class AccessibilityTelephonyCallback extends TelephonyCallback implements |
| TelephonyCallback.CallStateListener { |
| @Override |
| public void onCallStateChanged(int state) { |
| if (DBG) Log.d(LOG_TAG, "PhoneStateListener.onCallStateChanged: state=" + state); |
| Preference pref = getPreferenceScreen().findPreference(BUTTON_TTY_KEY); |
| if (pref != null) { |
| // Use TelephonyManager#getCallState instead of 'state' parameter because |
| // needs to check the current state of all phone calls to |
| // support multi sim configuration. |
| TelephonyManager telephonyManager = |
| (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); |
| final boolean isVolteTtySupported = isVolteTtySupportedInAnySlot(); |
| pref.setEnabled((isVolteTtySupported && !isVideoCallOrConferenceInProgress()) |
| || (telephonyManager.getCallState() == TelephonyManager.CALL_STATE_IDLE)); |
| } |
| } |
| } |
| |
| private Context mContext; |
| private AudioManager mAudioManager; |
| |
| private TtyModeListPreference mButtonTty; |
| private SwitchPreference mButtonHac; |
| private SwitchPreference mButtonRtt; |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| |
| mContext = getActivity().getApplicationContext(); |
| mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); |
| |
| addPreferencesFromResource(R.xml.accessibility_settings); |
| |
| mButtonTty = (TtyModeListPreference) findPreference( |
| getResources().getString(R.string.tty_mode_key)); |
| mButtonHac = (SwitchPreference) findPreference(BUTTON_HAC_KEY); |
| mButtonRtt = (SwitchPreference) findPreference(BUTTON_RTT_KEY); |
| |
| if (PhoneGlobals.getInstance().phoneMgr.isTtyModeSupported() && isTtySupportedByCarrier()) { |
| mButtonTty.init(); |
| } else { |
| getPreferenceScreen().removePreference(mButtonTty); |
| mButtonTty = null; |
| } |
| |
| if (PhoneGlobals.getInstance().phoneMgr.isHearingAidCompatibilitySupported()) { |
| int hac = Settings.System.getInt(mContext.getContentResolver(), |
| Settings.System.HEARING_AID, SettingsConstants.HAC_DISABLED); |
| mButtonHac.setChecked(hac == SettingsConstants.HAC_ENABLED); |
| } else { |
| getPreferenceScreen().removePreference(mButtonHac); |
| mButtonHac = null; |
| } |
| |
| if (shouldShowRttSetting()) { |
| TelephonyManager tm = |
| (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); |
| boolean isRoaming = tm.isNetworkRoaming( |
| SubscriptionManager.getDefaultVoiceSubscriptionId()); |
| boolean alwaysAllowWhileRoaming = isCarrierAllowRttWhenRoaming( |
| SubscriptionManager.getDefaultVoiceSubscriptionId()); |
| |
| boolean shouldDisableBecauseRoamingOffWfc = |
| (isRoaming && !isOnWfc()) && !alwaysAllowWhileRoaming; |
| |
| if (shouldDisableBecauseRoamingOffWfc) { |
| mButtonRtt.setSummary(TextUtils.concat(getText(R.string.rtt_mode_summary), "\n", |
| getText(R.string.no_rtt_when_roaming))); |
| } |
| boolean rttOn = Settings.Secure.getInt( |
| mContext.getContentResolver(), Settings.Secure.RTT_CALLING_MODE, 0) != 0; |
| mButtonRtt.setChecked(rttOn); |
| } else { |
| getPreferenceScreen().removePreference(mButtonRtt); |
| Preference rttInfoPref = findPreference(RTT_INFO_PREF); |
| getPreferenceScreen().removePreference(rttInfoPref); |
| mButtonRtt = null; |
| } |
| } |
| |
| @Override |
| public void onResume() { |
| super.onResume(); |
| TelephonyManager tm = |
| (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); |
| tm.registerTelephonyCallback(new HandlerExecutor(new Handler(Looper.getMainLooper())), |
| mTelephonyCallback); |
| } |
| |
| @Override |
| public void onPause() { |
| super.onPause(); |
| TelephonyManager tm = |
| (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); |
| tm.unregisterTelephonyCallback(mTelephonyCallback); |
| } |
| |
| @Override |
| public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { |
| if (preference == mButtonTty) { |
| return true; |
| } else if (preference == mButtonHac) { |
| int hac = mButtonHac.isChecked() |
| ? SettingsConstants.HAC_ENABLED : SettingsConstants.HAC_DISABLED; |
| // Update HAC value in Settings database. |
| Settings.System.putInt(mContext.getContentResolver(), Settings.System.HEARING_AID, hac); |
| |
| // Update HAC Value in AudioManager. |
| mAudioManager.setParameters( |
| SettingsConstants.HAC_KEY + "=" + (hac == SettingsConstants.HAC_ENABLED |
| ? SettingsConstants.HAC_VAL_ON : SettingsConstants.HAC_VAL_OFF)); |
| return true; |
| } else if (preference == mButtonRtt) { |
| Log.i(LOG_TAG, "RTT setting changed -- now " + mButtonRtt.isChecked()); |
| int rttMode = mButtonRtt.isChecked() ? 1 : 0; |
| Settings.Secure.putInt(mContext.getContentResolver(), Settings.Secure.RTT_CALLING_MODE, |
| rttMode); |
| // Update RTT config with IMS Manager if the always-on carrier config isn't set to true. |
| CarrierConfigManager configManager = (CarrierConfigManager) mContext.getSystemService( |
| Context.CARRIER_CONFIG_SERVICE); |
| int[] activeSubIds; |
| if (PhoneFactory.isSubscriptionManagerServiceEnabled()) { |
| activeSubIds = SubscriptionManagerService.getInstance().getActiveSubIdList(true); |
| } else { |
| activeSubIds = SubscriptionController.getInstance().getActiveSubIdList(true); |
| } |
| for (int subId : activeSubIds) { |
| if (!configManager.getConfigForSubId(subId).getBoolean( |
| CarrierConfigManager.KEY_IGNORE_RTT_MODE_SETTING_BOOL, false)) { |
| int phoneId = SubscriptionManager.getPhoneId(subId); |
| ImsManager imsManager = ImsManager.getInstance(getContext(), phoneId); |
| imsManager.setRttEnabled(mButtonRtt.isChecked()); |
| } |
| } |
| return true; |
| } |
| |
| return false; |
| } |
| |
| private boolean isVolteTtySupportedInAnySlot() { |
| final Phone[] phones = PhoneFactory.getPhones(); |
| if (phones == null) { |
| if (DBG) Log.d(LOG_TAG, "isVolteTtySupportedInAnySlot: No phones found."); |
| return false; |
| } |
| |
| CarrierConfigManager configManager = |
| (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); |
| for (Phone phone : phones) { |
| // Check if this phone supports VoLTE. |
| ImsManager imsManager = ImsManager.getInstance(mContext, phone.getPhoneId()); |
| boolean volteEnabled = false; |
| if (imsManager != null) { |
| volteEnabled = imsManager.isVolteEnabledByPlatform(); |
| } |
| |
| // Check if this phone suports VoLTE TTY. |
| boolean volteTtySupported = false; |
| PersistableBundle carrierConfig = configManager.getConfigForSubId(phone.getSubId()); |
| if (carrierConfig != null) { |
| volteTtySupported = carrierConfig.getBoolean( |
| CarrierConfigManager.KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL); |
| } |
| |
| if (volteEnabled && volteTtySupported) { |
| // VoLTE TTY is supported on this phone that also suports VoLTE. |
| return true; |
| } |
| } |
| // VoLTE TTY was not supported on any phone that also supports VoLTE. |
| return false; |
| } |
| |
| private boolean isVideoCallOrConferenceInProgress() { |
| final Phone[] phones = PhoneFactory.getPhones(); |
| if (phones == null) { |
| if (DBG) Log.d(LOG_TAG, "isVideoCallOrConferenceInProgress: No phones found."); |
| return false; |
| } |
| |
| for (Phone phone : phones) { |
| if (phone.isImsVideoCallOrConferencePresent()) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| private boolean isOnWfc() { |
| LinkedBlockingQueue<Integer> result = new LinkedBlockingQueue<>(1); |
| Executor executor = Executors.newSingleThreadExecutor(); |
| mContext.getSystemService(android.telephony.ims.ImsManager.class) |
| .getImsMmTelManager(SubscriptionManager.getDefaultSubscriptionId()) |
| .getRegistrationTransportType(executor, result::offer); |
| try { |
| Integer transportType = result.poll(WFC_QUERY_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS); |
| return transportType != null |
| && transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN; |
| } catch (InterruptedException e) { |
| return false; |
| } |
| } |
| |
| private boolean shouldShowRttSetting() { |
| // Go through all the subs -- if we want to display the RTT setting for any of them, do |
| // display it. |
| if (PhoneFactory.isSubscriptionManagerServiceEnabled()) { |
| for (int subId : SubscriptionManagerService.getInstance().getActiveSubIdList(true)) { |
| if (PhoneGlobals.getInstance().phoneMgr.isRttSupported(subId)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| for (int subId : SubscriptionController.getInstance().getActiveSubIdList(true)) { |
| if (PhoneGlobals.getInstance().phoneMgr.isRttSupported(subId)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** |
| * Determines if the device supports TTY per carrier config. |
| * @return {@code true} if the carrier supports TTY, {@code false} otherwise. |
| */ |
| private boolean isTtySupportedByCarrier() { |
| CarrierConfigManager configManager = |
| (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); |
| return configManager.getConfig().getBoolean( |
| CarrierConfigManager.KEY_TTY_SUPPORTED_BOOL); |
| } |
| |
| /** |
| * Determines from carrier config whether to always allow RTT while roaming. |
| */ |
| private boolean isCarrierAllowRttWhenRoaming(int subId) { |
| PersistableBundle b = |
| PhoneGlobals.getInstance().getCarrierConfigForSubId(subId); |
| return b.getBoolean(CarrierConfigManager.KEY_RTT_SUPPORTED_WHILE_ROAMING_BOOL); |
| } |
| } |