diff options
Diffstat (limited to 'services/java/com/android/server')
5 files changed, 350 insertions, 192 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 851cb33..8c42f31 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -171,6 +171,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { private static final int ENABLED = 1; private static final int DISABLED = 0; + private static final boolean ADD = true; + private static final boolean REMOVE = false; + + private static final boolean TO_DEFAULT_TABLE = true; + private static final boolean TO_SECONDARY_TABLE = false; + // Share the event space with NetworkStateTracker (which can't see this // internal class but sends us events). If you change these, change // NetworkStateTracker.java too. @@ -501,7 +507,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b); - mTethering = new Tethering(mContext, nmService, statsService, mHandler.getLooper()); + mTethering = new Tethering(mContext, nmService, statsService, this, mHandler.getLooper()); mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 || mTethering.getTetherableWifiRegexs().length != 0 || mTethering.getTetherableBluetoothRegexs().length != 0) && @@ -1146,23 +1152,24 @@ public class ConnectivityService extends IConnectivityManager.Stub { return false; } - private boolean addRoute(LinkProperties p, RouteInfo r) { - return modifyRoute(p.getInterfaceName(), p, r, 0, true); + private boolean addRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) { + return modifyRoute(p.getInterfaceName(), p, r, 0, ADD, toDefaultTable); } - private boolean removeRoute(LinkProperties p, RouteInfo r) { - return modifyRoute(p.getInterfaceName(), p, r, 0, false); + private boolean removeRoute(LinkProperties p, RouteInfo r, boolean toDefaultTable) { + return modifyRoute(p.getInterfaceName(), p, r, 0, REMOVE, toDefaultTable); } private boolean addRouteToAddress(LinkProperties lp, InetAddress addr) { - return modifyRouteToAddress(lp, addr, true); + return modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE); } private boolean removeRouteToAddress(LinkProperties lp, InetAddress addr) { - return modifyRouteToAddress(lp, addr, false); + return modifyRouteToAddress(lp, addr, REMOVE, TO_DEFAULT_TABLE); } - private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd) { + private boolean modifyRouteToAddress(LinkProperties lp, InetAddress addr, boolean doAdd, + boolean toDefaultTable) { RouteInfo bestRoute = RouteInfo.selectBestRoute(lp.getRoutes(), addr); if (bestRoute == null) { bestRoute = RouteInfo.makeHostRoute(addr); @@ -1176,15 +1183,15 @@ public class ConnectivityService extends IConnectivityManager.Stub { bestRoute = RouteInfo.makeHostRoute(addr, bestRoute.getGateway()); } } - return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd); + return modifyRoute(lp.getInterfaceName(), lp, bestRoute, 0, doAdd, toDefaultTable); } private boolean modifyRoute(String ifaceName, LinkProperties lp, RouteInfo r, int cycleCount, - boolean doAdd) { + boolean doAdd, boolean toDefaultTable) { if ((ifaceName == null) || (lp == null) || (r == null)) return false; if (cycleCount > MAX_HOSTROUTE_CYCLE_COUNT) { - loge("Error adding route - too much recursion"); + loge("Error modifying route - too much recursion"); return false; } @@ -1199,14 +1206,18 @@ public class ConnectivityService extends IConnectivityManager.Stub { // route to it's gateway bestRoute = RouteInfo.makeHostRoute(r.getGateway(), bestRoute.getGateway()); } - modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd); + modifyRoute(ifaceName, lp, bestRoute, cycleCount+1, doAdd, toDefaultTable); } } if (doAdd) { if (VDBG) log("Adding " + r + " for interface " + ifaceName); - mAddedRoutes.add(r); try { - mNetd.addRoute(ifaceName, r); + if (toDefaultTable) { + mAddedRoutes.add(r); // only track default table - only one apps can effect + mNetd.addRoute(ifaceName, r); + } else { + mNetd.addSecondaryRoute(ifaceName, r); + } } catch (Exception e) { // never crash - catch them all if (VDBG) loge("Exception trying to add a route: " + e); @@ -1215,18 +1226,29 @@ public class ConnectivityService extends IConnectivityManager.Stub { } else { // if we remove this one and there are no more like it, then refcount==0 and // we can remove it from the table - mAddedRoutes.remove(r); - if (mAddedRoutes.contains(r) == false) { + if (toDefaultTable) { + mAddedRoutes.remove(r); + if (mAddedRoutes.contains(r) == false) { + if (VDBG) log("Removing " + r + " for interface " + ifaceName); + try { + mNetd.removeRoute(ifaceName, r); + } catch (Exception e) { + // never crash - catch them all + if (VDBG) loge("Exception trying to remove a route: " + e); + return false; + } + } else { + if (VDBG) log("not removing " + r + " as it's still in use"); + } + } else { if (VDBG) log("Removing " + r + " for interface " + ifaceName); try { - mNetd.removeRoute(ifaceName, r); + mNetd.removeSecondaryRoute(ifaceName, r); } catch (Exception e) { // never crash - catch them all if (VDBG) loge("Exception trying to remove a route: " + e); return false; } - } else { - if (VDBG) log("not removing " + r + " as it's still in use"); } } return true; @@ -1862,14 +1884,21 @@ public class ConnectivityService extends IConnectivityManager.Stub { for (RouteInfo r : routeDiff.removed) { if (isLinkDefault || ! r.isDefaultRoute()) { - removeRoute(curLp, r); + removeRoute(curLp, r, TO_DEFAULT_TABLE); + } + if (isLinkDefault == false) { + // remove from a secondary route table + removeRoute(curLp, r, TO_SECONDARY_TABLE); } } for (RouteInfo r : routeDiff.added) { if (isLinkDefault || ! r.isDefaultRoute()) { - addRoute(newLp, r); + addRoute(newLp, r, TO_DEFAULT_TABLE); } else { + // add to a secondary route table + addRoute(newLp, r, TO_SECONDARY_TABLE); + // many radios add a default route even when we don't want one. // remove the default route unless somebody else has asked for it String ifaceName = newLp.getInterfaceName(); @@ -2450,12 +2479,6 @@ public class ConnectivityService extends IConnectivityManager.Stub { int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1); boolean tetherEnabledInSettings = (Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0); - // Short term disabling of Tethering if DUN is required. - // TODO - fix multi-connection tethering using policy-base routing - int[] upstreamConnTypes = mTethering.getUpstreamIfaceTypes(); - for (int i : upstreamConnTypes) { - if (i == ConnectivityManager.TYPE_MOBILE_DUN) return false; - } return tetherEnabledInSettings && mTetheringConfigValid; } diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index fb13b75..4c26dbb 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -59,7 +59,11 @@ import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Inet4Address; import java.net.InetAddress; +import java.net.InterfaceAddress; +import java.net.NetworkInterface; +import java.net.SocketException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.NoSuchElementException; import java.util.StringTokenizer; @@ -77,6 +81,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub private static final int ADD = 1; private static final int REMOVE = 2; + private static final String DEFAULT = "default"; + private static final String SECONDARY = "secondary"; + /** * Name representing {@link #setGlobalAlert(long)} limit when delivered to * {@link INetworkManagementEventObserver#limitReached(String, String)}. @@ -500,15 +507,25 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void addRoute(String interfaceName, RouteInfo route) { mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); - modifyRoute(interfaceName, ADD, route); + modifyRoute(interfaceName, ADD, route, DEFAULT); } public void removeRoute(String interfaceName, RouteInfo route) { mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); - modifyRoute(interfaceName, REMOVE, route); + modifyRoute(interfaceName, REMOVE, route, DEFAULT); + } + + public void addSecondaryRoute(String interfaceName, RouteInfo route) { + mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); + modifyRoute(interfaceName, ADD, route, SECONDARY); } - private void modifyRoute(String interfaceName, int action, RouteInfo route) { + public void removeSecondaryRoute(String interfaceName, RouteInfo route) { + mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG); + modifyRoute(interfaceName, REMOVE, route, SECONDARY); + } + + private void modifyRoute(String interfaceName, int action, RouteInfo route, String type) { ArrayList<String> rsp; StringBuilder cmd; @@ -516,12 +533,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub switch (action) { case ADD: { - cmd = new StringBuilder("interface route add " + interfaceName); + cmd = new StringBuilder("interface route add " + interfaceName + " " + type); break; } case REMOVE: { - cmd = new StringBuilder("interface route remove " + interfaceName); + cmd = new StringBuilder("interface route remove " + interfaceName + " " + type); break; } default: @@ -828,14 +845,33 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } + private void modifyNat(String cmd, String internalInterface, String externalInterface) + throws SocketException { + cmd = String.format("nat %s %s %s", cmd, internalInterface, externalInterface); + + NetworkInterface internalNetworkInterface = + NetworkInterface.getByName(internalInterface); + Collection<InterfaceAddress>interfaceAddresses = + internalNetworkInterface.getInterfaceAddresses(); + cmd += " " + interfaceAddresses.size(); + for (InterfaceAddress ia : interfaceAddresses) { + InetAddress addr = NetworkUtils.getNetworkPart(ia.getAddress(), + ia.getNetworkPrefixLength()); + cmd = cmd + " " + addr.getHostAddress() + "/" + ia.getNetworkPrefixLength(); + } + + mConnector.doCommand(cmd); + } + public void enableNat(String internalInterface, String externalInterface) throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + if (DBG) Log.d(TAG, "enableNat(" + internalInterface + ", " + externalInterface + ")"); try { - mConnector.doCommand( - String.format("nat enable %s %s", internalInterface, externalInterface)); - } catch (NativeDaemonConnectorException e) { + modifyNat("enable", internalInterface, externalInterface); + } catch (Exception e) { + Log.e(TAG, "enableNat got Exception " + e.toString()); throw new IllegalStateException( "Unable to communicate to native daemon for enabling NAT interface"); } @@ -845,10 +881,11 @@ public class NetworkManagementService extends INetworkManagementService.Stub throws IllegalStateException { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService"); + if (DBG) Log.d(TAG, "disableNat(" + internalInterface + ", " + externalInterface + ")"); try { - mConnector.doCommand( - String.format("nat disable %s %s", internalInterface, externalInterface)); - } catch (NativeDaemonConnectorException e) { + modifyNat("disable", internalInterface, externalInterface); + } catch (Exception e) { + Log.e(TAG, "disableNat got Exception " + e.toString()); throw new IllegalStateException( "Unable to communicate to native daemon for disabling NAT interface"); } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 0d6f405..2a867af 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -120,6 +120,7 @@ import android.view.WindowManagerPolicy; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; +import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; @@ -128,8 +129,10 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.PrintWriter; +import java.io.StringWriter; import java.lang.IllegalStateException; import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -844,9 +847,11 @@ public final class ActivityManagerService extends ActivityManagerNative static final int SHOW_COMPAT_MODE_DIALOG_MSG = 30; static final int DISPATCH_FOREGROUND_ACTIVITIES_CHANGED = 31; static final int DISPATCH_PROCESS_DIED = 32; + static final int REPORT_MEM_USAGE = 33; AlertDialog mUidAlert; CompatModeDialog mCompatModeDialog; + long mLastMemUsageReportTime = 0; final Handler mHandler = new Handler() { //public Handler() { @@ -1186,6 +1191,56 @@ public final class ActivityManagerService extends ActivityManagerNative dispatchProcessDied(pid, uid); break; } + case REPORT_MEM_USAGE: { + boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); + if (!isDebuggable) { + return; + } + synchronized (ActivityManagerService.this) { + long now = SystemClock.uptimeMillis(); + if (now < (mLastMemUsageReportTime+10000)) { + // Don't report more than every 10 seconds to somewhat + // avoid spamming. + return; + } + mLastMemUsageReportTime = now; + } + Thread thread = new Thread() { + @Override public void run() { + try { + java.lang.Process proc = Runtime.getRuntime().exec(new String[] { + "procrank", }); + final InputStreamReader converter = new InputStreamReader( + proc.getInputStream()); + BufferedReader in = new BufferedReader(converter); + String line; + while (true) { + line = in.readLine(); + if (line == null) { + break; + } + if (line.length() > 0) { + Slog.i(TAG, line); + } + } + converter.close(); + } catch (IOException e) { + } + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + dumpApplicationMemoryUsage(null, pw, " ", new String[] { }, true); + Slog.i(TAG, sw.toString()); + synchronized (ActivityManagerService.this) { + long now = SystemClock.uptimeMillis(); + if (mLastMemUsageReportTime < now) { + mLastMemUsageReportTime = now; + } + } + } + }; + thread.start(); + break; + } } } }; @@ -1326,7 +1381,7 @@ public final class ActivityManagerService extends ActivityManagerNative return; } - mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args); + mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false); } } @@ -2755,6 +2810,7 @@ public final class ActivityManagerService extends ActivityManagerNative addProcessToGcListLocked(rec); } } + mHandler.sendEmptyMessage(REPORT_MEM_USAGE); scheduleAppGcsLocked(); } } @@ -9216,7 +9272,7 @@ public final class ActivityManagerService extends ActivityManagerNative } final void dumpApplicationMemoryUsage(FileDescriptor fd, - PrintWriter pw, String prefix, String[] args) { + PrintWriter pw, String prefix, String[] args, boolean brief) { boolean dumpAll = false; int opti = 0; @@ -9354,15 +9410,19 @@ public final class ActivityManagerService extends ActivityManagerNative } } - pw.println(); - pw.println("Total PSS by process:"); - dumpMemItems(pw, " ", procMems, true); - pw.println(); + if (!brief) { + pw.println(); + pw.println("Total PSS by process:"); + dumpMemItems(pw, " ", procMems, true); + pw.println(); + } pw.println("Total PSS by OOM adjustment:"); dumpMemItems(pw, " ", oomMems, false); - pw.println(); - pw.println("Total PSS by category:"); - dumpMemItems(pw, " ", catMems, true); + if (!brief) { + pw.println(); + pw.println("Total PSS by category:"); + dumpMemItems(pw, " ", catMems, true); + } pw.println(); pw.print("Total PSS: "); pw.print(totalPss); pw.println(" Kb"); } diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java index 7bd29d9..423a78f 100644 --- a/services/java/com/android/server/connectivity/Tethering.java +++ b/services/java/com/android/server/connectivity/Tethering.java @@ -81,6 +81,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private String[] mTetherableBluetoothRegexs; private Collection<Integer> mUpstreamIfaceTypes; + // used to synchronize public access to members + private Object mPublicSync; + private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE); private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI); private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN); @@ -91,6 +94,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { private final INetworkManagementService mNMService; private final INetworkStatsService mStatsService; + private final IConnectivityManager mConnService; private Looper mLooper; private HandlerThread mThread; @@ -127,12 +131,15 @@ public class Tethering extends INetworkManagementEventObserver.Stub { // when RNDIS is enabled public Tethering(Context context, INetworkManagementService nmService, - INetworkStatsService statsService, Looper looper) { + INetworkStatsService statsService, IConnectivityManager connService, Looper looper) { mContext = context; mNMService = nmService; mStatsService = statsService; + mConnService = connService; mLooper = looper; + mPublicSync = new Object(); + mIfaces = new HashMap<String, TetherInterfaceSM>(); // make our own thread so we don't anr the system @@ -170,18 +177,25 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } void updateConfiguration() { - mTetherableUsbRegexs = mContext.getResources().getStringArray( + String[] tetherableUsbRegexs = mContext.getResources().getStringArray( com.android.internal.R.array.config_tether_usb_regexs); - mTetherableWifiRegexs = mContext.getResources().getStringArray( + String[] tetherableWifiRegexs = mContext.getResources().getStringArray( com.android.internal.R.array.config_tether_wifi_regexs); - mTetherableBluetoothRegexs = mContext.getResources().getStringArray( + String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray( com.android.internal.R.array.config_tether_bluetooth_regexs); int ifaceTypes[] = mContext.getResources().getIntArray( com.android.internal.R.array.config_tether_upstream_types); - mUpstreamIfaceTypes = new ArrayList(); + Collection<Integer> upstreamIfaceTypes = new ArrayList(); for (int i : ifaceTypes) { - mUpstreamIfaceTypes.add(new Integer(i)); + upstreamIfaceTypes.add(new Integer(i)); + } + + synchronized (mPublicSync) { + mTetherableUsbRegexs = tetherableUsbRegexs; + mTetherableWifiRegexs = tetherableWifiRegexs; + mTetherableBluetoothRegexs = tetherableBluetoothRegexs; + mUpstreamIfaceTypes = upstreamIfaceTypes; } // check if the upstream type list needs to be modified due to secure-settings @@ -192,17 +206,17 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up); boolean found = false; boolean usb = false; - if (isWifi(iface)) { - found = true; - } else if (isUsb(iface)) { - found = true; - usb = true; - } else if (isBluetooth(iface)) { - found = true; - } - if (found == false) return; + synchronized (mPublicSync) { + if (isWifi(iface)) { + found = true; + } else if (isUsb(iface)) { + found = true; + usb = true; + } else if (isBluetooth(iface)) { + found = true; + } + if (found == false) return; - synchronized (mIfaces) { TetherInterfaceSM sm = mIfaces.get(iface); if (up) { if (sm == null) { @@ -229,46 +243,52 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } private boolean isUsb(String iface) { - for (String regex : mTetherableUsbRegexs) { - if (iface.matches(regex)) return true; + synchronized (mPublicSync) { + for (String regex : mTetherableUsbRegexs) { + if (iface.matches(regex)) return true; + } + return false; } - return false; } public boolean isWifi(String iface) { - for (String regex : mTetherableWifiRegexs) { - if (iface.matches(regex)) return true; + synchronized (mPublicSync) { + for (String regex : mTetherableWifiRegexs) { + if (iface.matches(regex)) return true; + } + return false; } - return false; } public boolean isBluetooth(String iface) { - for (String regex : mTetherableBluetoothRegexs) { - if (iface.matches(regex)) return true; + synchronized (mPublicSync) { + for (String regex : mTetherableBluetoothRegexs) { + if (iface.matches(regex)) return true; + } + return false; } - return false; } public void interfaceAdded(String iface) { if (VDBG) Log.d(TAG, "interfaceAdded " + iface); boolean found = false; boolean usb = false; - if (isWifi(iface)) { - found = true; - } - if (isUsb(iface)) { - found = true; - usb = true; - } - if (isBluetooth(iface)) { - found = true; - } - if (found == false) { - if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring"); - return; - } + synchronized (mPublicSync) { + if (isWifi(iface)) { + found = true; + } + if (isUsb(iface)) { + found = true; + usb = true; + } + if (isBluetooth(iface)) { + found = true; + } + if (found == false) { + if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring"); + return; + } - synchronized (mIfaces) { TetherInterfaceSM sm = mIfaces.get(iface); if (sm != null) { if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring"); @@ -283,7 +303,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { public void interfaceRemoved(String iface) { if (VDBG) Log.d(TAG, "interfaceRemoved " + iface); - synchronized (mIfaces) { + synchronized (mPublicSync) { TetherInterfaceSM sm = mIfaces.get(iface); if (sm == null) { if (VDBG) { @@ -301,7 +321,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { public int tether(String iface) { if (DBG) Log.d(TAG, "Tethering " + iface); TetherInterfaceSM sm = null; - synchronized (mIfaces) { + synchronized (mPublicSync) { sm = mIfaces.get(iface); } if (sm == null) { @@ -319,7 +339,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { public int untether(String iface) { if (DBG) Log.d(TAG, "Untethering " + iface); TetherInterfaceSM sm = null; - synchronized (mIfaces) { + synchronized (mPublicSync) { sm = mIfaces.get(iface); } if (sm == null) { @@ -336,21 +356,22 @@ public class Tethering extends INetworkManagementEventObserver.Stub { public int getLastTetherError(String iface) { TetherInterfaceSM sm = null; - synchronized (mIfaces) { + synchronized (mPublicSync) { sm = mIfaces.get(iface); + if (sm == null) { + Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + + ", ignoring"); + return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; + } + return sm.getLastError(); } - if (sm == null) { - Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface + ", ignoring"); - return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE; - } - return sm.getLastError(); } + // TODO - move all private methods used only by the state machine into the state machine + // to clarify what needs synchronized protection. private void sendTetherStateChangedBroadcast() { - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); try { - if (!cm.isTetheringSupported()) return; + if (!mConnService.isTetheringSupported()) return; } catch (RemoteException e) { return; } @@ -363,7 +384,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { boolean usbTethered = false; boolean bluetoothTethered = false; - synchronized (mIfaces) { + synchronized (mPublicSync) { Set ifaces = mIfaces.keySet(); for (Object iface : ifaces) { TetherInterfaceSM sm = mIfaces.get(iface); @@ -469,7 +490,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { public void onReceive(Context content, Intent intent) { String action = intent.getAction(); if (action.equals(UsbManager.ACTION_USB_STATE)) { - synchronized (Tethering.this) { + synchronized (Tethering.this.mPublicSync) { boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false); // start tethering if we have a request pending @@ -545,6 +566,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return true; } + // TODO - return copies so people can't tamper public String[] getTetherableUsbRegexs() { return mTetherableUsbRegexs; } @@ -561,7 +583,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")"); UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE); - synchronized (this) { + synchronized (mPublicSync) { if (enable) { if (mRndisEnabled) { tetherUsb(true); @@ -581,11 +603,14 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } public int[] getUpstreamIfaceTypes() { - updateConfiguration(); - int values[] = new int[mUpstreamIfaceTypes.size()]; - Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator(); - for (int i=0; i < mUpstreamIfaceTypes.size(); i++) { - values[i] = iterator.next(); + int values[]; + synchronized (mPublicSync) { + updateConfiguration(); + values = new int[mUpstreamIfaceTypes.size()]; + Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator(); + for (int i=0; i < mUpstreamIfaceTypes.size(); i++) { + values[i] = iterator.next(); + } } return values; } @@ -593,43 +618,46 @@ public class Tethering extends INetworkManagementEventObserver.Stub { public void checkDunRequired() { int secureSetting = Settings.Secure.getInt(mContext.getContentResolver(), Settings.Secure.TETHER_DUN_REQUIRED, 2); - // 2 = not set, 0 = DUN not required, 1 = DUN required - if (secureSetting != 2) { - int requiredApn = (secureSetting == 1 ? - ConnectivityManager.TYPE_MOBILE_DUN : - ConnectivityManager.TYPE_MOBILE_HIPRI); - if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) { - while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) { - mUpstreamIfaceTypes.remove(MOBILE_TYPE); - } - while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) { - mUpstreamIfaceTypes.remove(HIPRI_TYPE); - } - if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) { - mUpstreamIfaceTypes.add(DUN_TYPE); + synchronized (mPublicSync) { + // 2 = not set, 0 = DUN not required, 1 = DUN required + if (secureSetting != 2) { + int requiredApn = (secureSetting == 1 ? + ConnectivityManager.TYPE_MOBILE_DUN : + ConnectivityManager.TYPE_MOBILE_HIPRI); + if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) { + while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) { + mUpstreamIfaceTypes.remove(MOBILE_TYPE); + } + while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) { + mUpstreamIfaceTypes.remove(HIPRI_TYPE); + } + if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) { + mUpstreamIfaceTypes.add(DUN_TYPE); + } + } else { + while (mUpstreamIfaceTypes.contains(DUN_TYPE)) { + mUpstreamIfaceTypes.remove(DUN_TYPE); + } + if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) { + mUpstreamIfaceTypes.add(MOBILE_TYPE); + } + if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) { + mUpstreamIfaceTypes.add(HIPRI_TYPE); + } } + } + if (mUpstreamIfaceTypes.contains(DUN_TYPE)) { + mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN; } else { - while (mUpstreamIfaceTypes.contains(DUN_TYPE)) { - mUpstreamIfaceTypes.remove(DUN_TYPE); - } - if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) { - mUpstreamIfaceTypes.add(MOBILE_TYPE); - } - if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) { - mUpstreamIfaceTypes.add(HIPRI_TYPE); - } + mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI; } } - if (mUpstreamIfaceTypes.contains(DUN_TYPE)) { - mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN; - } else { - mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI; - } } + // TODO review API - maybe return ArrayList<String> here and below? public String[] getTetheredIfaces() { ArrayList<String> list = new ArrayList<String>(); - synchronized (mIfaces) { + synchronized (mPublicSync) { Set keys = mIfaces.keySet(); for (Object key : keys) { TetherInterfaceSM sm = mIfaces.get(key); @@ -647,7 +675,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { public String[] getTetheredIfacePairs() { final ArrayList<String> list = Lists.newArrayList(); - synchronized (mIfaces) { + synchronized (mPublicSync) { for (TetherInterfaceSM sm : mIfaces.values()) { if (sm.isTethered()) { list.add(sm.mMyUpstreamIfaceName); @@ -660,7 +688,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { public String[] getTetherableIfaces() { ArrayList<String> list = new ArrayList<String>(); - synchronized (mIfaces) { + synchronized (mPublicSync) { Set keys = mIfaces.keySet(); for (Object key : keys) { TetherInterfaceSM sm = mIfaces.get(key); @@ -678,7 +706,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { public String[] getErroredIfaces() { ArrayList<String> list = new ArrayList<String>(); - synchronized (mIfaces) { + synchronized (mPublicSync) { Set keys = mIfaces.keySet(); for (Object key : keys) { TetherInterfaceSM sm = mIfaces.get(key); @@ -777,43 +805,54 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return res; } - public synchronized int getLastError() { - return mLastError; + public int getLastError() { + synchronized (Tethering.this.mPublicSync) { + return mLastError; + } } - private synchronized void setLastError(int error) { - mLastError = error; + private void setLastError(int error) { + synchronized (Tethering.this.mPublicSync) { + mLastError = error; - if (isErrored()) { - if (mUsb) { - // note everything's been unwound by this point so nothing to do on - // further error.. - Tethering.this.configureUsbIface(false); + if (isErrored()) { + if (mUsb) { + // note everything's been unwound by this point so nothing to do on + // further error.. + Tethering.this.configureUsbIface(false); + } } } } - // synchronized between this getter and the following setter - public synchronized boolean isAvailable() { - return mAvailable; + public boolean isAvailable() { + synchronized (Tethering.this.mPublicSync) { + return mAvailable; + } } - private synchronized void setAvailable(boolean available) { - mAvailable = available; + private void setAvailable(boolean available) { + synchronized (Tethering.this.mPublicSync) { + mAvailable = available; + } } - // synchronized between this getter and the following setter - public synchronized boolean isTethered() { - return mTethered; + public boolean isTethered() { + synchronized (Tethering.this.mPublicSync) { + return mTethered; + } } - private synchronized void setTethered(boolean tethered) { - mTethered = tethered; + private void setTethered(boolean tethered) { + synchronized (Tethering.this.mPublicSync) { + mTethered = tethered; + } } - // synchronized between this getter and the following setter - public synchronized boolean isErrored() { - return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR); + public boolean isErrored() { + synchronized (Tethering.this.mPublicSync) { + return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR); + } } class InitialState extends State { @@ -910,6 +949,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { try { mNMService.tetherInterface(mIfaceName); } catch (Exception e) { + Log.e(TAG, "Error Tethering: " + e.toString()); setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR); transitionTo(mInitialState); @@ -921,7 +961,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { sendTetherStateChangedBroadcast(); } - void cleanupUpstream() { + private void cleanupUpstream() { if (mMyUpstreamIfaceName != null) { // note that we don't care about errors here. // sometimes interfaces are gone before we get @@ -987,6 +1027,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { try { mNMService.enableNat(mIfaceName, newUpstreamIfaceName); } catch (Exception e) { + Log.e(TAG, "Exception enabling Nat: " + e.toString()); try { mNMService.untetherInterface(mIfaceName); } catch (Exception ee) {} @@ -1150,13 +1191,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub { boolean retValue = true; if (apnType == ConnectivityManager.TYPE_NONE) return false; if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection(); - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); int result = Phone.APN_REQUEST_FAILED; String enableString = enableString(apnType); if (enableString == null) return false; try { - result = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, + result = mConnService.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, enableString, new Binder()); } catch (Exception e) { } @@ -1178,10 +1217,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } protected boolean turnOffUpstreamMobileConnection() { if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) { - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); try { - cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, + mConnService.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, enableString(mMobileApnReserved)); } catch (Exception e) { return false; @@ -1234,28 +1271,28 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } protected void chooseUpstreamType(boolean tryCell) { - IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); - IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b); int upType = ConnectivityManager.TYPE_NONE; String iface = null; updateConfiguration(); - if (VDBG) { - Log.d(TAG, "chooseUpstreamType has upstream iface types:"); - for (Integer netType : mUpstreamIfaceTypes) { - Log.d(TAG, " " + netType); + synchronized (mPublicSync) { + if (VDBG) { + Log.d(TAG, "chooseUpstreamType has upstream iface types:"); + for (Integer netType : mUpstreamIfaceTypes) { + Log.d(TAG, " " + netType); + } } - } - for (Integer netType : mUpstreamIfaceTypes) { - NetworkInfo info = null; - try { - info = cm.getNetworkInfo(netType.intValue()); - } catch (RemoteException e) { } - if ((info != null) && info.isConnected()) { - upType = netType.intValue(); - break; + for (Integer netType : mUpstreamIfaceTypes) { + NetworkInfo info = null; + try { + info = mConnService.getNetworkInfo(netType.intValue()); + } catch (RemoteException e) { } + if ((info != null) && info.isConnected()) { + upType = netType.intValue(); + break; + } } } @@ -1283,7 +1320,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub { } else { LinkProperties linkProperties = null; try { - linkProperties = cm.getLinkProperties(upType); + linkProperties = mConnService.getLinkProperties(upType); } catch (RemoteException e) { } if (linkProperties != null) iface = linkProperties.getInterfaceName(); } @@ -1483,14 +1520,14 @@ public class Tethering extends INetworkManagementEventObserver.Stub { return; } - pw.println("mUpstreamIfaceTypes: "); - for (Integer netType : mUpstreamIfaceTypes) { - pw.println(" " + netType); - } + synchronized (mPublicSync) { + pw.println("mUpstreamIfaceTypes: "); + for (Integer netType : mUpstreamIfaceTypes) { + pw.println(" " + netType); + } - pw.println(); - pw.println("Tether state:"); - synchronized (mIfaces) { + pw.println(); + pw.println("Tether state:"); for (Object o : mIfaces.values()) { pw.println(" "+o.toString()); } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index a199a7e..122d515 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -8660,7 +8660,8 @@ public class WindowManagerService extends IWindowManager.Stub if (needRelayout) { requestAnimationLocked(0); } else if (animating) { - requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis()); + final int refreshTimeUs = (int)(1000 / mDisplay.getRefreshRate()); + requestAnimationLocked(currentTime + refreshTimeUs - SystemClock.uptimeMillis()); } // Finally update all input windows now that the window changes have stabilized. |
