• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.os.PersistableBundle;
21 import android.telephony.CarrierConfigManager;
22 import android.telephony.SubscriptionManager;
23 import android.telephony.TelephonyCallback;
24 import android.telephony.TelephonyManager;
25 import android.telephony.ims.ImsMmTelManager;
26 import android.util.Log;
27 
28 import androidx.annotation.VisibleForTesting;
29 import androidx.preference.Preference;
30 import androidx.preference.PreferenceScreen;
31 import androidx.preference.SwitchPreference;
32 
33 import com.android.settings.network.MobileDataEnabledListener;
34 import com.android.settings.network.ims.VolteQueryImsState;
35 import com.android.settings.network.ims.VtQueryImsState;
36 import com.android.settingslib.core.lifecycle.LifecycleObserver;
37 import com.android.settingslib.core.lifecycle.events.OnStart;
38 import com.android.settingslib.core.lifecycle.events.OnStop;
39 
40 /**
41  * Preference controller for "Video Calling"
42  */
43 public class VideoCallingPreferenceController extends TelephonyTogglePreferenceController implements
44         LifecycleObserver, OnStart, OnStop,
45         MobileDataEnabledListener.Client,
46         Enhanced4gBasePreferenceController.On4gLteUpdateListener {
47 
48     private static final String TAG = "VideoCallingPreference";
49 
50     private Preference mPreference;
51     private CarrierConfigManager mCarrierConfigManager;
52     private PhoneTelephonyCallback mTelephonyCallback;
53     @VisibleForTesting
54     Integer mCallState;
55     private MobileDataEnabledListener mDataContentObserver;
56 
VideoCallingPreferenceController(Context context, String key)57     public VideoCallingPreferenceController(Context context, String key) {
58         super(context, key);
59         mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
60         mDataContentObserver = new MobileDataEnabledListener(context, this);
61         mTelephonyCallback = new PhoneTelephonyCallback();
62     }
63 
64     @Override
getAvailabilityStatus(int subId)65     public int getAvailabilityStatus(int subId) {
66         return SubscriptionManager.isValidSubscriptionId(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         mTelephonyCallback.register(mContext, mSubId);
81         mDataContentObserver.start(mSubId);
82     }
83 
84     @Override
onStop()85     public void onStop() {
86         mTelephonyCallback.unregister();
87         mDataContentObserver.stop();
88     }
89 
90     @Override
updateState(Preference preference)91     public void updateState(Preference preference) {
92         super.updateState(preference);
93         if ((mCallState == null) || (preference == null)) {
94             Log.d(TAG, "Skip update under mCallState=" + mCallState);
95             return;
96         }
97         final SwitchPreference switchPreference = (SwitchPreference) preference;
98         final boolean videoCallEnabled = isVideoCallEnabled(mSubId);
99         switchPreference.setVisible(videoCallEnabled);
100         if (videoCallEnabled) {
101             final boolean videoCallEditable = queryVoLteState(mSubId).isEnabledByUser()
102                     && queryImsState(mSubId).isAllowUserControl();
103             preference.setEnabled(videoCallEditable
104                     && mCallState == TelephonyManager.CALL_STATE_IDLE);
105             switchPreference.setChecked(videoCallEditable && isChecked());
106         }
107     }
108 
109     @Override
setChecked(boolean isChecked)110     public boolean setChecked(boolean isChecked) {
111         if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
112             return false;
113         }
114         final ImsMmTelManager imsMmTelManager = ImsMmTelManager.createForSubscriptionId(mSubId);
115         if (imsMmTelManager == null) {
116             return false;
117         }
118         try {
119             imsMmTelManager.setVtSettingEnabled(isChecked);
120             return true;
121         } catch (IllegalArgumentException exception) {
122             Log.w(TAG, "Unable to set VT status " + isChecked + ". subId=" + mSubId,
123                     exception);
124         }
125         return false;
126     }
127 
128     @Override
isChecked()129     public boolean isChecked() {
130         return queryImsState(mSubId).isEnabledByUser();
131     }
132 
init(int subId)133     public VideoCallingPreferenceController init(int subId) {
134         mSubId = subId;
135 
136         return this;
137     }
138 
139     @VisibleForTesting
isVideoCallEnabled(int subId)140     boolean isVideoCallEnabled(int subId) {
141         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
142             return false;
143         }
144 
145         // When called within Settings Search, this variable may still be null.
146         if (mCarrierConfigManager == null) {
147             Log.e(TAG, "CarrierConfigManager set to null.");
148             mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class);
149             if (mCarrierConfigManager == null) {
150                 Log.e(TAG, "Unable to reinitialize CarrierConfigManager.");
151                 return false;
152             }
153         }
154 
155         final PersistableBundle carrierConfig = mCarrierConfigManager.getConfigForSubId(subId);
156         if (carrierConfig == null) {
157             return false;
158         }
159 
160         if (!carrierConfig.getBoolean(
161                 CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS)
162                 && (!mContext.getSystemService(TelephonyManager.class)
163                     .createForSubscriptionId(subId).isDataEnabled())) {
164             return false;
165         }
166 
167         return queryImsState(subId).isReadyToVideoCall();
168     }
169 
170     @Override
on4gLteUpdated()171     public void on4gLteUpdated() {
172         updateState(mPreference);
173     }
174 
175     private class PhoneTelephonyCallback extends TelephonyCallback implements
176             TelephonyCallback.CallStateListener {
177 
178         private TelephonyManager mTelephonyManager;
179 
180         @Override
onCallStateChanged(int state)181         public void onCallStateChanged(int state) {
182             mCallState = state;
183             updateState(mPreference);
184         }
185 
register(Context context, int subId)186         public void register(Context context, int subId) {
187             mTelephonyManager = context.getSystemService(TelephonyManager.class);
188             if (SubscriptionManager.isValidSubscriptionId(subId)) {
189                 mTelephonyManager = mTelephonyManager.createForSubscriptionId(subId);
190             }
191             // assign current call state so that it helps to show correct preference state even
192             // before first onCallStateChanged() by initial registration.
193             mCallState = mTelephonyManager.getCallState(subId);
194             mTelephonyManager.registerTelephonyCallback(context.getMainExecutor(), this);
195         }
196 
unregister()197         public void unregister() {
198             mCallState = null;
199             mTelephonyManager.unregisterTelephonyCallback(this);
200         }
201     }
202 
203     /**
204      * Implementation of MobileDataEnabledListener.Client
205      */
onMobileDataEnabledChange()206     public void onMobileDataEnabledChange() {
207         updateState(mPreference);
208     }
209 
210     @VisibleForTesting
queryImsState(int subId)211     VtQueryImsState queryImsState(int subId) {
212         return new VtQueryImsState(mContext, subId);
213     }
214 
215     @VisibleForTesting
queryVoLteState(int subId)216     VolteQueryImsState queryVoLteState(int subId) {
217         return new VolteQueryImsState(mContext, subId);
218     }
219 }
220