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
This commit is contained in:
@@ -439,6 +439,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
return tracker != null && tracker.setRadio(turnOn);
|
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 {
|
private class FeatureUser implements IBinder.DeathRecipient {
|
||||||
int mNetworkType;
|
int mNetworkType;
|
||||||
String mFeature;
|
String mFeature;
|
||||||
@@ -453,6 +460,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
mBinder = binder;
|
mBinder = binder;
|
||||||
mPid = getCallingPid();
|
mPid = getCallingPid();
|
||||||
mUid = getCallingUid();
|
mUid = getCallingUid();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mBinder.linkToDeath(this, 0);
|
mBinder.linkToDeath(this, 0);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
@@ -467,11 +475,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
public void binderDied() {
|
public void binderDied() {
|
||||||
Log.d(TAG, "ConnectivityService FeatureUser binderDied(" +
|
Log.d(TAG, "ConnectivityService FeatureUser binderDied(" +
|
||||||
mNetworkType + ", " + mFeature + ", " + mBinder);
|
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,
|
public int startUsingNetworkFeature(int networkType, String feature,
|
||||||
IBinder binder) {
|
IBinder binder) {
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
@@ -483,9 +497,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
return Phone.APN_REQUEST_FAILED;
|
return Phone.APN_REQUEST_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mFeatureUsers) {
|
FeatureUser f = new FeatureUser(networkType, feature, binder);
|
||||||
mFeatureUsers.add(new FeatureUser(networkType, feature, binder));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO - move this into the MobileDataStateTracker
|
// TODO - move this into the MobileDataStateTracker
|
||||||
int usedNetworkType = networkType;
|
int usedNetworkType = networkType;
|
||||||
@@ -513,10 +525,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
return Phone.APN_TYPE_NOT_AVAILABLE;
|
return Phone.APN_TYPE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
|
synchronized(this) {
|
||||||
// this gets used for per-pid dns when connected
|
mFeatureUsers.add(f);
|
||||||
mNetRequestersPids[usedNetworkType].add(currentPid);
|
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) &&
|
if ((ni.isConnectedOrConnecting() == true) &&
|
||||||
!network.isTeardownRequested()) {
|
!network.isTeardownRequested()) {
|
||||||
@@ -533,22 +552,17 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
// check if the radio in play can make another contact
|
// check if the radio in play can make another contact
|
||||||
// assume if cannot for now
|
// 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");
|
if (DBG) Log.d(TAG, "reconnecting to special network");
|
||||||
network.reconnect();
|
network.reconnect();
|
||||||
return Phone.APN_REQUEST_STARTED;
|
return Phone.APN_REQUEST_STARTED;
|
||||||
} else {
|
} else {
|
||||||
|
synchronized(this) {
|
||||||
|
mFeatureUsers.add(f);
|
||||||
|
}
|
||||||
|
mHandler.sendMessageDelayed(mHandler.obtainMessage(
|
||||||
|
NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK,
|
||||||
|
f), getRestoreDefaultNetworkDelay());
|
||||||
|
|
||||||
return network.startUsingNetworkFeature(feature,
|
return network.startUsingNetworkFeature(feature,
|
||||||
getCallingPid(), getCallingUid());
|
getCallingPid(), getCallingUid());
|
||||||
}
|
}
|
||||||
@@ -556,13 +570,43 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
return Phone.APN_TYPE_NOT_AVAILABLE;
|
return Phone.APN_TYPE_NOT_AVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// javadoc from interface
|
||||||
public int stopUsingNetworkFeature(int networkType, String feature) {
|
public int stopUsingNetworkFeature(int networkType, String feature) {
|
||||||
return stopUsingNetworkFeature(networkType, feature, getCallingPid(),
|
int pid = getCallingPid();
|
||||||
getCallingUid());
|
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,
|
private int stopUsingNetworkFeature(FeatureUser u, boolean ignoreDups) {
|
||||||
int pid, int uid) {
|
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) {
|
if (DBG) {
|
||||||
Log.d(TAG, "stopUsingNetworkFeature for net " + networkType +
|
Log.d(TAG, "stopUsingNetworkFeature for net " + networkType +
|
||||||
": " + feature);
|
": " + feature);
|
||||||
@@ -572,55 +616,65 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mFeatureUsers) {
|
// need to link the mFeatureUsers list with the mNetRequestersPids state in this
|
||||||
for (int i=0; i < mFeatureUsers.size(); i++) {
|
// sync block
|
||||||
FeatureUser u = (FeatureUser)mFeatureUsers.get(i);
|
synchronized(this) {
|
||||||
if (uid == u.mUid && pid == u.mPid &&
|
// check if this process still has an outstanding start request
|
||||||
networkType == u.mNetworkType &&
|
if (!mFeatureUsers.contains(u)) {
|
||||||
TextUtils.equals(feature, u.mFeature)) {
|
|
||||||
u.unlinkDeathRecipient();
|
|
||||||
mFeatureUsers.remove(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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)) {
|
|
||||||
reassessPidDns(pid, true);
|
|
||||||
}
|
|
||||||
if (mNetRequestersPids[usedNetworkType].size() != 0) {
|
|
||||||
if (DBG) Log.d(TAG, "not tearing down special network - " +
|
|
||||||
"others still using it");
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
u.unlinkDeathRecipient();
|
||||||
tracker.teardown();
|
mFeatureUsers.remove(mFeatureUsers.indexOf(u));
|
||||||
NetworkStateTracker radio = mNetTrackers[networkType];
|
// If we care about duplicate requests, check for that here.
|
||||||
// Check if we want to revert to the default
|
//
|
||||||
if (mHandler.hasMessages(NetworkStateTracker.
|
// This is done to support the extension of a request - the app
|
||||||
EVENT_RESTORE_DEFAULT_NETWORK, radio)) {
|
// can request we start the network feature again and renew the
|
||||||
mHandler.removeMessages(NetworkStateTracker.
|
// auto-shutoff delay. Normal "stop" calls from the app though
|
||||||
EVENT_RESTORE_DEFAULT_NETWORK, radio);
|
// do not pay attention to duplicate requests - in effect the
|
||||||
radio.reconnect();
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 (callTeardown) {
|
||||||
|
tracker.teardown();
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
|
// do it the old fashioned way
|
||||||
return tracker.stopUsingNetworkFeature(feature, pid, uid);
|
return tracker.stopUsingNetworkFeature(feature, pid, uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1231,17 +1285,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
|||||||
// fill me in
|
// fill me in
|
||||||
break;
|
break;
|
||||||
case NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK:
|
case NetworkStateTracker.EVENT_RESTORE_DEFAULT_NETWORK:
|
||||||
for (NetworkStateTracker net : mNetTrackers) {
|
FeatureUser u = (FeatureUser)msg.obj;
|
||||||
NetworkInfo i = net.getNetworkInfo();
|
u.expire();
|
||||||
if (i.isConnected() &&
|
|
||||||
!mNetAttributes[i.getType()].isDefault()) {
|
|
||||||
if (DBG) {
|
|
||||||
Log.d(TAG, "tearing down " + i +
|
|
||||||
" to restore the default network");
|
|
||||||
}
|
|
||||||
teardown(net);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user