diff options
8 files changed, 169 insertions, 79 deletions
diff --git a/core/java/android/net/DummyDataStateTracker.java b/core/java/android/net/DummyDataStateTracker.java index a759865..daa1c09 100644 --- a/core/java/android/net/DummyDataStateTracker.java +++ b/core/java/android/net/DummyDataStateTracker.java @@ -189,6 +189,9 @@ public class DummyDataStateTracker implements NetworkStateTracker { return -1; } + public void setDataEnable(boolean enabled) { + } + @Override public String toString() { StringBuffer sb = new StringBuffer("Dummy data state: none, dummy!"); diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java index 4df8db5..b3a354f 100644 --- a/core/java/android/net/MobileDataStateTracker.java +++ b/core/java/android/net/MobileDataStateTracker.java @@ -20,14 +20,21 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.os.HandlerThread; +import android.os.Looper; +import android.os.Messenger; import android.os.RemoteException; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.ServiceManager; + +import com.android.internal.telephony.DataConnectionTracker; import com.android.internal.telephony.ITelephony; import com.android.internal.telephony.Phone; import com.android.internal.telephony.TelephonyIntents; +import com.android.internal.util.AsyncChannel; + import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo; import android.net.LinkProperties; @@ -67,6 +74,10 @@ public class MobileDataStateTracker implements NetworkStateTracker { // the other is also disconnected before we reset sockets private boolean mIsDefaultOrHipri = false; + private Handler mHandler; + private AsyncChannel mDataConnectionTrackerAc; + private Messenger mMessenger; + /** * Create a new MobileDataStateTracker * @param netType the ConnectivityManager network type @@ -107,14 +118,54 @@ public class MobileDataStateTracker implements NetworkStateTracker { mTarget = target; mContext = context; + HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread"); + handlerThread.start(); + mHandler = new MdstHandler(handlerThread.getLooper(), this); + IntentFilter filter = new IntentFilter(); filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); + filter.addAction(DataConnectionTracker.ACTION_DATA_CONNECTION_TRACKER_MESSENGER); mContext.registerReceiver(new MobileDataStateReceiver(), filter); mMobileDataState = Phone.DataState.DISCONNECTED; } + static class MdstHandler extends Handler { + private MobileDataStateTracker mMdst; + + MdstHandler(Looper looper, MobileDataStateTracker mdst) { + super(looper); + mMdst = mdst; + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: + if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { + if (DBG) { + mMdst.log("MdstHandler connected"); + } + mMdst.mDataConnectionTrackerAc = (AsyncChannel) msg.obj; + } else { + if (DBG) { + mMdst.log("MdstHandler %s NOT connected error=" + msg.arg1); + } + } + break; + case AsyncChannel.CMD_CHANNEL_DISCONNECTED: + mMdst.log("Disconnected from DataStateTracker"); + mMdst.mDataConnectionTrackerAc = null; + break; + default: { + mMdst.log("Ignorning unknown message=" + msg); + break; + } + } + } + } + /** * Return the IP addresses of the DNS servers available for the mobile data * network interface. @@ -179,7 +230,7 @@ public class MobileDataStateTracker implements NetworkStateTracker { false)); if (DBG) { - log(mApnType + " Received state=" + state + ", old=" + mMobileDataState + + log("Received state=" + state + ", old=" + mMobileDataState + ", reason=" + (reason == null ? "(unspecified)" : reason)); } if (mMobileDataState != state) { @@ -265,10 +316,16 @@ public class MobileDataStateTracker implements NetworkStateTracker { String reason = intent.getStringExtra(Phone.FAILURE_REASON_KEY); String apnName = intent.getStringExtra(Phone.DATA_APN_KEY); if (DBG) { - log(mApnType + "Received " + intent.getAction() + + log("Received " + intent.getAction() + " broadcast" + reason == null ? "" : "(" + reason + ")"); } setDetailedState(DetailedState.FAILED, reason, apnName); + } else if (intent.getAction(). + equals(DataConnectionTracker.ACTION_DATA_CONNECTION_TRACKER_MESSENGER)) { + if (DBG) log(mApnType + " got ACTION_DATA_CONNECTION_TRACKER_MESSENGER"); + mMessenger = intent.getParcelableExtra(DataConnectionTracker.EXTRA_MESSENGER); + AsyncChannel ac = new AsyncChannel(); + ac.connect(mContext, MobileDataStateTracker.this.mHandler, mMessenger); } else { if (DBG) log("Broadcast received: ignore " + intent.getAction()); } @@ -488,6 +545,20 @@ public class MobileDataStateTracker implements NetworkStateTracker { return -1; } + /** + * @param enabled + */ + public void setDataEnable(boolean enabled) { + try { + log("setDataEnable: E enabled=" + enabled); + mDataConnectionTrackerAc.sendMessage(DataConnectionTracker.CMD_SET_DATA_ENABLE, + enabled ? DataConnectionTracker.ENABLED : DataConnectionTracker.DISABLED); + log("setDataEnable: X enabled=" + enabled); + } catch (Exception e) { + log("setDataEnable: X mAc was null" + e); + } + } + @Override public String toString() { StringBuffer sb = new StringBuffer("Mobile data state: "); @@ -543,7 +614,7 @@ public class MobileDataStateTracker implements NetworkStateTracker { case ConnectivityManager.TYPE_MOBILE_HIPRI: return Phone.APN_TYPE_HIPRI; default: - loge("Error mapping networkType " + netType + " to apnType."); + sloge("Error mapping networkType " + netType + " to apnType."); return null; } } @@ -562,11 +633,15 @@ public class MobileDataStateTracker implements NetworkStateTracker { return new LinkCapabilities(mLinkCapabilities); } - static private void log(String s) { - Slog.d(TAG, s); + private void log(String s) { + Slog.d(TAG, mApnType + ": " + s); + } + + private void loge(String s) { + Slog.e(TAG, mApnType + ": " + s); } - static private void loge(String s) { + static private void sloge(String s) { Slog.e(TAG, s); } } diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java index 8afdcee..e378506 100644 --- a/core/java/android/net/NetworkStateTracker.java +++ b/core/java/android/net/NetworkStateTracker.java @@ -169,6 +169,11 @@ public interface NetworkStateTracker { public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid); /** + * @param enabled + */ + public void setDataEnable(boolean enabled); + + /** * ------------------------------------------------------------- * Storage API used by ConnectivityService for saving * Network specific information. @@ -204,5 +209,4 @@ public interface NetworkStateTracker { * Indicate tear down requested from connectivity */ public void setTeardownRequested(boolean isRequested); - } diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 758f9f3..9d11d87 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -387,7 +387,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { * the number of different network types is not going * to change very often. */ - boolean noMobileData = !getMobileDataEnabled(); for (int netType : mPriorityList) { switch (mNetAttributes[netType].mRadio) { case ConnectivityManager.TYPE_WIFI: @@ -407,10 +406,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { mNetTrackers[netType] = new MobileDataStateTracker(netType, mNetAttributes[netType].mName); mNetTrackers[netType].startMonitoring(context, mHandler); - if (noMobileData) { - if (DBG) log("tearing down Mobile networks due to setting"); - mNetTrackers[netType].teardown(); - } break; case ConnectivityManager.TYPE_DUMMY: mNetTrackers[netType] = new DummyDataStateTracker(netType, @@ -691,10 +686,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { // TODO - move this into the MobileDataStateTracker int usedNetworkType = networkType; if(networkType == ConnectivityManager.TYPE_MOBILE) { - if (!getMobileDataEnabled()) { - if (DBG) log("requested special network with data disabled - rejected"); - return Phone.APN_TYPE_NOT_AVAILABLE; - } if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) { usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS; } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) { @@ -985,6 +976,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { * @see ConnectivityManager#getMobileDataEnabled() */ public boolean getMobileDataEnabled() { + // TODO: This detail should probably be in DataConnectionTracker's + // which is where we store the value and maybe make this + // asynchronous. enforceAccessPermission(); boolean retVal = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.MOBILE_DATA, 1) == 1; @@ -1004,40 +998,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { } private void handleSetMobileData(boolean enabled) { - if (getMobileDataEnabled() == enabled) return; - - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.MOBILE_DATA, enabled ? 1 : 0); - - if (enabled) { - if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) { - if (DBG) { - log("starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]); - } - mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect(); - } - } else { - for (NetworkStateTracker nt : mNetTrackers) { - if (nt == null) continue; - int netType = nt.getNetworkInfo().getType(); - if (mNetAttributes[netType].mRadio == ConnectivityManager.TYPE_MOBILE) { - if (DBG) log("tearing down " + nt); - nt.teardown(); - } - } - } - } - - private int getNumConnectedNetworks() { - int numConnectedNets = 0; - - for (NetworkStateTracker nt : mNetTrackers) { - if (nt != null && nt.getNetworkInfo().isConnected() && - !nt.isTeardownRequested()) { - ++numConnectedNets; + if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) { + if (DBG) { + Slog.d(TAG, mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled); } + mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled); } - return numConnectedNets; } private void enforceAccessPermission() { @@ -1159,16 +1125,9 @@ public class ConnectivityService extends IConnectivityManager.Stub { int newType = -1; int newPriority = -1; - boolean noMobileData = !getMobileDataEnabled(); for (int checkType=0; checkType <= ConnectivityManager.MAX_NETWORK_TYPE; checkType++) { if (checkType == prevNetType) continue; if (mNetAttributes[checkType] == null) continue; - if (mNetAttributes[checkType].mRadio == ConnectivityManager.TYPE_MOBILE && - noMobileData) { - loge("not failing over to mobile type " + checkType + - " because Mobile Data Disabled"); - continue; - } if (mNetAttributes[checkType].isDefault()) { /* TODO - if we have multiple nets we could use * we may want to put more thought into which we choose diff --git a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java index 069e1b8..737342f 100644 --- a/telephony/java/com/android/internal/telephony/DataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/DataConnectionTracker.java @@ -30,6 +30,7 @@ import android.net.wifi.WifiManager; import android.os.AsyncResult; import android.os.Handler; import android.os.Message; +import android.os.Messenger; import android.os.ServiceManager; import android.preference.PreferenceManager; import android.provider.Settings; @@ -81,6 +82,10 @@ public abstract class DataConnectionTracker extends Handler { DORMANT } + public static String ACTION_DATA_CONNECTION_TRACKER_MESSENGER = + "com.android.internal.telephony"; + public static String EXTRA_MESSENGER = "EXTRA_MESSENGER"; + /***** Event Codes *****/ protected static final int EVENT_DATA_SETUP_COMPLETE = 1; protected static final int EVENT_RADIO_AVAILABLE = 3; @@ -113,6 +118,8 @@ public abstract class DataConnectionTracker extends Handler { protected static final int EVENT_SET_INTERNAL_DATA_ENABLE = 37; protected static final int EVENT_RESET_DONE = 38; + public static final int CMD_SET_DATA_ENABLE = 39; + /***** Constants *****/ protected static final int APN_INVALID_ID = -1; @@ -123,13 +130,18 @@ public abstract class DataConnectionTracker extends Handler { protected static final int APN_HIPRI_ID = 4; protected static final int APN_NUM_TYPES = 5; - protected static final int DISABLED = 0; - protected static final int ENABLED = 1; + public static final int DISABLED = 0; + public static final int ENABLED = 1; // responds to the setInternalDataEnabled call - used internally to turn off data // for example during emergency calls protected boolean mInternalDataEnabled = true; + // responds to public (user) API to enable/disable data use + // independent of mInternalDataEnabled and requests for APN access + // persisted + protected boolean mDataEnabled = true; + protected boolean[] dataEnabled = new boolean[APN_NUM_TYPES]; protected int enabledCount = 0; @@ -289,6 +301,9 @@ public abstract class DataConnectionTracker extends Handler { filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); + mDataEnabled = Settings.Secure.getInt(mPhone.getContext().getContentResolver(), + Settings.Secure.MOBILE_DATA, 1) == 1; + // TODO: Why is this registering the phone as the receiver of the intent // and not its own handler? mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone); @@ -296,16 +311,8 @@ public abstract class DataConnectionTracker extends Handler { // This preference tells us 1) initial condition for "dataEnabled", // and 2) whether the RIL will setup the baseband to auto-PS attach. SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mPhone.getContext()); - boolean dataEnabledSetting = true; - try { - dataEnabledSetting = IConnectivityManager.Stub.asInterface(ServiceManager. - getService(Context.CONNECTIVITY_SERVICE)).getMobileDataEnabled(); - } catch (Exception e) { - // nothing to do - use the old behavior and leave data on - } dataEnabled[APN_DEFAULT_ID] = - !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false) && - dataEnabledSetting; + !sp.getBoolean(PhoneBase.DATA_DISABLED_ON_BOOT_KEY, false); if (dataEnabled[APN_DEFAULT_ID]) { enabledCount++; } @@ -316,6 +323,12 @@ public abstract class DataConnectionTracker extends Handler { mPhone.getContext().unregisterReceiver(this.mIntentReceiver); } + protected void broadcastMessenger() { + Intent intent = new Intent(ACTION_DATA_CONNECTION_TRACKER_MESSENGER); + intent.putExtra(EXTRA_MESSENGER, new Messenger(this)); + mPhone.getContext().sendBroadcast(intent); + } + public Activity getActivity() { return mActivity; } @@ -490,14 +503,20 @@ public abstract class DataConnectionTracker extends Handler { onCleanUpConnection(tearDown, (String) msg.obj); break; - case EVENT_SET_INTERNAL_DATA_ENABLE: + case EVENT_SET_INTERNAL_DATA_ENABLE: { boolean enabled = (msg.arg1 == ENABLED) ? true : false; onSetInternalDataEnabled(enabled); break; - + } case EVENT_RESET_DONE: onResetDone((AsyncResult) msg.obj); break; + case CMD_SET_DATA_ENABLE: { + log("CMD_SET_DATA_ENABLE msg=" + msg); + boolean enabled = (msg.arg1 == ENABLED) ? true : false; + onSetDataEnabled(enabled); + break; + } default: Log.e("DATA", "Unidentified event = " + msg.what); @@ -512,7 +531,7 @@ public abstract class DataConnectionTracker extends Handler { * {@code true} otherwise. */ public synchronized boolean getAnyDataEnabled() { - return (mInternalDataEnabled && (enabledCount != 0)); + return (mInternalDataEnabled && mDataEnabled && (enabledCount != 0)); } protected abstract void startNetStatPoll(); @@ -828,11 +847,6 @@ public abstract class DataConnectionTracker extends Handler { * Prevent mobile data connections from being established, or once again * allow mobile data connections. If the state toggles, then either tear * down or set up data, as appropriate to match the new state. - * <p> - * This operation only affects the default APN, and if the same APN is - * currently being used for MMS traffic, the teardown will not happen even - * when {@code enable} is {@code false}. - * </p> * * @param enable indicates whether to enable ({@code true}) or disable ( * {@code false}) data @@ -849,15 +863,41 @@ public abstract class DataConnectionTracker extends Handler { } protected void onSetInternalDataEnabled(boolean enable) { + boolean prevEnabled = getAnyDataEnabled(); if (mInternalDataEnabled != enable) { synchronized (this) { mInternalDataEnabled = enable; } - if (enable) { - mRetryMgr.resetRetryCount(); - onTrySetupData(Phone.REASON_DATA_ENABLED); - } else { - onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); + if (prevEnabled != getAnyDataEnabled()) { + if (!prevEnabled) { + mRetryMgr.resetRetryCount(); + onTrySetupData(Phone.REASON_DATA_ENABLED); + } else { + onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); + } + } + } + } + + public synchronized boolean getDataEnabled() { + return mDataEnabled; + } + + protected void onSetDataEnabled(boolean enable) { + boolean prevEnabled = getAnyDataEnabled(); + if (mDataEnabled != enable) { + synchronized (this) { + mDataEnabled = enable; + } + Settings.Secure.putInt(mPhone.getContext().getContentResolver(), + Settings.Secure.MOBILE_DATA, enable ? 1 : 0); + if (prevEnabled != getAnyDataEnabled()) { + if (!prevEnabled) { + mRetryMgr.resetRetryCount(); + onTrySetupData(Phone.REASON_DATA_ENABLED); + } else { + onCleanUpConnection(true, Phone.REASON_DATA_DISABLED); + } } } } diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java index b005cd3..60df7df 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaDataConnectionTracker.java @@ -113,6 +113,7 @@ public final class CdmaDataConnectionTracker extends DataConnectionTracker { mDataConnectionTracker = this; createAllDataConnectionList(); + broadcastMessenger(); } @Override diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java index 4713c24..cd0d9e3 100644 --- a/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java +++ b/telephony/java/com/android/internal/telephony/gsm/GsmDataConnectionTracker.java @@ -160,6 +160,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker { /** Create the default connection */ createDataConnection(Phone.APN_TYPE_DEFAULT); + broadcastMessenger(); } @Override diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java index d0231be..2aff7ec 100644 --- a/wifi/java/android/net/wifi/WifiStateTracker.java +++ b/wifi/java/android/net/wifi/WifiStateTracker.java @@ -170,6 +170,13 @@ public class WifiStateTracker implements NetworkStateTracker { } /** + * @param enabled + */ + public void setDataEnable(boolean enabled) { + android.util.Log.d(TAG, "setDataEnabled: IGNORING enabled=" + enabled); + } + + /** * Check if private DNS route is set for the network */ public boolean isPrivateDnsRouteSet() { |