1 /* 2 * Copyright (C) 2020 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.phone; 18 19 import android.app.ActionBar; 20 import android.content.ContentProvider; 21 import android.content.Intent; 22 import android.database.Cursor; 23 import android.os.Bundle; 24 import android.os.PersistableBundle; 25 import android.os.Process; 26 import android.os.UserHandle; 27 import android.preference.Preference; 28 import android.preference.PreferenceScreen; 29 import android.telephony.CarrierConfigManager; 30 import android.util.Log; 31 import android.view.MenuItem; 32 33 import com.android.internal.telephony.CallForwardInfo; 34 import com.android.internal.telephony.CommandsInterface; 35 import com.android.internal.telephony.Phone; 36 37 import java.util.ArrayList; 38 39 public class CdmaCallForwardOptions extends TimeConsumingPreferenceActivity { 40 private static final String LOG_TAG = "CdmaCallForwardOptions"; 41 42 private static final String NUM_PROJECTION[] = { 43 android.provider.ContactsContract.CommonDataKinds.Phone.NUMBER 44 }; 45 46 private static final String BUTTON_CFU_KEY = "button_cfu_key"; 47 private static final String BUTTON_CFB_KEY = "button_cfb_key"; 48 private static final String BUTTON_CFNRY_KEY = "button_cfnry_key"; 49 private static final String BUTTON_CFNRC_KEY = "button_cfnrc_key"; 50 51 private static final String KEY_TOGGLE = "toggle"; 52 private static final String KEY_STATUS = "status"; 53 private static final String KEY_NUMBER = "number"; 54 private static final String KEY_ENABLE = "enable"; 55 56 private CallForwardEditPreference mButtonCFU; 57 private CallForwardEditPreference mButtonCFB; 58 private CallForwardEditPreference mButtonCFNRy; 59 private CallForwardEditPreference mButtonCFNRc; 60 61 private final ArrayList<CallForwardEditPreference> mPreferences = 62 new ArrayList<CallForwardEditPreference> (); 63 private int mInitIndex= 0; 64 65 private boolean mFirstResume; 66 private Bundle mIcicle; 67 private Phone mPhone; 68 private SubscriptionInfoHelper mSubscriptionInfoHelper; 69 private boolean mReplaceInvalidCFNumbers; 70 private boolean mCallForwardByUssd; 71 72 @Override onCreate(Bundle icicle)73 protected void onCreate(Bundle icicle) { 74 super.onCreate(icicle); 75 76 addPreferencesFromResource(R.xml.callforward_options); 77 78 mSubscriptionInfoHelper = new SubscriptionInfoHelper(this, getIntent()); 79 mSubscriptionInfoHelper.setActionBarTitle( 80 getActionBar(), getResources(), R.string.call_forwarding_settings_with_label); 81 mPhone = mSubscriptionInfoHelper.getPhone(); 82 83 PersistableBundle b = null; 84 boolean supportCFNRc = true; 85 if (mSubscriptionInfoHelper.hasSubId()) { 86 b = PhoneGlobals.getInstance().getCarrierConfigForSubId( 87 mSubscriptionInfoHelper.getSubId()); 88 } else { 89 b = PhoneGlobals.getInstance().getCarrierConfig(); 90 } 91 if (b != null) { 92 mReplaceInvalidCFNumbers = b.getBoolean( 93 CarrierConfigManager.KEY_CALL_FORWARDING_MAP_NON_NUMBER_TO_VOICEMAIL_BOOL); 94 mCallForwardByUssd = b.getBoolean( 95 CarrierConfigManager.KEY_USE_CALL_FORWARDING_USSD_BOOL); 96 supportCFNRc = b.getBoolean( 97 CarrierConfigManager.KEY_CALL_FORWARDING_WHEN_UNREACHABLE_SUPPORTED_BOOL); 98 } 99 100 PreferenceScreen prefSet = getPreferenceScreen(); 101 mButtonCFU = (CallForwardEditPreference) prefSet.findPreference(BUTTON_CFU_KEY); 102 mButtonCFB = (CallForwardEditPreference) prefSet.findPreference(BUTTON_CFB_KEY); 103 mButtonCFNRy = (CallForwardEditPreference) prefSet.findPreference(BUTTON_CFNRY_KEY); 104 mButtonCFNRc = (CallForwardEditPreference) prefSet.findPreference(BUTTON_CFNRC_KEY); 105 106 mButtonCFU.setParentActivity(this, mButtonCFU.reason); 107 mButtonCFB.setParentActivity(this, mButtonCFB.reason); 108 mButtonCFNRy.setParentActivity(this, mButtonCFNRy.reason); 109 mButtonCFNRc.setParentActivity(this, mButtonCFNRc.reason); 110 111 mPreferences.add(mButtonCFU); 112 mPreferences.add(mButtonCFB); 113 mPreferences.add(mButtonCFNRy); 114 115 if (supportCFNRc) { 116 mPreferences.add(mButtonCFNRc); 117 } else { 118 // When CFNRc is not supported, mButtonCFNRc is grayed out from the menu. 119 // Default state for the preferences in this PreferenceScreen is disabled. 120 // Only preferences listed in the ArrayList mPreferences will be enabled. 121 // By not adding mButtonCFNRc to mPreferences it will be kept disabled. 122 Log.d(LOG_TAG, "onCreate: CFNRc is not supported, grey out the item."); 123 } 124 125 if (mCallForwardByUssd) { 126 //the call forwarding ussd command's behavior is similar to the call forwarding when 127 //unanswered,so only display the call forwarding when unanswered item. 128 prefSet.removePreference(mButtonCFU); 129 prefSet.removePreference(mButtonCFB); 130 prefSet.removePreference(mButtonCFNRc); 131 mPreferences.remove(mButtonCFU); 132 mPreferences.remove(mButtonCFB); 133 mPreferences.remove(mButtonCFNRc); 134 mButtonCFNRy.setDependency(null); 135 } 136 137 // we wait to do the initialization until onResume so that the 138 // TimeConsumingPreferenceActivity dialog can display as it 139 // relies on onResume / onPause to maintain its foreground state. 140 141 mFirstResume = true; 142 mIcicle = icicle; 143 144 ActionBar actionBar = getActionBar(); 145 if (actionBar != null) { 146 // android.R.id.home will be triggered in onOptionsItemSelected() 147 actionBar.setDisplayHomeAsUpEnabled(true); 148 } 149 } 150 151 @Override onResume()152 public void onResume() { 153 super.onResume(); 154 155 if (mFirstResume) { 156 if (mIcicle == null) { 157 Log.d(LOG_TAG, "start to init "); 158 CallForwardEditPreference pref = mPreferences.get(mInitIndex); 159 pref.init(this, mPhone, mReplaceInvalidCFNumbers, mCallForwardByUssd); 160 pref.startCallForwardOptionsQuery(); 161 162 } else { 163 mInitIndex = mPreferences.size(); 164 165 for (CallForwardEditPreference pref : mPreferences) { 166 Bundle bundle = mIcicle.getParcelable(pref.getKey()); 167 pref.setToggled(bundle.getBoolean(KEY_TOGGLE)); 168 pref.setEnabled(bundle.getBoolean(KEY_ENABLE)); 169 CallForwardInfo cf = new CallForwardInfo(); 170 cf.number = bundle.getString(KEY_NUMBER); 171 cf.status = bundle.getInt(KEY_STATUS); 172 pref.init(this, mPhone, mReplaceInvalidCFNumbers, mCallForwardByUssd); 173 pref.restoreCallForwardInfo(cf); 174 } 175 } 176 mFirstResume = false; 177 mIcicle = null; 178 } 179 } 180 181 @Override onSaveInstanceState(Bundle outState)182 protected void onSaveInstanceState(Bundle outState) { 183 super.onSaveInstanceState(outState); 184 185 for (CallForwardEditPreference pref : mPreferences) { 186 Bundle bundle = new Bundle(); 187 bundle.putBoolean(KEY_TOGGLE, pref.isToggled()); 188 bundle.putBoolean(KEY_ENABLE, pref.isEnabled()); 189 if (pref.callForwardInfo != null) { 190 bundle.putString(KEY_NUMBER, pref.callForwardInfo.number); 191 bundle.putInt(KEY_STATUS, pref.callForwardInfo.status); 192 } 193 outState.putParcelable(pref.getKey(), bundle); 194 } 195 } 196 197 @Override onFinished(Preference preference, boolean reading)198 public void onFinished(Preference preference, boolean reading) { 199 if (mInitIndex < mPreferences.size()-1 && !isFinishing()) { 200 mInitIndex++; 201 CallForwardEditPreference pref = mPreferences.get(mInitIndex); 202 pref.init(this, mPhone, mReplaceInvalidCFNumbers, mCallForwardByUssd); 203 pref.startCallForwardOptionsQuery(); 204 } 205 206 super.onFinished(preference, reading); 207 } 208 209 @Override onActivityResult(int requestCode, int resultCode, Intent data)210 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 211 Log.d(LOG_TAG, "onActivityResult: done"); 212 if (resultCode != RESULT_OK) { 213 Log.d(LOG_TAG, "onActivityResult: contact picker result not OK."); 214 return; 215 } 216 Cursor cursor = null; 217 try { 218 // check if the URI returned by the user belongs to the user 219 final int currentUser = UserHandle.getUserId(Process.myUid()); 220 if (currentUser 221 != ContentProvider.getUserIdFromUri(data.getData(), currentUser)) { 222 223 Log.w(LOG_TAG, "onActivityResult: Contact data of different user, " 224 + "cannot access"); 225 return; 226 } 227 cursor = getContentResolver().query(data.getData(), 228 NUM_PROJECTION, null, null, null); 229 if ((cursor == null) || (!cursor.moveToFirst())) { 230 Log.d(LOG_TAG, "onActivityResult: bad contact data, no results found."); 231 return; 232 } 233 234 switch (requestCode) { 235 case CommandsInterface.CF_REASON_UNCONDITIONAL: 236 mButtonCFU.onPickActivityResult(cursor.getString(0)); 237 break; 238 case CommandsInterface.CF_REASON_BUSY: 239 mButtonCFB.onPickActivityResult(cursor.getString(0)); 240 break; 241 case CommandsInterface.CF_REASON_NO_REPLY: 242 mButtonCFNRy.onPickActivityResult(cursor.getString(0)); 243 break; 244 case CommandsInterface.CF_REASON_NOT_REACHABLE: 245 mButtonCFNRc.onPickActivityResult(cursor.getString(0)); 246 break; 247 default: 248 // TODO: may need exception here. 249 } 250 } finally { 251 if (cursor != null) { 252 cursor.close(); 253 } 254 } 255 } 256 257 @Override onOptionsItemSelected(MenuItem item)258 public boolean onOptionsItemSelected(MenuItem item) { 259 final int itemId = item.getItemId(); 260 if (itemId == android.R.id.home) { // See ActionBar#setDisplayHomeAsUpEnabled() 261 CallFeaturesSetting.goUpToTopLevelSetting(this, mSubscriptionInfoHelper); 262 return true; 263 } 264 return super.onOptionsItemSelected(item); 265 } 266 } 267