Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit aa0fdbb4 authored by Yashdev Singh's avatar Yashdev Singh Committed by Linux Build Service Account
Browse files

Telephony: Implementation of DATA+MMS.

- Initial implementation of Msim data.
- Implemented DDS switch and auto-retrieval.
- Implemented plugin for DDS switch service.
- Serialize on-demand DDS switch logic.
- Implement callback interface between DCT and SubscriptionController
for onDemandDds requests

Change-Id: If69fc8b4f90bfb07c66c6520a4586e510166767b
Conflicts:
src/java/com/android/internal/telephony/dataconnection/DcTracker.java
parent 938d2dec
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ package com.android.internal.telephony;

import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;

import android.telephony.Rlog;
@@ -94,7 +95,10 @@ public class ProxyController {
        mUiccController = uiccController;
        mCi = ci;

        mDctController = DctController.makeDctController((PhoneProxy[])phoneProxy);
        HandlerThread t = new HandlerThread("DctControllerThread");
        t.start();

        mDctController = DctController.makeDctController((PhoneProxy[])phoneProxy, t.getLooper());
        mUiccPhoneBookController = new UiccPhoneBookController(mProxyPhones);
        mPhoneSubInfoController = new PhoneSubInfoController(mProxyPhones);
        mUiccSmsController = new UiccSmsController(mProxyPhones);
+2 −1
Original line number Diff line number Diff line
@@ -729,7 +729,8 @@ public final class RIL extends BaseCommands implements CommandsInterface {
    // FIXME This API should take an AID and slot ID
    public void setDataAllowed(boolean allowed, Message result) {
        RILRequest rr = RILRequest.obtain(RIL_REQUEST_ALLOW_DATA, result);
        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
                + " " + allowed);

        rr.mParcel.writeInt(1);
        rr.mParcel.writeInt(allowed ? 1 : 0);
+112 −3
Original line number Diff line number Diff line
@@ -22,9 +22,12 @@ import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.Messenger;
import android.telephony.Rlog;
import android.util.Log;
import android.net.Uri;
import android.net.NetworkRequest;
import android.net.NetworkCapabilities;
import android.database.Cursor;
import android.content.Intent;
import android.provider.BaseColumns;
@@ -33,9 +36,13 @@ import android.provider.Settings.SettingNotFoundException;
import android.content.ContentResolver;
import android.content.ContentValues;

import com.android.internal.util.AsyncChannel;
import com.android.internal.telephony.ISub;
import com.android.internal.telephony.uicc.SpnOverride;

import com.android.internal.telephony.dataconnection.DctController;
import com.android.internal.telephony.dataconnection.DdsScheduler;
import com.android.internal.telephony.dataconnection.DdsSchedulerAc;
import android.telephony.SubscriptionManager;
import android.telephony.SubInfoRecord;
import android.telephony.TelephonyManager;
@@ -43,6 +50,7 @@ import android.text.format.Time;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.NumberFormatException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
@@ -152,6 +160,15 @@ public class SubscriptionController extends ISub.Stub {
        }
    };

    private static final int EVENT_SET_DEFAULT_DATA_DONE = 1;
    private DataConnectionHandler mDataConnectionHandler;
    private  DctController mDctController;

    private HashMap<Long, OnDemandDdsLockNotifier> mOnDemandDdsLockNotificationRegistrants =
        new HashMap<Long, OnDemandDdsLockNotifier>();

    private DdsScheduler mScheduler;
    private DdsSchedulerAc mSchedulerAc;

    public static SubscriptionController init(Phone phone) {
        synchronized (SubscriptionController.class) {
@@ -185,6 +202,7 @@ public class SubscriptionController extends ISub.Stub {
    }

    private SubscriptionController(Context c) {
        logd("SubscriptionController init by Context");
        mContext = c;
        mCM = CallManager.getInstance();

@@ -193,6 +211,41 @@ public class SubscriptionController extends ISub.Stub {
        }

        logdl("[SubscriptionController] init by Context");
        mDataConnectionHandler = new DataConnectionHandler();

        mScheduler = DdsScheduler.makeDdsScheduler();
        mScheduler.start();

        mSchedulerAc = new DdsSchedulerAc();
        mSchedulerAc.connect(mContext, mDataConnectionHandler, mScheduler.getHandler());

    }

    public long getSubIdFromNetworkRequest(NetworkRequest n) {
        long subId;
        if (n == null) {
            return getDefaultDataSubId();
        }

        String str = n.networkCapabilities.getNetworkSpecifier();
        try {
            subId = Long.parseLong(str);
        } catch(NumberFormatException e) {
            loge("Exception e = " + e);
            subId = getDefaultDataSubId();
        }

        return subId;
    }

    public void startOnDemandDataSubscriptionRequest(NetworkRequest n) {
        logd("startOnDemandDataSubscriptionRequest = " + n);
        mSchedulerAc.allocateDds(n);
    }

    public void stopOnDemandDataSubscriptionRequest(NetworkRequest n) {
        logd("stopOnDemandDataSubscriptionRequest = " + n);
        mSchedulerAc.freeDds(n);
    }

    private boolean isSubInfoReady() {
@@ -1181,13 +1234,27 @@ public class SubscriptionController extends ISub.Stub {

    @Override
    public void setDefaultDataSubId(long subId) {
        if (subId == SubscriptionManager.DEFAULT_SUB_ID) {
            throw new RuntimeException("setDefaultDataSubId called with DEFAULT_SUB_ID");
        }
        logdl("[setDefaultDataSubId] subId=" + subId);

        if (mDctController == null) {
            mDctController = DctController.getInstance();
            mDctController.registerForDefaultDataSwitchInfo(mDataConnectionHandler,
                    EVENT_SET_DEFAULT_DATA_DONE, null);
        }
        mDctController.setDefaultDataSubId(subId);

    }

    public long getCurrentDds() {
        return mScheduler.getCurrentDds();
    }


    private void updateDataSubId(long subId) {
        logd(" updateDataSubId,  subId=" + subId);
        Settings.Global.putLong(mContext.getContentResolver(),
                Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION, subId);
        mScheduler.updateCurrentDds(null);
        broadcastDefaultDataSubIdChanged(subId);

        // FIXME is this still needed?
@@ -1290,6 +1357,21 @@ public class SubscriptionController extends ISub.Stub {
        return true;
    }

    private class DataConnectionHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case EVENT_SET_DEFAULT_DATA_DONE:{
                    AsyncResult ar = (AsyncResult) msg.obj;
                    Long subId = (Long)ar.result;
                    logd("EVENT_SET_DEFAULT_DATA_DONE subId:" + subId);
                    updateDataSubId(subId);
                    break;
                }
            }
        }
    }

    /* This should return long and not long [] since each phone has
     * exactly 1 sub id for now, it could return the 0th element
     * returned from getSubId()
@@ -1564,4 +1646,31 @@ public class SubscriptionController extends ISub.Stub {
                Settings.Global.MULTI_SIM_VOICE_PROMPT, value);
        logd("setVoicePromptOption to " + enabled);
    }

    @Override
    public long getOnDemandDataSubId() {
        return getCurrentDds();
    }

    public void registerForOnDemandDdsLockNotification(long clientSubId,
            OnDemandDdsLockNotifier callback) {
        logd("registerForOnDemandDdsLockNotification for client=" + clientSubId);
        mOnDemandDdsLockNotificationRegistrants.put(clientSubId, callback);

    }

    /* {@hide} */
    public void notifyOnDemandDataSubIdChanged(NetworkRequest n) {
        OnDemandDdsLockNotifier notifier = mOnDemandDdsLockNotificationRegistrants.get(
                getSubIdFromNetworkRequest(n));
        if (notifier != null) {
            notifier.notifyOnDemandDdsLockGranted(n);
        } else {
            logd("No registrants for OnDemandDdsLockGranted event");
        }
    }

    public interface OnDemandDdsLockNotifier {
        public void notifyOnDemandDdsLockGranted(NetworkRequest n);
    }
}
+10 −3
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.os.SystemProperties;
import android.telephony.Rlog;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.SubscriptionManager;
import android.text.TextUtils;
import android.util.Pair;
import android.util.Patterns;
@@ -955,6 +956,10 @@ public final class DataConnection extends StateMachine {
                    }
                    default:
                }
                if (mPhone.getSubId() != SubscriptionManager.getDefaultDataSubId()) {
                    log("DataConnection on non-dds does not have INTERNET capability.");
                    result.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
                }
            }
            ConnectivityManager.maybeMarkCapabilitiesRestricted(result);
        }
@@ -980,6 +985,7 @@ public final class DataConnection extends StateMachine {
        }
        result.setLinkUpstreamBandwidthKbps(up);
        result.setLinkDownstreamBandwidthKbps(down);
        result.setNetworkSpecifier("" + mPhone.getSubId());
        return result;
    }

@@ -1738,9 +1744,10 @@ public final class DataConnection extends StateMachine {
                    mNetworkInfo.getReason(), null);
            mNetworkInfo.setExtraInfo(mApnSetting.apn);
            updateTcpBufferSizes(mRilRat);
            mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(), mPhone.getContext(),
                    "DcNetworkAgent", mNetworkInfo, makeNetworkCapabilities(), mLinkProperties,
                    50);
            mNetworkAgent = new DcNetworkAgent(getHandler().getLooper(),
                    mPhone.getContext(),
                    "DcNetworkAgent" + mPhone.getSubId(), mNetworkInfo,
                    makeNetworkCapabilities(), mLinkProperties, 50);
        }

        @Override
+229 −36
Original line number Diff line number Diff line
@@ -63,6 +63,8 @@ import android.telephony.gsm.GsmCellLocation;
import android.text.TextUtils;
import android.util.EventLog;
import android.view.WindowManager;
import android.util.Log;
import android.util.SparseArray;
import android.telephony.Rlog;

import com.android.internal.telephony.cdma.CDMALTEPhone;
@@ -79,6 +81,7 @@ import com.android.internal.telephony.cdma.CDMAPhone;
import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.uicc.IccRecords;
import com.android.internal.telephony.uicc.UiccController;
import com.android.internal.telephony.uicc.IccUtils;
@@ -190,6 +193,30 @@ public final class DcTracker extends DcTrackerBase {

    /* IWLAN and WWAN co-exist flag */
    private boolean mWwanIwlanCoexistFlag = false;
    private long mSubId;


    private BroadcastReceiver defaultDdsBroadcastReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            mSubId = mPhone.getSubId();
            log("got ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED, new DDS = "
                    + intent.getLongExtra(PhoneConstants.SUBSCRIPTION_KEY,
                            SubscriptionManager.INVALID_SUB_ID));
            updateSubIdAndCapability();

            if (mSubId == SubscriptionController.getInstance().getDefaultDataSubId()) {
                log("Dct is default-DDS now, process any pending MMS requests");
            }
        }
    };

    private BroadcastReceiver subInfoBroadcastReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            mSubId = mPhone.getSubId();
            log("got ACTION_SUBINFO_RECORD_UPDATED, mySubId = " + mSubId);
            updateSubIdAndCapability();
        }
    };

    private CdmaApnProfileTracker mOmhApt;

@@ -244,11 +271,11 @@ public final class DcTracker extends DcTrackerBase {
        mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_XCAP);
        mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_EIMS);
        mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
        mNetworkFilter.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
        //Dont add INTERNET capability, only defaultDataSubscription provides INTERNET.

        mNetworkFactory = new TelephonyNetworkFactory(this.getLooper(), p.getContext(),
                "TelephonyNetworkFactory", mNetworkFilter);
        mNetworkFactory.setScoreFilter(50);
                "TelephonyNetworkFactory", mNetworkFilter, mPhone);
        mNetworkFactory.setScoreFilter(-1);
        mNetworkFactoryMessenger = new Messenger(mNetworkFactory);
        cm.registerNetworkFactory(mNetworkFactoryMessenger, "Telephony");

@@ -257,6 +284,20 @@ public final class DcTracker extends DcTrackerBase {
        addEmergencyApnSetting();

        mProvisionActionName = "com.android.internal.telephony.PROVISION" + p.getPhoneId();
        mPhone.getContext().registerReceiver(subInfoBroadcastReceiver,
                new IntentFilter(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED));

        mPhone.getContext().registerReceiver(defaultDdsBroadcastReceiver,
                new IntentFilter(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED));

    }

    private void processPendingNetworkRequests(NetworkRequest n) {
        ((TelephonyNetworkFactory)mNetworkFactory).processPendingNetworkRequests(n);
    }

    private void updateSubIdAndCapability() {
        ((TelephonyNetworkFactory)mNetworkFactory).updateNetworkCapability(mSubId);
    }

    protected void registerForAllEvents() {
@@ -311,6 +352,10 @@ public final class DcTracker extends DcTrackerBase {
        ConnectivityManager cm = (ConnectivityManager)mPhone.getContext().getSystemService(
                Context.CONNECTIVITY_SERVICE);
        cm.unregisterNetworkFactory(mNetworkFactoryMessenger);

        mPhone.getContext().unregisterReceiver(defaultDdsBroadcastReceiver);
        mPhone.getContext().unregisterReceiver(subInfoBroadcastReceiver);

        mNetworkFactoryMessenger = null;

        cleanUpAllConnections(true, null);
@@ -353,23 +398,184 @@ public final class DcTracker extends DcTrackerBase {
    }

    private class TelephonyNetworkFactory extends NetworkFactory {
        public TelephonyNetworkFactory(Looper l, Context c, String TAG, NetworkCapabilities nc) {
        private PhoneBase mPhone;
        private NetworkCapabilities mNetworkCapabilities;

        //Thread safety not required as long as list operation are done by single thread.
        private SparseArray<NetworkRequest> mDdsRequests = new SparseArray<NetworkRequest>();

        public TelephonyNetworkFactory(Looper l, Context c, String TAG,
                NetworkCapabilities nc, PhoneBase phone) {
            super(l, c, TAG, nc);
            mPhone = phone;
            mNetworkCapabilities = nc;
        }

        public void processPendingNetworkRequests(NetworkRequest n) {
            for (int i = 0; i < mDdsRequests.size(); i++) {
                NetworkRequest nr = mDdsRequests.valueAt(i);
                if (nr.equals(n)) {
                    log("Found pending request in ddsRequest list = " + nr);
                    ApnContext apnContext = apnContextForNetworkRequest(nr);
                    if (apnContext != null) {
                        log("Activating APN=" + apnContext);
                        apnContext.incRefCount();
                    }
                }
            }
        }

        private void registerOnDemandDdsCallback() {
            SubscriptionController subController = SubscriptionController.getInstance();

            subController.registerForOnDemandDdsLockNotification(mPhone.getSubId(),
                    new SubscriptionController.OnDemandDdsLockNotifier() {
                        public void notifyOnDemandDdsLockGranted(NetworkRequest n) {
                            log("Got the tempDds lock for the request = " + n);
                            processPendingNetworkRequests(n);
                        }
                    });
        }

        public void updateNetworkCapability(long subId) {
            log("update networkCapabilites for subId = " + subId);

            mNetworkCapabilities.setNetworkSpecifier(""+subId);
            if (subId == SubscriptionController.getInstance().getDefaultDataSubId()) {
                log("INTERNET capability is with subId = " + subId);
                //Only defaultDataSub provides INTERNET.
                mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
            } else {
                log("INTERNET capability is removed from subId = " + subId);
                mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);

            }
            setScoreFilter(50);
            registerOnDemandDdsCallback();

            log("Ready to handle network requests");
        }

        private long getSubIdFromNetworkRequest(NetworkRequest networkRequest) {
            String requestedSpecifierStr = networkRequest.networkCapabilities
                .getNetworkSpecifier();
            long requestedSpecifier = SubscriptionManager.INVALID_SUB_ID;

            try {
                requestedSpecifier = (requestedSpecifierStr != null)? Long.parseLong(
                        requestedSpecifierStr) : SubscriptionManager.INVALID_SUB_ID;
            } catch (NumberFormatException e){
                //nop
            }

            return requestedSpecifier;
        }

        @Override
        protected void needNetworkFor(NetworkRequest networkRequest, int score) {
            // figure out the apn type and enable it
            if (DBG) log("Cellular needs Network for " + networkRequest);
            SubscriptionController subController = SubscriptionController.getInstance();
            log("subController = " + subController);

            long currentDds = subController.getDefaultDataSubId();
            long subId = mPhone.getSubId();
            long requestedSpecifier = getSubIdFromNetworkRequest(networkRequest);

            log("CurrentDds = " + currentDds);
            log("mySubId = " + subId);
            log("Requested networkSpecifier = " + requestedSpecifier);
            log("my networkSpecifier = " + mNetworkCapabilities.getNetworkSpecifier());

            if (subId < 0) {
                log("Can't handle any network request now, subId not ready.");
                return;
            }

            if ((requestedSpecifier != SubscriptionManager.INVALID_SUB_ID)
                    && (currentDds != requestedSpecifier)) {
                log("This request would result in DDS switch");
                log("Requested DDS switch to subId = " + requestedSpecifier);

                //Queue this request and initiate temp DDS switch.
                //Once the DDS switch is done we will revist the pending requests.
                mDdsRequests.put(networkRequest.requestId, networkRequest);
                requestOnDemandDataSubscriptionLock(networkRequest);

                return;
            } else {
                if(isNetworkRequestForInternet(networkRequest)) {
                    log("Activating internet request on subId = " + subId);
                    ApnContext apnContext = apnContextForNetworkRequest(networkRequest);
            if (apnContext != null) apnContext.incRefCount();
                    if (apnContext != null) {
                        log("Activating APN=" + apnContext);
                        apnContext.incRefCount();
                    }
                } else {
                    if(isValidRequest(networkRequest)) {
                        //non-default APN requests for this subscription.
                        mDdsRequests.put(networkRequest.requestId, networkRequest);
                        requestOnDemandDataSubscriptionLock(networkRequest);
                    } else {
                        log("Bogus request req = " + networkRequest);
                    }
                }
            }
        }

        private boolean isValidRequest(NetworkRequest n) {
            int[] types = n.networkCapabilities.getCapabilities();
            return (types.length > 0);
        }

        private boolean isNetworkRequestForInternet(NetworkRequest n) {
            boolean flag = n.networkCapabilities.hasCapability
                (NetworkCapabilities.NET_CAPABILITY_INTERNET);
            log("Is the request for Internet = " + flag);
            return flag;
        }

        private void requestOnDemandDataSubscriptionLock(NetworkRequest n) {
            if(!isNetworkRequestForInternet(n)) {
                //Request tempDDS lock only for non-default PDP requests
                SubscriptionController subController = SubscriptionController.getInstance();
                log("requestOnDemandDataSubscriptionLock for request = " + n);
                subController.startOnDemandDataSubscriptionRequest(n);
            }
        }

        private void removeRequestFromList(SparseArray<NetworkRequest> list, NetworkRequest n) {
            NetworkRequest nr = list.get(n.requestId);
            if (nr != null) {
                log("Removing request = " + nr);
                list.remove(n.requestId);
                ApnContext apnContext = apnContextForNetworkRequest(n);
                if (apnContext != null) {
                    log("Deactivating APN=" + apnContext);
                    apnContext.decRefCount();
                }
            }
        }

        private void removeRequestIfFound(NetworkRequest n) {
            log("Release the request from dds queue, if found");
            removeRequestFromList(mDdsRequests, n);

            if(!isNetworkRequestForInternet(n)) {
                SubscriptionController subController = SubscriptionController.getInstance();
                subController.stopOnDemandDataSubscriptionRequest(n);
            }
        }

        @Override
        protected void releaseNetworkFor(NetworkRequest networkRequest) {
            if (DBG) log("Cellular releasing Network for " + networkRequest);
            ApnContext apnContext = apnContextForNetworkRequest(networkRequest);
            if (apnContext != null) apnContext.decRefCount();
            removeRequestIfFound(networkRequest);
        }

        @Override
        protected void log(String s) {
            Log.d("TelephonyNetworkFactory" + mPhone.getSubId(), s);
        }
    }

@@ -2849,11 +3055,6 @@ public final class DcTracker extends DcTrackerBase {
            return;
        }

        if (!isActiveDataSubscription()) {
            loge("Ignore msgs since phone is not the current DDS");
            return;
        }

        switch (msg.what) {
            case DctConstants.EVENT_RECORDS_LOADED:
                onRecordsLoaded();
@@ -3071,7 +3272,6 @@ public final class DcTracker extends DcTrackerBase {
    // setAsCurrentDataConnectionTracker
    public void update() {
        log("update sub = " + mPhone.getSubId());
        if (isActiveDataSubscription()) {
        log("update(): Active DDS, register for all events now!");
        registerForAllEvents();
        onUpdateIcc();
@@ -3088,11 +3288,6 @@ public final class DcTracker extends DcTrackerBase {
        } else {
            log("Phone object is not MultiSim. This should not hit!!!!");
        }

        } else {
            unregisterForAllEvents();
            log("update(): NOT the active DDS, unregister for all events!");
        }
    }

    @Override
@@ -3101,10 +3296,8 @@ public final class DcTracker extends DcTrackerBase {
    }

    public void updateRecords() {
        if (isActiveDataSubscription()) {
        onUpdateIcc();
    }
    }

    public void cleanUpAllConnections(String cause, Message disconnectAllCompleteMsg) {
        log("cleanUpAllConnections");
Loading