1 /*
2  * Copyright (C) 2014 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.internal.telephony.dataconnection;
18 
19 import android.content.Context;
20 import android.database.ContentObserver;
21 import android.net.ConnectivityManager;
22 import android.net.NetworkCapabilities;
23 import android.net.NetworkFactory;
24 import android.net.NetworkRequest;
25 import android.os.AsyncResult;
26 import android.os.Handler;
27 import android.os.Looper;
28 import android.os.Message;
29 import android.os.Messenger;
30 import android.provider.Settings;
31 import android.telephony.Rlog;
32 import android.telephony.SubscriptionManager;
33 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
34 import android.util.LocalLog;
35 import android.util.SparseArray;
36 
37 import com.android.internal.telephony.Phone;
38 import com.android.internal.telephony.PhoneBase;
39 import com.android.internal.telephony.PhoneConstants;
40 import com.android.internal.telephony.PhoneProxy;
41 import com.android.internal.telephony.SubscriptionController;
42 import com.android.internal.telephony.dataconnection.DcSwitchAsyncChannel.RequestInfo;
43 import com.android.internal.util.AsyncChannel;
44 import com.android.internal.util.IndentingPrintWriter;
45 
46 import java.io.FileDescriptor;
47 import java.io.PrintWriter;
48 import java.util.ArrayDeque;
49 import java.util.HashMap;
50 import java.util.Iterator;
51 import java.util.Map.Entry;
52 
53 public class DctController extends Handler {
54     private static final String LOG_TAG = "DctController";
55     private static final boolean DBG = true;
56 
57     private static final int EVENT_PROCESS_REQUESTS = 100;
58     private static final int EVENT_EXECUTE_REQUEST = 101;
59     private static final int EVENT_EXECUTE_ALL_REQUESTS = 102;
60     private static final int EVENT_RELEASE_REQUEST = 103;
61     private static final int EVENT_RELEASE_ALL_REQUESTS = 104;
62     private static final int EVENT_RETRY_ATTACH = 105;
63     private static final int EVENT_SETTINGS_CHANGED = 106;
64     private static final int EVENT_SUBSCRIPTIONS_CHANGED = 107;
65 
66     private static final int EVENT_DATA_ATTACHED = 500;
67     private static final int EVENT_DATA_DETACHED = 600;
68     private static final int EVENT_EMERGENCY_CALL_TOGGLED = 700;
69 
70     private static DctController sDctController;
71 
72     private int mPhoneNum;
73     private PhoneProxy[] mPhones;
74     private DcSwitchStateMachine[] mDcSwitchStateMachine;
75     private DcSwitchAsyncChannel[] mDcSwitchAsyncChannel;
76     private Handler[] mDcSwitchStateHandler;
77     private HashMap<Integer, RequestInfo> mRequestInfos = new HashMap<Integer, RequestInfo>();
78     private Context mContext;
79 
80     /** Used to send us NetworkRequests from ConnectivityService.  Remember it so we can
81      * unregister on dispose. */
82     private Messenger[] mNetworkFactoryMessenger;
83     private NetworkFactory[] mNetworkFactory;
84     private NetworkCapabilities[] mNetworkFilter;
85 
86     private SubscriptionController mSubController = SubscriptionController.getInstance();
87 
88     private SubscriptionManager mSubMgr;
89 
90     private OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =
91             new OnSubscriptionsChangedListener() {
92         @Override
93         public void onSubscriptionsChanged() {
94             DctController.this.obtainMessage(EVENT_SUBSCRIPTIONS_CHANGED).sendToTarget();
95         }
96     };
97 
98     private ContentObserver mObserver = new ContentObserver(new Handler()) {
99         @Override
100         public void onChange(boolean selfChange) {
101             logd("Settings change");
102             DctController.this.obtainMessage(EVENT_SETTINGS_CHANGED).sendToTarget();
103         }
104     };
105 
updatePhoneObject(PhoneProxy phone)106     public void updatePhoneObject(PhoneProxy phone) {
107         if (phone == null) {
108             loge("updatePhoneObject phone = null");
109             return;
110         }
111 
112         PhoneBase phoneBase = (PhoneBase)phone.getActivePhone();
113         if (phoneBase == null) {
114             loge("updatePhoneObject phoneBase = null");
115             return;
116         }
117 
118         for (int i = 0; i < mPhoneNum; i++) {
119             if (mPhones[i] == phone) {
120                 updatePhoneBaseForIndex(i, phoneBase);
121                 break;
122             }
123         }
124     }
125 
updatePhoneBaseForIndex(int index, PhoneBase phoneBase)126     private void updatePhoneBaseForIndex(int index, PhoneBase phoneBase) {
127         logd("updatePhoneBaseForIndex for phone index=" + index);
128 
129         phoneBase.getServiceStateTracker().registerForDataConnectionAttached(mRspHandler,
130                    EVENT_DATA_ATTACHED + index, null);
131         phoneBase.getServiceStateTracker().registerForDataConnectionDetached(mRspHandler,
132                    EVENT_DATA_DETACHED + index, null);
133         phoneBase.registerForEmergencyCallToggle(mRspHandler,
134                 EVENT_EMERGENCY_CALL_TOGGLED + index, null);
135 
136         ConnectivityManager cm = (ConnectivityManager)mPhones[index].getContext()
137             .getSystemService(Context.CONNECTIVITY_SERVICE);
138 
139         if (mNetworkFactoryMessenger != null) {
140             logd("unregister TelephonyNetworkFactory for phone index=" + index);
141             cm.unregisterNetworkFactory(mNetworkFactoryMessenger[index]);
142             mNetworkFactoryMessenger[index] = null;
143             mNetworkFactory[index] = null;
144             mNetworkFilter[index] = null;
145         }
146 
147         mNetworkFilter[index] = new NetworkCapabilities();
148         mNetworkFilter[index].addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
149         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_MMS);
150         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_SUPL);
151         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
152         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_FOTA);
153         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_IMS);
154         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_CBS);
155         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_IA);
156         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_RCS);
157         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP);
158         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
159         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
160         mNetworkFilter[index].addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
161 
162         mNetworkFactory[index] = new TelephonyNetworkFactory(this.getLooper(),
163                 mPhones[index].getContext(), "TelephonyNetworkFactory", phoneBase,
164                 mNetworkFilter[index]);
165         mNetworkFactory[index].setScoreFilter(50);
166         mNetworkFactoryMessenger[index] = new Messenger(mNetworkFactory[index]);
167         cm.registerNetworkFactory(mNetworkFactoryMessenger[index], "Telephony");
168     }
169 
170     private Handler mRspHandler = new Handler() {
171         @Override
172         public void handleMessage(Message msg){
173             if (msg.what >= EVENT_EMERGENCY_CALL_TOGGLED) {
174                 logd("EVENT_PHONE" + (msg.what - EVENT_EMERGENCY_CALL_TOGGLED + 1)
175                         + "_EMERGENCY_CALL_END.");
176                 AsyncResult ar = (AsyncResult) msg.obj;
177                 Integer toggle = (Integer) ar.result;
178                 mDcSwitchAsyncChannel[msg.what - EVENT_EMERGENCY_CALL_TOGGLED].
179                         notifyEmergencyCallToggled(toggle.intValue());
180             } else if (msg.what >= EVENT_DATA_DETACHED) {
181                 logd("EVENT_PHONE" + (msg.what - EVENT_DATA_DETACHED + 1)
182                         + "_DATA_DETACH.");
183                 mDcSwitchAsyncChannel[msg.what - EVENT_DATA_DETACHED].notifyDataDetached();
184 
185             } else if (msg.what >= EVENT_DATA_ATTACHED) {
186                 logd("EVENT_PHONE" + (msg.what - EVENT_DATA_ATTACHED + 1)
187                         + "_DATA_ATTACH.");
188                 mDcSwitchAsyncChannel[msg.what - EVENT_DATA_ATTACHED].notifyDataAttached();
189             }
190         }
191     };
192 
getInstance()193     public static DctController getInstance() {
194        if (sDctController == null) {
195         throw new RuntimeException(
196             "DctController.getInstance can't be called before makeDCTController()");
197         }
198        return sDctController;
199     }
200 
makeDctController(PhoneProxy[] phones)201     public static DctController makeDctController(PhoneProxy[] phones) {
202         if (sDctController == null) {
203             logd("makeDctController: new DctController phones.length=" + phones.length);
204             sDctController = new DctController(phones);
205         }
206         logd("makeDctController: X sDctController=" + sDctController);
207         return sDctController;
208     }
209 
DctController(PhoneProxy[] phones)210     private DctController(PhoneProxy[] phones) {
211         logd("DctController(): phones.length=" + phones.length);
212         if (phones == null || phones.length == 0) {
213             if (phones == null) {
214                 loge("DctController(phones): UNEXPECTED phones=null, ignore");
215             } else {
216                 loge("DctController(phones): UNEXPECTED phones.length=0, ignore");
217             }
218             return;
219         }
220         mPhoneNum = phones.length;
221         mPhones = phones;
222 
223         mDcSwitchStateMachine = new DcSwitchStateMachine[mPhoneNum];
224         mDcSwitchAsyncChannel = new DcSwitchAsyncChannel[mPhoneNum];
225         mDcSwitchStateHandler = new Handler[mPhoneNum];
226         mNetworkFactoryMessenger = new Messenger[mPhoneNum];
227         mNetworkFactory = new NetworkFactory[mPhoneNum];
228         mNetworkFilter = new NetworkCapabilities[mPhoneNum];
229 
230         for (int i = 0; i < mPhoneNum; ++i) {
231             int phoneId = i;
232             mDcSwitchStateMachine[i] = new DcSwitchStateMachine(mPhones[i],
233                     "DcSwitchStateMachine-" + phoneId, phoneId);
234             mDcSwitchStateMachine[i].start();
235             mDcSwitchAsyncChannel[i] = new DcSwitchAsyncChannel(mDcSwitchStateMachine[i], phoneId);
236             mDcSwitchStateHandler[i] = new Handler();
237 
238             int status = mDcSwitchAsyncChannel[i].fullyConnectSync(mPhones[i].getContext(),
239                 mDcSwitchStateHandler[i], mDcSwitchStateMachine[i].getHandler());
240 
241             if (status == AsyncChannel.STATUS_SUCCESSFUL) {
242                 logd("DctController(phones): Connect success: " + i);
243             } else {
244                 loge("DctController(phones): Could not connect to " + i);
245             }
246 
247             // Register for radio state change
248             PhoneBase phoneBase = (PhoneBase)mPhones[i].getActivePhone();
249             updatePhoneBaseForIndex(i, phoneBase);
250         }
251 
252         mContext = mPhones[0].getContext();
253         mSubMgr = SubscriptionManager.from(mContext);
254         mSubMgr.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
255 
256         //Register for settings change.
257         mContext.getContentResolver().registerContentObserver(
258                 Settings.Global.getUriFor(
259                 Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION),
260                 false, mObserver);
261     }
262 
dispose()263     public void dispose() {
264         logd("DctController.dispose");
265         for (int i = 0; i < mPhoneNum; ++i) {
266             ConnectivityManager cm = (ConnectivityManager)mPhones[i].getContext()
267                 .getSystemService(Context.CONNECTIVITY_SERVICE);
268             cm.unregisterNetworkFactory(mNetworkFactoryMessenger[i]);
269             mNetworkFactoryMessenger[i] = null;
270         }
271 
272         mSubMgr.removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
273         mContext.getContentResolver().unregisterContentObserver(mObserver);
274     }
275 
276 
277     @Override
handleMessage(Message msg)278     public void handleMessage (Message msg) {
279         logd("handleMessage msg=" + msg);
280         switch (msg.what) {
281             case EVENT_PROCESS_REQUESTS:
282                 onProcessRequest();
283                 break;
284             case EVENT_EXECUTE_REQUEST:
285                 onExecuteRequest((RequestInfo)msg.obj);
286                 break;
287             case EVENT_EXECUTE_ALL_REQUESTS:
288                 onExecuteAllRequests(msg.arg1);
289                 break;
290             case EVENT_RELEASE_REQUEST:
291                 onReleaseRequest((RequestInfo)msg.obj);
292                 break;
293             case EVENT_RELEASE_ALL_REQUESTS:
294                 onReleaseAllRequests(msg.arg1);
295                 break;
296             case EVENT_RETRY_ATTACH:
297                 onRetryAttach(msg.arg1);
298                 break;
299             case EVENT_SETTINGS_CHANGED:
300                 onSettingsChanged();
301                 break;
302             case EVENT_SUBSCRIPTIONS_CHANGED:
303                 onSubInfoReady();
304                 break;
305             default:
306                 loge("Un-handled message [" + msg.what + "]");
307         }
308     }
309 
requestNetwork(NetworkRequest request, int priority, LocalLog l, int phoneId)310     private int requestNetwork(NetworkRequest request, int priority, LocalLog l, int phoneId) {
311         logd("requestNetwork request=" + request
312                 + ", priority=" + priority);
313         l.log("Dctc.requestNetwork, priority=" + priority);
314 
315         RequestInfo requestInfo = new RequestInfo(request, priority, l, phoneId);
316         mRequestInfos.put(request.requestId, requestInfo);
317         processRequests();
318 
319         return PhoneConstants.APN_REQUEST_STARTED;
320     }
321 
releaseNetwork(NetworkRequest request)322     private int releaseNetwork(NetworkRequest request) {
323         RequestInfo requestInfo = mRequestInfos.get(request.requestId);
324         logd("releaseNetwork request=" + request + ", requestInfo=" + requestInfo);
325         if (requestInfo != null) requestInfo.log("DctController.releaseNetwork");
326 
327         mRequestInfos.remove(request.requestId);
328         releaseRequest(requestInfo);
329         processRequests();
330         return PhoneConstants.APN_REQUEST_STARTED;
331     }
332 
processRequests()333     void processRequests() {
334         logd("processRequests");
335         sendMessage(obtainMessage(EVENT_PROCESS_REQUESTS));
336     }
337 
executeRequest(RequestInfo request)338     void executeRequest(RequestInfo request) {
339         logd("executeRequest, request= " + request);
340         sendMessage(obtainMessage(EVENT_EXECUTE_REQUEST, request));
341     }
342 
executeAllRequests(int phoneId)343     void executeAllRequests(int phoneId) {
344         logd("executeAllRequests, phone:" + phoneId);
345         sendMessage(obtainMessage(EVENT_EXECUTE_ALL_REQUESTS, phoneId,0));
346     }
347 
releaseRequest(RequestInfo request)348     void releaseRequest(RequestInfo request) {
349         logd("releaseRequest, request= " + request);
350         sendMessage(obtainMessage(EVENT_RELEASE_REQUEST, request));
351     }
352 
releaseAllRequests(int phoneId)353     void releaseAllRequests(int phoneId) {
354         logd("releaseAllRequests, phone:" + phoneId);
355         sendMessage(obtainMessage(EVENT_RELEASE_ALL_REQUESTS, phoneId, 0));
356     }
357 
retryAttach(int phoneId)358     public void retryAttach(int phoneId) {
359         logd("retryAttach, phone:" + phoneId);
360         sendMessage(obtainMessage(EVENT_RETRY_ATTACH, phoneId, 0));
361     }
362 
onProcessRequest()363     private void onProcessRequest() {
364         //process all requests
365         //1. Check all requests and find subscription of the top priority
366         //   request
367         //2. Is current data allowed on the selected subscription
368         //2-1. If yes, execute all the requests of the sub
369         //2-2. If no, set data not allow on the current PS subscription
370         //2-2-1. Set data allow on the selected subscription
371 
372         int phoneId = getTopPriorityRequestPhoneId();
373         int activePhoneId = -1;
374 
375         for (int i=0; i<mDcSwitchStateMachine.length; i++) {
376             if (!mDcSwitchAsyncChannel[i].isIdleSync()) {
377                 activePhoneId = i;
378                 break;
379             }
380         }
381 
382         logd("onProcessRequest phoneId=" + phoneId
383                 + ", activePhoneId=" + activePhoneId);
384 
385         if (activePhoneId == -1 || activePhoneId == phoneId) {
386             Iterator<Integer> iterator = mRequestInfos.keySet().iterator();
387             while (iterator.hasNext()) {
388                 RequestInfo requestInfo = mRequestInfos.get(iterator.next());
389                 if (requestInfo.phoneId == phoneId && !requestInfo.executed) {
390                     mDcSwitchAsyncChannel[phoneId].connect(requestInfo);
391                 }
392             }
393         } else {
394             mDcSwitchAsyncChannel[activePhoneId].disconnectAll();
395         }
396     }
397 
onExecuteRequest(RequestInfo requestInfo)398     private void onExecuteRequest(RequestInfo requestInfo) {
399         if (!requestInfo.executed && mRequestInfos.containsKey(requestInfo.request.requestId)) {
400             logd("onExecuteRequest request=" + requestInfo);
401             requestInfo.log("DctController.onExecuteRequest - executed=" + requestInfo.executed);
402             requestInfo.executed = true;
403             String apn = apnForNetworkRequest(requestInfo.request);
404             int phoneId = requestInfo.phoneId;
405             PhoneBase phoneBase = (PhoneBase)mPhones[phoneId].getActivePhone();
406             DcTrackerBase dcTracker = phoneBase.mDcTracker;
407             dcTracker.incApnRefCount(apn, requestInfo.getLog());
408         }
409     }
410 
onExecuteAllRequests(int phoneId)411     private void onExecuteAllRequests(int phoneId) {
412         logd("onExecuteAllRequests phoneId=" + phoneId);
413         Iterator<Integer> iterator = mRequestInfos.keySet().iterator();
414         while (iterator.hasNext()) {
415             RequestInfo requestInfo = mRequestInfos.get(iterator.next());
416             if (requestInfo.phoneId == phoneId) {
417                 onExecuteRequest(requestInfo);
418             }
419         }
420     }
421 
onReleaseRequest(RequestInfo requestInfo)422     private void onReleaseRequest(RequestInfo requestInfo) {
423         logd("onReleaseRequest request=" + requestInfo);
424         if (requestInfo != null) {
425             requestInfo.log("DctController.onReleaseRequest");
426             if (requestInfo.executed) {
427                 String apn = apnForNetworkRequest(requestInfo.request);
428                 int phoneId = requestInfo.phoneId;
429                 PhoneBase phoneBase = (PhoneBase)mPhones[phoneId].getActivePhone();
430                 DcTrackerBase dcTracker = phoneBase.mDcTracker;
431                 dcTracker.decApnRefCount(apn, requestInfo.getLog());
432                 requestInfo.executed = false;
433             }
434         }
435     }
436 
onReleaseAllRequests(int phoneId)437     private void onReleaseAllRequests(int phoneId) {
438         logd("onReleaseAllRequests phoneId=" + phoneId);
439         Iterator<Integer> iterator = mRequestInfos.keySet().iterator();
440         while (iterator.hasNext()) {
441             RequestInfo requestInfo = mRequestInfos.get(iterator.next());
442             if (requestInfo.phoneId == phoneId) {
443                 onReleaseRequest(requestInfo);
444             }
445         }
446     }
447 
onRetryAttach(int phoneId)448     private void onRetryAttach(int phoneId) {
449         final int topPriPhone = getTopPriorityRequestPhoneId();
450         logd("onRetryAttach phoneId=" + phoneId + " topPri phone = " + topPriPhone);
451 
452         if (phoneId != -1 && phoneId == topPriPhone) {
453             mDcSwitchAsyncChannel[phoneId].retryConnect();
454         }
455     }
456 
onSettingsChanged()457     private void onSettingsChanged() {
458         //Sub Selection
459         long dataSubId = mSubController.getDefaultDataSubId();
460 
461         int activePhoneId = -1;
462         for (int i=0; i<mDcSwitchStateMachine.length; i++) {
463             if (!mDcSwitchAsyncChannel[i].isIdleSync()) {
464                 activePhoneId = i;
465                 break;
466             }
467         }
468 
469         int[] subIds = SubscriptionManager.getSubId(activePhoneId);
470         if (subIds ==  null || subIds.length == 0) {
471             loge("onSettingsChange, subIds null or length 0 for activePhoneId " + activePhoneId);
472             return;
473         }
474         logd("onSettingsChange, data sub: " + dataSubId + ", active data sub: " + subIds[0]);
475 
476         if (subIds[0] != dataSubId) {
477             Iterator<Integer> iterator = mRequestInfos.keySet().iterator();
478             while (iterator.hasNext()) {
479                 RequestInfo requestInfo = mRequestInfos.get(iterator.next());
480                 String specifier = requestInfo.request.networkCapabilities.getNetworkSpecifier();
481                 if (specifier == null || specifier.equals("")) {
482                     if (requestInfo.executed) {
483                         String apn = apnForNetworkRequest(requestInfo.request);
484                         logd("[setDataSubId] activePhoneId:" + activePhoneId + ", subId =" +
485                                 dataSubId);
486                         requestInfo.log("DctController.onSettingsChange releasing request");
487                         PhoneBase phoneBase =
488                                 (PhoneBase)mPhones[activePhoneId].getActivePhone();
489                         DcTrackerBase dcTracker = phoneBase.mDcTracker;
490                         dcTracker.decApnRefCount(apn, requestInfo.getLog());
491                         requestInfo.executed = false;
492                     }
493                 }
494             }
495         }
496 
497         // Some request maybe pending due to invalid settings
498         // Try to handle pending request when settings changed
499         for (int i = 0; i < mPhoneNum; ++i) {
500             ((DctController.TelephonyNetworkFactory)mNetworkFactory[i]).evalPendingRequest();
501         }
502 
503         processRequests();
504     }
505 
getTopPriorityRequestPhoneId()506     private int getTopPriorityRequestPhoneId() {
507         RequestInfo retRequestInfo = null;
508         int phoneId = 0;
509         int priority = -1;
510 
511         //TODO: Handle SIM Switch
512         for (int i=0; i<mPhoneNum; i++) {
513             Iterator<Integer> iterator = mRequestInfos.keySet().iterator();
514             while (iterator.hasNext()) {
515                 RequestInfo requestInfo = mRequestInfos.get(iterator.next());
516                 logd("selectExecPhone requestInfo = " + requestInfo);
517                 if (requestInfo.phoneId == i &&
518                         priority < requestInfo.priority) {
519                     priority = requestInfo.priority;
520                     retRequestInfo = requestInfo;
521                 }
522             }
523         }
524 
525         if (retRequestInfo != null) {
526             phoneId = getRequestPhoneId(retRequestInfo.request);
527         } else {
528             int defaultDds = mSubController.getDefaultDataSubId();
529             phoneId = mSubController.getPhoneId(defaultDds);
530             logd("getTopPriorityRequestPhoneId: RequestInfo list is empty, " +
531                     "use Dds sub phone id");
532         }
533 
534         logd("getTopPriorityRequestPhoneId = " + phoneId
535                 + ", priority = " + priority);
536 
537         return phoneId;
538     }
539 
onSubInfoReady()540     private void onSubInfoReady() {
541         logd("onSubInfoReady mPhoneNum=" + mPhoneNum);
542         for (int i = 0; i < mPhoneNum; ++i) {
543             int subId = mPhones[i].getSubId();
544             logd("onSubInfoReady handle pending requests subId=" + subId);
545             mNetworkFilter[i].setNetworkSpecifier(String.valueOf(subId));
546             ((DctController.TelephonyNetworkFactory)mNetworkFactory[i]).evalPendingRequest();
547         }
548         processRequests();
549     }
550 
apnForNetworkRequest(NetworkRequest nr)551     private String apnForNetworkRequest(NetworkRequest nr) {
552         NetworkCapabilities nc = nr.networkCapabilities;
553         // For now, ignore the bandwidth stuff
554         if (nc.getTransportTypes().length > 0 &&
555                 nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) == false) {
556             return null;
557         }
558 
559         // in the near term just do 1-1 matches.
560         // TODO - actually try to match the set of capabilities
561         int type = -1;
562         String name = null;
563 
564         boolean error = false;
565         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
566             if (name != null) error = true;
567             name = PhoneConstants.APN_TYPE_DEFAULT;
568             type = ConnectivityManager.TYPE_MOBILE;
569         }
570         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
571             if (name != null) error = true;
572             name = PhoneConstants.APN_TYPE_MMS;
573             type = ConnectivityManager.TYPE_MOBILE_MMS;
574         }
575         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
576             if (name != null) error = true;
577             name = PhoneConstants.APN_TYPE_SUPL;
578             type = ConnectivityManager.TYPE_MOBILE_SUPL;
579         }
580         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
581             if (name != null) error = true;
582             name = PhoneConstants.APN_TYPE_DUN;
583             type = ConnectivityManager.TYPE_MOBILE_DUN;
584         }
585         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
586             if (name != null) error = true;
587             name = PhoneConstants.APN_TYPE_FOTA;
588             type = ConnectivityManager.TYPE_MOBILE_FOTA;
589         }
590         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
591             if (name != null) error = true;
592             name = PhoneConstants.APN_TYPE_IMS;
593             type = ConnectivityManager.TYPE_MOBILE_IMS;
594         }
595         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
596             if (name != null) error = true;
597             name = PhoneConstants.APN_TYPE_CBS;
598             type = ConnectivityManager.TYPE_MOBILE_CBS;
599         }
600         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_IA)) {
601             if (name != null) error = true;
602             name = PhoneConstants.APN_TYPE_IA;
603             type = ConnectivityManager.TYPE_MOBILE_IA;
604         }
605         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_RCS)) {
606             if (name != null) error = true;
607             name = null;
608             loge("RCS APN type not yet supported");
609         }
610         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_XCAP)) {
611             if (name != null) error = true;
612             name = null;
613             loge("XCAP APN type not yet supported");
614         }
615         if (nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) {
616             if (name != null) error = true;
617             name = PhoneConstants.APN_TYPE_EMERGENCY;
618             type = ConnectivityManager.TYPE_MOBILE_EMERGENCY;
619         }
620         if (error) {
621             // TODO: If this error condition is removed, the framework's handling of
622             // NET_CAPABILITY_NOT_RESTRICTED will need to be updated so requests for
623             // say FOTA and INTERNET are marked as restricted.  This is not how
624             // NetworkCapabilities.maybeMarkCapabilitiesRestricted currently works.
625             loge("Multiple apn types specified in request - result is unspecified!");
626         }
627         if (type == -1 || name == null) {
628             loge("Unsupported NetworkRequest in Telephony: nr=" + nr);
629             return null;
630         }
631         return name;
632     }
633 
getRequestPhoneId(NetworkRequest networkRequest)634     private int getRequestPhoneId(NetworkRequest networkRequest) {
635         String specifier = networkRequest.networkCapabilities.getNetworkSpecifier();
636         int subId;
637         if (specifier == null || specifier.equals("")) {
638             subId = mSubController.getDefaultDataSubId();
639         } else {
640             subId = Integer.parseInt(specifier);
641         }
642         int phoneId = mSubController.getPhoneId(subId);
643         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
644             phoneId = 0;
645             if (!SubscriptionManager.isValidPhoneId(phoneId)) {
646                 throw new RuntimeException("Should not happen, no valid phoneId");
647             }
648         }
649         return phoneId;
650     }
651 
logd(String s)652     private static void logd(String s) {
653         if (DBG) Rlog.d(LOG_TAG, s);
654     }
655 
loge(String s)656     private static void loge(String s) {
657         if (DBG) Rlog.e(LOG_TAG, s);
658     }
659 
660     private class TelephonyNetworkFactory extends NetworkFactory {
661         private final SparseArray<NetworkRequest> mPendingReq = new SparseArray<NetworkRequest>();
662         private Phone mPhone;
663 
664         private class RequestLogger {
665             public NetworkRequest request;
666             public LocalLog log;
667 
RequestLogger(NetworkRequest r, LocalLog log)668             public RequestLogger(NetworkRequest r, LocalLog log) {
669                 request = r;
670                 this.log = log;
671             }
672         }
673 
674         private static final int MAX_REQUESTS_LOGGED = 20;
675         private static final int MAX_LOG_LINES_PER_REQUEST = 50;
676 
677         private ArrayDeque<RequestLogger> mRequestLogs = new ArrayDeque<RequestLogger>();
678 
TelephonyNetworkFactory(Looper l, Context c, String TAG, Phone phone, NetworkCapabilities nc)679         public TelephonyNetworkFactory(Looper l, Context c, String TAG, Phone phone,
680                 NetworkCapabilities nc) {
681             super(l, c, TAG, nc);
682             mPhone = phone;
683             log("NetworkCapabilities: " + nc);
684         }
685 
requestLog(int requestId, String l)686         public LocalLog requestLog(int requestId, String l) {
687             synchronized(mRequestLogs) {
688                 for (RequestLogger r : mRequestLogs) {
689                     if (r.request.requestId == requestId) {
690                         r.log.log(l);
691                         return r.log;
692                     }
693                 }
694             }
695             return null;
696         }
697 
addLogger(NetworkRequest request)698         private LocalLog addLogger(NetworkRequest request) {
699             synchronized(mRequestLogs) {
700                 for (RequestLogger r : mRequestLogs) {
701                     if (r.request.requestId == request.requestId) {
702                         return r.log;
703                     }
704                 }
705                 LocalLog l = new LocalLog(MAX_LOG_LINES_PER_REQUEST);
706                 RequestLogger logger = new RequestLogger(request, l);
707                 while (mRequestLogs.size() >= MAX_REQUESTS_LOGGED) {
708                     mRequestLogs.removeFirst();
709                 }
710                 mRequestLogs.addLast(logger);
711                 return l;
712             }
713         }
714 
715         @Override
needNetworkFor(NetworkRequest networkRequest, int score)716         protected void needNetworkFor(NetworkRequest networkRequest, int score) {
717             // figure out the apn type and enable it
718             log("Cellular needs Network for " + networkRequest);
719 
720             final LocalLog l = addLogger(networkRequest);
721 
722             if (!SubscriptionManager.isUsableSubIdValue(mPhone.getSubId()) ||
723                     getRequestPhoneId(networkRequest) != mPhone.getPhoneId()) {
724                 final String str = "Request not useable, pending request.";
725                 log(str);
726                 l.log(str);
727                 mPendingReq.put(networkRequest.requestId, networkRequest);
728                 return;
729             }
730 
731             DcTrackerBase dcTracker =((PhoneBase)mPhone).mDcTracker;
732             String apn = apnForNetworkRequest(networkRequest);
733             if (dcTracker.isApnSupported(apn)) {
734                 requestNetwork(networkRequest, dcTracker.getApnPriority(apn), l,
735                         mPhone.getPhoneId());
736             } else {
737                 final String str = "Unsupported APN";
738                 log(str);
739                 l.log(str);
740             }
741         }
742 
743         @Override
releaseNetworkFor(NetworkRequest networkRequest)744         protected void releaseNetworkFor(NetworkRequest networkRequest) {
745             String str = "Cellular releasing Network for ";
746             log(str + networkRequest);
747             final LocalLog l = requestLog(networkRequest.requestId, str);
748 
749             if (mPendingReq.get(networkRequest.requestId) != null) {
750                 str = "Sub Info has not been ready, remove request.";
751                 log(str);
752                 if (l != null) l.log(str);
753                 mPendingReq.remove(networkRequest.requestId);
754                 return;
755             }
756 
757             releaseNetwork(networkRequest);
758         }
759 
760         @Override
log(String s)761         protected void log(String s) {
762             if (DBG) Rlog.d(LOG_TAG, "[TNF " + mPhone.getSubId() + "]" + s);
763         }
764 
evalPendingRequest()765         public void evalPendingRequest() {
766             log("evalPendingRequest, pending request size is " + mPendingReq.size());
767             int key = 0;
768             for(int i = 0; i < mPendingReq.size(); i++) {
769                 key = mPendingReq.keyAt(i);
770                 NetworkRequest request = mPendingReq.get(key);
771                 log("evalPendingRequest: request = " + request);
772 
773                 mPendingReq.remove(request.requestId);
774                 needNetworkFor(request, 0);
775             }
776         }
777 
778         @Override
dump(FileDescriptor fd, PrintWriter writer, String[] args)779         public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
780             super.dump(fd, writer, args);
781             final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
782             pw.increaseIndent();
783             pw.println("Pending Requests:");
784             pw.increaseIndent();
785             for (int i = 0; i < mPendingReq.size(); i++) {
786                 NetworkRequest request = mPendingReq.valueAt(i);
787                 pw.println(request);
788             }
789             pw.decreaseIndent();
790 
791             pw.println("Request History:");
792             pw.increaseIndent();
793             synchronized(mRequestLogs) {
794                 for (RequestLogger r : mRequestLogs) {
795                     pw.println(r.request);
796                     pw.increaseIndent();
797                     r.log.dump(fd, pw, args);
798                     pw.decreaseIndent();
799                 }
800             }
801             pw.decreaseIndent();
802             pw.decreaseIndent();
803         }
804     }
805 
dump(FileDescriptor fd, PrintWriter pw, String[] args)806     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
807         pw.println("DctController:");
808         try {
809             for (DcSwitchStateMachine dssm : mDcSwitchStateMachine) {
810                 dssm.dump(fd, pw, args);
811             }
812         } catch (Exception e) {
813             e.printStackTrace();
814         }
815         pw.flush();
816         pw.println("++++++++++++++++++++++++++++++++");
817 
818         try {
819             for (Entry<Integer, RequestInfo> entry : mRequestInfos.entrySet()) {
820                 pw.println("mRequestInfos[" + entry.getKey() + "]=" + entry.getValue());
821             }
822         } catch (Exception e) {
823             e.printStackTrace();
824         }
825         pw.flush();
826         pw.println("++++++++++++++++++++++++++++++++");
827         pw.flush();
828         pw.println("TelephonyNetworkFactories:");
829         for (NetworkFactory tnf : mNetworkFactory) {
830             tnf.dump(fd, pw, args);
831         }
832         pw.flush();
833         pw.println("++++++++++++++++++++++++++++++++");
834         pw.flush();
835     }
836 }
837