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