diff options
author | Robert Greenwalt <robdroid@android.com> | 2009-09-27 17:27:04 -0700 |
---|---|---|
committer | Robert Greenwalt <robdroid@android.com> | 2009-09-29 13:18:17 -0700 |
commit | 9c75d4af63f92806943a9fa9d942644bd601310e (patch) | |
tree | 2e374bf20f08475d141ed9de86f17a958d72e0c8 /services/java | |
parent | 7db7e6a00c5a0b38bb2077d93a009581941884d3 (diff) | |
download | frameworks_base-9c75d4af63f92806943a9fa9d942644bd601310e.zip frameworks_base-9c75d4af63f92806943a9fa9d942644bd601310e.tar.gz frameworks_base-9c75d4af63f92806943a9fa9d942644bd601310e.tar.bz2 |
Fix network-feature timeout code.
Track requests independently with seperate timers. Clean up on expiration
by just stopping that particular request, not immediately restoring the default.
bug: 2127590
Diffstat (limited to 'services/java')
-rw-r--r-- | services/java/com/android/server/ConnectivityService.java | 191 |
1 files changed, 118 insertions, 73 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 63845e9..798bcd2 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -439,6 +439,13 @@ public class ConnectivityService extends IConnectivityManager.Stub { return tracker != null && tracker.setRadio(turnOn); } + /** + * Used to notice when the calling process dies so we can self-expire + * + * Also used to know if the process has cleaned up after itself when + * our auto-expire timer goes off. The timer has a link to an object. + * + */ private class FeatureUser implements IBinder.DeathRecipient { int mNetworkType; String mFeature; @@ -453,6 +460,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { mBinder = binder; mPid = getCallingPid(); mUid = getCallingUid(); + try { mBinder.linkToDeath(this, 0); } catch (RemoteException e) { @@ -467,11 +475,17 @@ public class ConnectivityService extends IConnectivityManager.Stub { public void binderDied() { Log.d(TAG, "ConnectivityService FeatureUser binderDied(" + mNetworkType + ", " + mFeature + ", " + mBinder); - stopUsingNetworkFeature(mNetworkType, mFeature, mPid, mUid); + stopUsingNetworkFeature(this, false); } + public void expire() { + Log.d(TAG, "ConnectivityService FeatureUser expire(" + + mNetworkType + ", " + mFeature + ", " + mBinder); + stopUsingNetworkFeature(this, false); + } } + // javadoc from interface public int startUsingNetworkFeature(int networkType, String feature, IBinder binder) { if (DBG) { @@ -483,9 +497,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { return Phone.APN_REQUEST_FAILED; } - synchronized (mFeatureUsers) { - mFeatureUsers.add(new FeatureUser(networkType, feature, binder)); - } + FeatureUser f = new FeatureUser(networkType, feature, binder); // TODO - move this into the MobileDataStateTracker int usedNetworkType = networkType; @@ -513,10 +525,17 @@ public class ConnectivityService extends IConnectivityManager.Stub { return Phone.APN_TYPE_NOT_AVAILABLE; } - if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) { - // this gets used for per-pid dns when connected - mNetRequestersPids[usedNetworkType].add(currentPid); + synchronized(this) { + mFeatureUsers.add(f); + if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) { + // this gets used for per-pid dns when connected + mNetRequestersPids[usedNetworkType].add(currentPid); + } } + mHandler.sendMessageDelayed(mHandler.obtainMessage( + NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK, + f), getRestoreDefaultNetworkDelay()); + if ((ni.isConnectedOrConnecting() == true) && !network.isTeardownRequested()) { @@ -533,22 +552,17 @@ public class ConnectivityService extends IConnectivityManager.Stub { // check if the radio in play can make another contact // assume if cannot for now - // since we have to drop the default on this radio, setup - // an automatic event to switch back - if(mHandler.hasMessages(NetworkStateTracker. - EVENT_RESTORE_DEFAULT_NETWORK, radio) || - radio.getNetworkInfo().isConnectedOrConnecting()) { - mHandler.removeMessages(NetworkStateTracker. - EVENT_RESTORE_DEFAULT_NETWORK, - radio); - mHandler.sendMessageDelayed(mHandler.obtainMessage( - NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK, - radio), getRestoreDefaultNetworkDelay()); - } if (DBG) Log.d(TAG, "reconnecting to special network"); network.reconnect(); return Phone.APN_REQUEST_STARTED; } else { + synchronized(this) { + mFeatureUsers.add(f); + } + mHandler.sendMessageDelayed(mHandler.obtainMessage( + NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK, + f), getRestoreDefaultNetworkDelay()); + return network.startUsingNetworkFeature(feature, getCallingPid(), getCallingUid()); } @@ -556,13 +570,43 @@ public class ConnectivityService extends IConnectivityManager.Stub { return Phone.APN_TYPE_NOT_AVAILABLE; } + // javadoc from interface public int stopUsingNetworkFeature(int networkType, String feature) { - return stopUsingNetworkFeature(networkType, feature, getCallingPid(), - getCallingUid()); + int pid = getCallingPid(); + int uid = getCallingUid(); + + FeatureUser u = null; + boolean found = false; + + synchronized(this) { + for (int i = 0; i < mFeatureUsers.size() ; i++) { + u = (FeatureUser)mFeatureUsers.get(i); + if (uid == u.mUid && pid == u.mPid && + networkType == u.mNetworkType && + TextUtils.equals(feature, u.mFeature)) { + found = true; + break; + } + } + } + if (found && u != null) { + // stop regardless of how many other time this proc had called start + return stopUsingNetworkFeature(u, true); + } else { + // none found! + return 1; + } } - private int stopUsingNetworkFeature(int networkType, String feature, - int pid, int uid) { + private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) { + int networkType = u.mNetworkType; + String feature = u.mFeature; + int pid = u.mPid; + int uid = u.mUid; + + NetworkStateTracker tracker = null; + boolean callTeardown = false; // used to carry our decision outside of sync block + if (DBG) { Log.d(TAG, "stopUsingNetworkFeature for net " + networkType + ": " + feature); @@ -572,55 +616,65 @@ public class ConnectivityService extends IConnectivityManager.Stub { return -1; } - synchronized (mFeatureUsers) { - for (int i=0; i < mFeatureUsers.size(); i++) { - FeatureUser u = (FeatureUser)mFeatureUsers.get(i); - if (uid == u.mUid && pid == u.mPid && - networkType == u.mNetworkType && - TextUtils.equals(feature, u.mFeature)) { - u.unlinkDeathRecipient(); - mFeatureUsers.remove(i); - break; + // need to link the mFeatureUsers list with the mNetRequestersPids state in this + // sync block + synchronized(this) { + // check if this process still has an outstanding start request + if (!mFeatureUsers.contains(u)) { + return 1; + } + u.unlinkDeathRecipient(); + mFeatureUsers.remove(mFeatureUsers.indexOf(u)); + // If we care about duplicate requests, check for that here. + // + // This is done to support the extension of a request - the app + // can request we start the network feature again and renew the + // auto-shutoff delay. Normal "stop" calls from the app though + // do not pay attention to duplicate requests - in effect the + // API does not refcount and a single stop will counter multiple starts. + if (ignoreDups == false) { + for (int i = 0; i < mFeatureUsers.size() ; i++) { + FeatureUser x = (FeatureUser)mFeatureUsers.get(i); + if (x.mUid == u.mUid && x.mPid == u.mPid && + x.mNetworkType == u.mNetworkType && + TextUtils.equals(x.mFeature, u.mFeature)) { + return 1; + } } } - } - // TODO - move to MobileDataStateTracker - int usedNetworkType = networkType; - if (networkType == ConnectivityManager.TYPE_MOBILE) { - if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) { - usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS; - } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) { - usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL; - } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) { - usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN; - } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) { - usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI; + // TODO - move to MobileDataStateTracker + int usedNetworkType = networkType; + if (networkType == ConnectivityManager.TYPE_MOBILE) { + if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) { + usedNetworkType = ConnectivityManager.TYPE_MOBILE_MMS; + } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) { + usedNetworkType = ConnectivityManager.TYPE_MOBILE_SUPL; + } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_DUN)) { + usedNetworkType = ConnectivityManager.TYPE_MOBILE_DUN; + } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_HIPRI)) { + usedNetworkType = ConnectivityManager.TYPE_MOBILE_HIPRI; + } } - } - NetworkStateTracker tracker = mNetTrackers[usedNetworkType]; - if(usedNetworkType != networkType) { - Integer currentPid = new Integer(pid); - if (mNetRequestersPids[usedNetworkType].remove(currentPid)) { + tracker = mNetTrackers[usedNetworkType]; + if(usedNetworkType != networkType) { + Integer currentPid = new Integer(pid); reassessPidDns(pid, true); + mNetRequestersPids[usedNetworkType].remove(currentPid); + if (mNetRequestersPids[usedNetworkType].size() != 0) { + if (DBG) Log.d(TAG, "not tearing down special network - " + + "others still using it"); + return 1; + } + callTeardown = true; } - if (mNetRequestersPids[usedNetworkType].size() != 0) { - if (DBG) Log.d(TAG, "not tearing down special network - " + - "others still using it"); - return 1; - } + } + if (callTeardown) { tracker.teardown(); - NetworkStateTracker radio = mNetTrackers[networkType]; - // Check if we want to revert to the default - if (mHandler.hasMessages(NetworkStateTracker. - EVENT_RESTORE_DEFAULT_NETWORK, radio)) { - mHandler.removeMessages(NetworkStateTracker. - EVENT_RESTORE_DEFAULT_NETWORK, radio); - radio.reconnect(); - } return 1; } else { + // do it the old fashioned way return tracker.stopUsingNetworkFeature(feature, pid, uid); } } @@ -1231,17 +1285,8 @@ public class ConnectivityService extends IConnectivityManager.Stub { // fill me in break; case NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK: - for (NetworkStateTracker net : mNetTrackers) { - NetworkInfo i = net.getNetworkInfo(); - if (i.isConnected() && - !mNetAttributes[i.getType()].isDefault()) { - if (DBG) { - Log.d(TAG, "tearing down " + i + - " to restore the default network"); - } - teardown(net); - } - } + FeatureUser u = (FeatureUser)msg.obj; + u.expire(); break; } } |