1 /* 2 * Copyright (C) 2018 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.network.telephony; 18 19 import android.content.Context; 20 import android.database.ContentObserver; 21 import android.net.Uri; 22 import android.os.Handler; 23 import android.os.Looper; 24 import android.os.PersistableBundle; 25 import android.provider.Settings; 26 import android.telephony.CarrierConfigManager; 27 import android.telephony.PhoneStateListener; 28 import android.telephony.SubscriptionManager; 29 import android.telephony.TelephonyManager; 30 31 import androidx.annotation.VisibleForTesting; 32 import androidx.preference.Preference; 33 import androidx.preference.PreferenceScreen; 34 import androidx.preference.SwitchPreference; 35 36 import com.android.ims.ImsManager; 37 import com.android.settingslib.core.lifecycle.LifecycleObserver; 38 import com.android.settingslib.core.lifecycle.events.OnStart; 39 import com.android.settingslib.core.lifecycle.events.OnStop; 40 41 /** 42 * Preference controller for "Video Calling" 43 */ 44 public class VideoCallingPreferenceController extends TelephonyTogglePreferenceController implements 45 LifecycleObserver, OnStart, OnStop, 46 Enhanced4gLtePreferenceController.On4gLteUpdateListener { 47 48 private Preference mPreference; 49 private TelephonyManager mTelephonyManager; 50 private CarrierConfigManager mCarrierConfigManager; 51 @VisibleForTesting 52 ImsManager mImsManager; 53 private PhoneCallStateListener mPhoneStateListener; 54 private DataContentObserver mDataContentObserver; 55 VideoCallingPreferenceController(Context context, String key)56 public VideoCallingPreferenceController(Context context, String key) { 57 super(context, key); 58 mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class); 59 mDataContentObserver = new DataContentObserver(new Handler(Looper.getMainLooper())); 60 mPhoneStateListener = new PhoneCallStateListener(Looper.getMainLooper()); 61 } 62 63 @Override getAvailabilityStatus(int subId)64 public int getAvailabilityStatus(int subId) { 65 return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID 66 && MobileNetworkUtils.isWifiCallingEnabled(mContext, subId) 67 && isVideoCallEnabled(subId) 68 ? AVAILABLE 69 : CONDITIONALLY_UNAVAILABLE; 70 } 71 72 @Override displayPreference(PreferenceScreen screen)73 public void displayPreference(PreferenceScreen screen) { 74 super.displayPreference(screen); 75 mPreference = screen.findPreference(getPreferenceKey()); 76 } 77 78 @Override onStart()79 public void onStart() { 80 mPhoneStateListener.register(mSubId); 81 mDataContentObserver.register(mContext, mSubId); 82 } 83 84 @Override onStop()85 public void onStop() { 86 mPhoneStateListener.unregister(); 87 mDataContentObserver.unRegister(mContext); 88 } 89 90 @Override updateState(Preference preference)91 public void updateState(Preference preference) { 92 super.updateState(preference); 93 final SwitchPreference switchPreference = (SwitchPreference) preference; 94 final boolean videoCallEnabled = isVideoCallEnabled(mSubId, mImsManager); 95 switchPreference.setVisible(videoCallEnabled); 96 if (videoCallEnabled) { 97 final boolean is4gLteEnabled = mImsManager.isEnhanced4gLteModeSettingEnabledByUser() 98 && mImsManager.isNonTtyOrTtyOnVolteEnabled(); 99 preference.setEnabled(is4gLteEnabled && 100 mTelephonyManager.getCallState(mSubId) == TelephonyManager.CALL_STATE_IDLE); 101 switchPreference.setChecked(is4gLteEnabled && mImsManager.isVtEnabledByUser()); 102 } 103 } 104 105 @Override setChecked(boolean isChecked)106 public boolean setChecked(boolean isChecked) { 107 mImsManager.setVtSetting(isChecked); 108 return true; 109 } 110 111 @Override isChecked()112 public boolean isChecked() { 113 return mImsManager.isVtEnabledByUser(); 114 } 115 init(int subId)116 public VideoCallingPreferenceController init(int subId) { 117 mSubId = subId; 118 mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); 119 if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 120 mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId)); 121 } 122 123 return this; 124 } 125 isVideoCallEnabled(int subId)126 private boolean isVideoCallEnabled(int subId) { 127 final ImsManager imsManager = subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID 128 ? ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(subId)) 129 : null; 130 return isVideoCallEnabled(subId, imsManager); 131 } 132 133 @VisibleForTesting isVideoCallEnabled(int subId, ImsManager imsManager)134 boolean isVideoCallEnabled(int subId, ImsManager imsManager) { 135 final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); 136 final TelephonyManager telephonyManager = TelephonyManager 137 .from(mContext).createForSubscriptionId(subId); 138 return carrierConfig != null && imsManager != null 139 && imsManager.isVtEnabledByPlatform() 140 && imsManager.isVtProvisionedOnDevice() 141 && MobileNetworkUtils.isImsServiceStateReady(imsManager) 142 && (carrierConfig.getBoolean( 143 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS) 144 || telephonyManager.isDataEnabled()); 145 } 146 147 @Override on4gLteUpdated()148 public void on4gLteUpdated() { 149 updateState(mPreference); 150 } 151 152 private class PhoneCallStateListener extends PhoneStateListener { 153 PhoneCallStateListener(Looper looper)154 public PhoneCallStateListener(Looper looper) { 155 super(looper); 156 } 157 158 @Override onCallStateChanged(int state, String incomingNumber)159 public void onCallStateChanged(int state, String incomingNumber) { 160 updateState(mPreference); 161 } 162 register(int subId)163 public void register(int subId) { 164 mSubId = subId; 165 mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE); 166 } 167 unregister()168 public void unregister() { 169 mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE); 170 } 171 } 172 173 /** 174 * Listener that listens mobile data state change. 175 */ 176 public class DataContentObserver extends ContentObserver { 177 DataContentObserver(Handler handler)178 public DataContentObserver(Handler handler) { 179 super(handler); 180 } 181 182 @Override onChange(boolean selfChange)183 public void onChange(boolean selfChange) { 184 super.onChange(selfChange); 185 updateState(mPreference); 186 } 187 register(Context context, int subId)188 public void register(Context context, int subId) { 189 Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA); 190 if (TelephonyManager.getDefault().getSimCount() != 1) { 191 uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId); 192 } 193 context.getContentResolver().registerContentObserver(uri, 194 false /* notifyForDescendants */, this /* observer */); 195 } 196 unRegister(Context context)197 public void unRegister(Context context) { 198 context.getContentResolver().unregisterContentObserver(this); 199 } 200 } 201 } 202