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