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.car.developeroptions.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, 67 SubscriptionManager.getPhoneId(subId)) 68 && isVideoCallEnabled(subId) 69 ? AVAILABLE 70 : CONDITIONALLY_UNAVAILABLE; 71 } 72 73 @Override displayPreference(PreferenceScreen screen)74 public void displayPreference(PreferenceScreen screen) { 75 super.displayPreference(screen); 76 mPreference = screen.findPreference(getPreferenceKey()); 77 } 78 79 @Override onStart()80 public void onStart() { 81 mPhoneStateListener.register(mSubId); 82 mDataContentObserver.register(mContext, mSubId); 83 } 84 85 @Override onStop()86 public void onStop() { 87 mPhoneStateListener.unregister(); 88 mDataContentObserver.unRegister(mContext); 89 } 90 91 @Override updateState(Preference preference)92 public void updateState(Preference preference) { 93 super.updateState(preference); 94 final SwitchPreference switchPreference = (SwitchPreference) preference; 95 final boolean videoCallEnabled = isVideoCallEnabled(mSubId, mImsManager); 96 switchPreference.setVisible(videoCallEnabled); 97 if (videoCallEnabled) { 98 final boolean is4gLteEnabled = mImsManager.isEnhanced4gLteModeSettingEnabledByUser() 99 && mImsManager.isNonTtyOrTtyOnVolteEnabled(); 100 preference.setEnabled(is4gLteEnabled && 101 mTelephonyManager.getCallState(mSubId) == TelephonyManager.CALL_STATE_IDLE); 102 switchPreference.setChecked(is4gLteEnabled && mImsManager.isVtEnabledByUser()); 103 } 104 } 105 106 @Override setChecked(boolean isChecked)107 public boolean setChecked(boolean isChecked) { 108 mImsManager.setVtSetting(isChecked); 109 return true; 110 } 111 112 @Override isChecked()113 public boolean isChecked() { 114 return mImsManager.isVtEnabledByUser(); 115 } 116 init(int subId)117 public VideoCallingPreferenceController init(int subId) { 118 mSubId = subId; 119 mTelephonyManager = TelephonyManager.from(mContext).createForSubscriptionId(mSubId); 120 if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 121 mImsManager = ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(mSubId)); 122 } 123 124 return this; 125 } 126 isVideoCallEnabled(int subId)127 private boolean isVideoCallEnabled(int subId) { 128 final ImsManager imsManager = subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID 129 ? ImsManager.getInstance(mContext, SubscriptionManager.getPhoneId(subId)) 130 : null; 131 return isVideoCallEnabled(subId, imsManager); 132 } 133 134 @VisibleForTesting isVideoCallEnabled(int subId, ImsManager imsManager)135 boolean isVideoCallEnabled(int subId, ImsManager imsManager) { 136 final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId); 137 final TelephonyManager telephonyManager = TelephonyManager 138 .from(mContext).createForSubscriptionId(subId); 139 return carrierConfig != null && imsManager != null 140 && imsManager.isVtEnabledByPlatform() 141 && imsManager.isVtProvisionedOnDevice() 142 && MobileNetworkUtils.isImsServiceStateReady(imsManager) 143 && (carrierConfig.getBoolean( 144 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS) 145 || telephonyManager.isDataEnabled()); 146 } 147 148 @Override on4gLteUpdated()149 public void on4gLteUpdated() { 150 updateState(mPreference); 151 } 152 153 private class PhoneCallStateListener extends PhoneStateListener { 154 PhoneCallStateListener(Looper looper)155 public PhoneCallStateListener(Looper looper) { 156 super(looper); 157 } 158 159 @Override onCallStateChanged(int state, String incomingNumber)160 public void onCallStateChanged(int state, String incomingNumber) { 161 updateState(mPreference); 162 } 163 register(int subId)164 public void register(int subId) { 165 mSubId = subId; 166 mTelephonyManager.listen(this, PhoneStateListener.LISTEN_CALL_STATE); 167 } 168 unregister()169 public void unregister() { 170 mTelephonyManager.listen(this, PhoneStateListener.LISTEN_NONE); 171 } 172 } 173 174 /** 175 * Listener that listens mobile data state change. 176 */ 177 public class DataContentObserver extends ContentObserver { 178 DataContentObserver(Handler handler)179 public DataContentObserver(Handler handler) { 180 super(handler); 181 } 182 183 @Override onChange(boolean selfChange)184 public void onChange(boolean selfChange) { 185 super.onChange(selfChange); 186 updateState(mPreference); 187 } 188 register(Context context, int subId)189 public void register(Context context, int subId) { 190 Uri uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA); 191 if (TelephonyManager.getDefault().getSimCount() != 1) { 192 uri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + subId); 193 } 194 context.getContentResolver().registerContentObserver(uri, 195 false /* notifyForDescendants */, this /* observer */); 196 } 197 unRegister(Context context)198 public void unRegister(Context context) { 199 context.getContentResolver().unregisterContentObserver(this); 200 } 201 } 202 } 203