1 /* 2 * Copyright (C) 2015 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.wifi.calling; 18 19 import android.app.settings.SettingsEnums; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.os.Bundle; 23 import android.provider.Settings; 24 import android.telephony.SubscriptionInfo; 25 import android.telephony.SubscriptionManager; 26 import android.util.Log; 27 import android.view.LayoutInflater; 28 import android.view.View; 29 import android.view.ViewGroup; 30 import android.view.ViewStub; 31 32 import androidx.annotation.VisibleForTesting; 33 import androidx.fragment.app.Fragment; 34 import androidx.fragment.app.FragmentManager; 35 import androidx.fragment.app.FragmentPagerAdapter; 36 37 import com.android.internal.util.CollectionUtils; 38 import com.android.settings.R; 39 import com.android.settings.SettingsPreferenceFragment; 40 import com.android.settings.network.ActiveSubscriptionsListener; 41 import com.android.settings.network.SubscriptionUtil; 42 import com.android.settings.network.ims.WifiCallingQueryImsState; 43 import com.android.settings.network.telephony.MobileNetworkUtils; 44 import com.android.settings.search.actionbar.SearchMenuController; 45 import com.android.settings.support.actionbar.HelpResourceProvider; 46 import com.android.settings.widget.RtlCompatibleViewPager; 47 import com.android.settings.widget.SlidingTabLayout; 48 49 import java.util.ArrayList; 50 import java.util.Arrays; 51 import java.util.Collections; 52 import java.util.List; 53 54 /** 55 * "Wi-Fi Calling settings" screen. This is the container fragment which holds 56 * {@link WifiCallingSettingsForSub} fragments. 57 */ 58 public class WifiCallingSettings extends SettingsPreferenceFragment 59 implements HelpResourceProvider { 60 private static final String TAG = "WifiCallingSettings"; 61 private int mConstructionSubId; 62 private List<SubscriptionInfo> mSil; 63 private ActiveSubscriptionsListener mSubscriptionChangeListener; 64 private static final int [] EMPTY_SUB_ID_LIST = new int[0]; 65 66 //UI objects 67 private RtlCompatibleViewPager mViewPager; 68 private WifiCallingViewPagerAdapter mPagerAdapter; 69 private SlidingTabLayout mTabLayout; 70 71 private final class InternalViewPagerListener implements 72 RtlCompatibleViewPager.OnPageChangeListener { 73 @Override onPageScrolled(int position, float positionOffset, int positionOffsetPixels)74 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 75 // Do nothing. 76 } 77 78 @Override onPageSelected(int position)79 public void onPageSelected(int position) { 80 updateTitleForCurrentSub(); 81 } 82 83 @Override onPageScrollStateChanged(int state)84 public void onPageScrollStateChanged(int state) { 85 // Do nothing. 86 } 87 } 88 89 @Override getMetricsCategory()90 public int getMetricsCategory() { 91 return SettingsEnums.WIFI_CALLING; 92 } 93 94 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)95 public View onCreateView(LayoutInflater inflater, ViewGroup container, 96 Bundle savedInstanceState) { 97 super.onCreateView(inflater, container, savedInstanceState); 98 if (MobileNetworkUtils.isMobileNetworkUserRestricted(getActivity())) { 99 return new ViewStub(getActivity()); 100 } 101 final View view = inflater.inflate(R.layout.wifi_calling_settings_tabs, container, false); 102 103 mTabLayout = view.findViewById(R.id.sliding_tabs); 104 mViewPager = (RtlCompatibleViewPager) view.findViewById(R.id.view_pager); 105 106 mPagerAdapter = new WifiCallingViewPagerAdapter(getChildFragmentManager(), mViewPager); 107 mViewPager.setAdapter(mPagerAdapter); 108 mViewPager.addOnPageChangeListener(new InternalViewPagerListener()); 109 maybeSetViewForSubId(); 110 return view; 111 } 112 getConstructionSubId(Bundle bundle)113 private int getConstructionSubId(Bundle bundle) { 114 int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 115 116 Intent intent = getActivity().getIntent(); 117 if (intent != null) { 118 subId = intent.getIntExtra(Settings.EXTRA_SUB_ID, 119 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 120 } 121 if ((subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) && (bundle != null)) { 122 subId = bundle.getInt(Settings.EXTRA_SUB_ID, 123 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 124 } 125 return subId; 126 } 127 maybeSetViewForSubId()128 private void maybeSetViewForSubId() { 129 if (mSil == null) { 130 return; 131 } 132 int subId = mConstructionSubId; 133 if (SubscriptionManager.isValidSubscriptionId(subId)) { 134 for (SubscriptionInfo subInfo : mSil) { 135 if (subId == subInfo.getSubscriptionId()) { 136 mViewPager.setCurrentItem(mSil.indexOf(subInfo)); 137 break; 138 } 139 } 140 } 141 } 142 143 @Override onCreate(Bundle icicle)144 public void onCreate(Bundle icicle) { 145 mConstructionSubId = getConstructionSubId(icicle); 146 super.onCreate(icicle); 147 if (MobileNetworkUtils.isMobileNetworkUserRestricted(getActivity())) { 148 finish(); 149 return; 150 } 151 Log.d(TAG, "SubId=" + mConstructionSubId); 152 153 if (mConstructionSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 154 // Only config Wfc if it's enabled by platform. 155 mSubscriptionChangeListener = getSubscriptionChangeListener(getContext()); 156 } 157 mSil = updateSubList(); 158 } 159 160 @Override onStart()161 public void onStart() { 162 super.onStart(); 163 164 if (mSil != null && mSil.size() > 1) { 165 mTabLayout.setViewPager(mViewPager); 166 } else { 167 mTabLayout.setVisibility(View.GONE); 168 } 169 170 updateTitleForCurrentSub(); 171 172 if (mSubscriptionChangeListener != null) { 173 mSubscriptionChangeListener.start(); 174 } 175 } 176 177 @Override onStop()178 public void onStop() { 179 if (mSubscriptionChangeListener != null) { 180 mSubscriptionChangeListener.stop(); 181 } 182 183 super.onStop(); 184 } 185 186 @Override onSaveInstanceState(Bundle outState)187 public void onSaveInstanceState(Bundle outState) { 188 super.onSaveInstanceState(outState); 189 // keep subscription ID for recreation 190 outState.putInt(Settings.EXTRA_SUB_ID, mConstructionSubId); 191 } 192 193 @Override getHelpResource()194 public int getHelpResource() { 195 return R.string.help_uri_wifi_calling; 196 } 197 198 @VisibleForTesting 199 final class WifiCallingViewPagerAdapter extends FragmentPagerAdapter { 200 private final RtlCompatibleViewPager mViewPager; 201 WifiCallingViewPagerAdapter(FragmentManager fragmentManager, RtlCompatibleViewPager viewPager)202 public WifiCallingViewPagerAdapter(FragmentManager fragmentManager, 203 RtlCompatibleViewPager viewPager) { 204 super(fragmentManager); 205 mViewPager = viewPager; 206 } 207 208 @Override getPageTitle(int position)209 public CharSequence getPageTitle(int position) { 210 return String.valueOf(SubscriptionUtil.getUniqueSubscriptionDisplayName( 211 mSil.get(position), getContext())); 212 } 213 214 @Override getItem(int position)215 public Fragment getItem(int position) { 216 int subId = mSil.get(position).getSubscriptionId(); 217 Log.d(TAG, "Adapter getItem " + position + " for subId=" + subId); 218 final Bundle args = new Bundle(); 219 args.putBoolean(SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR, false); 220 args.putInt(WifiCallingSettingsForSub.FRAGMENT_BUNDLE_SUBID, subId); 221 final WifiCallingSettingsForSub fragment = new WifiCallingSettingsForSub(); 222 fragment.setArguments(args); 223 224 return fragment; 225 } 226 227 @Override instantiateItem(ViewGroup container, int position)228 public Object instantiateItem(ViewGroup container, int position) { 229 Log.d(TAG, "Adapter instantiateItem " + position); 230 return super.instantiateItem(container, 231 mViewPager.getRtlAwareIndex(position)); 232 } 233 234 @Override getCount()235 public int getCount() { 236 if (mSil == null) { 237 Log.d(TAG, "Adapter getCount null mSil "); 238 return 0; 239 } else { 240 Log.d(TAG, "Adapter getCount " + mSil.size()); 241 return mSil.size(); 242 } 243 } 244 } 245 246 @VisibleForTesting getSelectableSubscriptions(Context context)247 protected List<SubscriptionInfo> getSelectableSubscriptions(Context context) { 248 return SubscriptionUtil.getSelectableSubscriptionInfoList(context); 249 } 250 updateSubList()251 private List<SubscriptionInfo> updateSubList() { 252 List<SubscriptionInfo> subInfoList = getSelectableSubscriptions(getContext()); 253 254 if (subInfoList == null) { 255 return Collections.emptyList(); 256 } 257 List<SubscriptionInfo> selectedList = new ArrayList<SubscriptionInfo>(); 258 for (SubscriptionInfo subInfo : subInfoList) { 259 int subId = subInfo.getSubscriptionId(); 260 try { 261 if (MobileNetworkUtils.isWifiCallingEnabled( 262 getContext(), 263 subId, 264 queryImsState(subId))) { 265 selectedList.add(subInfo); 266 } 267 } catch (Exception exception) {} 268 } 269 return selectedList; 270 } 271 updateTitleForCurrentSub()272 private void updateTitleForCurrentSub() { 273 if (CollectionUtils.size(mSil) > 1) { 274 final int subId = mSil.get(mViewPager.getCurrentItem()).getSubscriptionId(); 275 final String title = SubscriptionManager.getResourcesForSubId(getContext(), subId) 276 .getString(R.string.wifi_calling_settings_title); 277 getActivity().getActionBar().setTitle(title); 278 } 279 } 280 281 @VisibleForTesting queryImsState(int subId)282 protected WifiCallingQueryImsState queryImsState(int subId) { 283 return new WifiCallingQueryImsState(getContext(), subId); 284 } 285 286 @VisibleForTesting getSubscriptionChangeListener(Context context)287 protected ActiveSubscriptionsListener getSubscriptionChangeListener(Context context) { 288 return new ActiveSubscriptionsListener(context.getMainLooper(), context) { 289 public void onChanged() { 290 onSubscriptionChange(context); 291 } 292 }; 293 } 294 295 protected void onSubscriptionChange(Context context) { 296 if (mSubscriptionChangeListener == null) { 297 return; 298 } 299 int [] previousSubIdList = subscriptionIdList(mSil); 300 List<SubscriptionInfo> updateList = updateSubList(); 301 int [] currentSubIdList = subscriptionIdList(updateList); 302 303 if (currentSubIdList.length > 0) { 304 // only keep fragment when any provisioned subscription is available 305 if (previousSubIdList.length == 0) { 306 // initial loading of list 307 mSil = updateList; 308 return; 309 } 310 if (previousSubIdList.length == currentSubIdList.length) { 311 // same number of subscriptions 312 if ( (!containsSubId(previousSubIdList, mConstructionSubId)) 313 // original request not yet appears in list 314 || containsSubId(currentSubIdList, mConstructionSubId) ) 315 // original request appears in list 316 { 317 mSil = updateList; 318 return; 319 } 320 } 321 } 322 Log.d(TAG, "Closed subId=" + mConstructionSubId 323 + " due to subscription change: " + Arrays.toString(previousSubIdList) 324 + " -> " + Arrays.toString(currentSubIdList)); 325 326 // close this fragment when no provisioned subscriptions available 327 if (mSubscriptionChangeListener != null) { 328 mSubscriptionChangeListener.stop(); 329 mSubscriptionChangeListener = null; 330 } 331 332 // close this fragment 333 finishFragment(); 334 } 335 336 protected int [] subscriptionIdList(List<SubscriptionInfo> subInfoList) { 337 return (subInfoList == null) ? EMPTY_SUB_ID_LIST : 338 subInfoList.stream().mapToInt(subInfo -> (subInfo == null) ? 339 SubscriptionManager.INVALID_SUBSCRIPTION_ID : subInfo.getSubscriptionId()) 340 .toArray(); 341 } 342 343 protected boolean containsSubId(int [] subIdArray, int subIdLookUp) { 344 return Arrays.stream(subIdArray).anyMatch(subId -> (subId == subIdLookUp)); 345 } 346 } 347