summaryrefslogtreecommitdiffstats
path: root/services/java/com/android
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android')
-rw-r--r--services/java/com/android/server/ConnectivityService.java171
-rw-r--r--services/java/com/android/server/DockObserver.java4
-rw-r--r--services/java/com/android/server/NetworkManagementService.java65
-rw-r--r--services/java/com/android/server/PowerManagerService.java9
-rw-r--r--services/java/com/android/server/TextServicesManagerService.java36
-rw-r--r--services/java/com/android/server/UiModeManagerService.java45
-rw-r--r--services/java/com/android/server/WifiService.java52
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java199
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java81
-rw-r--r--services/java/com/android/server/am/ActivityStack.java197
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java348
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java55
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java58
-rw-r--r--services/java/com/android/server/pm/Settings.java6
-rw-r--r--services/java/com/android/server/wm/InputManager.java8
-rw-r--r--services/java/com/android/server/wm/ScreenRotationAnimation.java3
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java150
17 files changed, 988 insertions, 499 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 851cb33..6e4aca7 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -26,8 +26,10 @@ import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import android.bluetooth.BluetoothTetheringDataTracker;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.ContextWrapper;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.database.ContentObserver;
import android.net.ConnectivityManager;
import android.net.DummyDataStateTracker;
@@ -51,6 +53,7 @@ import android.net.Proxy;
import android.net.ProxyProperties;
import android.net.RouteInfo;
import android.net.wifi.WifiStateTracker;
+import android.net.wimax.WimaxManagerConstants;
import android.os.Binder;
import android.os.FileUtils;
import android.os.Handler;
@@ -78,10 +81,14 @@ import com.android.server.connectivity.Tethering;
import com.android.server.connectivity.Vpn;
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
-
+import dalvik.system.DexClassLoader;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.InvocationTargetException;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
@@ -171,6 +178,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.
@@ -485,6 +498,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mNetTrackers[netType] = BluetoothTetheringDataTracker.getInstance();
mNetTrackers[netType].startMonitoring(context, mHandler);
break;
+ case ConnectivityManager.TYPE_WIMAX:
+ mNetTrackers[netType] = makeWimaxStateTracker();
+ if (mNetTrackers[netType]!= null) {
+ mNetTrackers[netType].startMonitoring(context, mHandler);
+ }
+ break;
case ConnectivityManager.TYPE_ETHERNET:
mNetTrackers[netType] = EthernetDataTracker.getInstance();
mNetTrackers[netType].startMonitoring(context, mHandler);
@@ -495,13 +514,15 @@ public class ConnectivityService extends IConnectivityManager.Stub {
continue;
}
mCurrentLinkProperties[netType] = null;
- if (mNetConfigs[netType].isDefault()) mNetTrackers[netType].reconnect();
+ if (mNetTrackers[netType] != null && mNetConfigs[netType].isDefault()) {
+ mNetTrackers[netType].reconnect();
+ }
}
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) &&
@@ -525,7 +546,81 @@ public class ConnectivityService extends IConnectivityManager.Stub {
loadGlobalProxy();
}
+private NetworkStateTracker makeWimaxStateTracker() {
+ //Initialize Wimax
+ DexClassLoader wimaxClassLoader;
+ Class wimaxStateTrackerClass = null;
+ Class wimaxServiceClass = null;
+ Class wimaxManagerClass;
+ String wimaxJarLocation;
+ String wimaxLibLocation;
+ String wimaxManagerClassName;
+ String wimaxServiceClassName;
+ String wimaxStateTrackerClassName;
+
+ NetworkStateTracker wimaxStateTracker = null;
+
+ boolean isWimaxEnabled = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_wimaxEnabled);
+
+ if (isWimaxEnabled) {
+ try {
+ wimaxJarLocation = mContext.getResources().getString(
+ com.android.internal.R.string.config_wimaxServiceJarLocation);
+ wimaxLibLocation = mContext.getResources().getString(
+ com.android.internal.R.string.config_wimaxNativeLibLocation);
+ wimaxManagerClassName = mContext.getResources().getString(
+ com.android.internal.R.string.config_wimaxManagerClassname);
+ wimaxServiceClassName = mContext.getResources().getString(
+ com.android.internal.R.string.config_wimaxServiceClassname);
+ wimaxStateTrackerClassName = mContext.getResources().getString(
+ com.android.internal.R.string.config_wimaxStateTrackerClassname);
+
+ log("wimaxJarLocation: " + wimaxJarLocation);
+ wimaxClassLoader = new DexClassLoader(wimaxJarLocation,
+ new ContextWrapper(mContext).getCacheDir().getAbsolutePath(),
+ wimaxLibLocation, ClassLoader.getSystemClassLoader());
+
+ try {
+ wimaxManagerClass = wimaxClassLoader.loadClass(wimaxManagerClassName);
+ wimaxStateTrackerClass = wimaxClassLoader.loadClass(wimaxStateTrackerClassName);
+ wimaxServiceClass = wimaxClassLoader.loadClass(wimaxServiceClassName);
+ } catch (ClassNotFoundException ex) {
+ loge("Exception finding Wimax classes: " + ex.toString());
+ return null;
+ }
+ } catch(Resources.NotFoundException ex) {
+ loge("Wimax Resources does not exist!!! ");
+ return null;
+ }
+
+ try {
+ log("Starting Wimax Service... ");
+
+ Constructor wmxStTrkrConst = wimaxStateTrackerClass.getConstructor
+ (new Class[] {Context.class, Handler.class});
+ wimaxStateTracker = (NetworkStateTracker)wmxStTrkrConst.newInstance(mContext,
+ mHandler);
+
+ Constructor wmxSrvConst = wimaxServiceClass.getDeclaredConstructor
+ (new Class[] {Context.class, wimaxStateTrackerClass});
+ wmxSrvConst.setAccessible(true);
+ IBinder svcInvoker = (IBinder)wmxSrvConst.newInstance(mContext, wimaxStateTracker);
+ wmxSrvConst.setAccessible(false);
+
+ ServiceManager.addService(WimaxManagerConstants.WIMAX_SERVICE, svcInvoker);
+
+ } catch(Exception ex) {
+ loge("Exception creating Wimax classes: " + ex.toString());
+ return null;
+ }
+ } else {
+ loge("Wimax is not enabled or not added to the network attributes!!! ");
+ return null;
+ }
+ return wimaxStateTracker;
+ }
/**
* Sets the preferred network.
* @param preference the new preference
@@ -1146,23 +1241,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 +1272,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 +1295,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 +1315,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;
@@ -1486,6 +1597,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (checkType == prevNetType) continue;
if (mNetConfigs[checkType] == null) continue;
if (!mNetConfigs[checkType].isDefault()) continue;
+ if (mNetTrackers[checkType] == null) continue;
// Enabling the isAvailable() optimization caused mobile to not get
// selected if it was in the middle of error handling. Specifically
@@ -1862,14 +1974,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 +2569,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/DockObserver.java b/services/java/com/android/server/DockObserver.java
index dea9007..64789d3 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -82,7 +82,9 @@ class DockObserver extends UEventObserver {
// Don't force screen on when undocking from the desk dock.
// The change in power state will do this anyway.
// FIXME - we should be configurable.
- if (mPreviousDockState != Intent.EXTRA_DOCK_STATE_DESK ||
+ if ((mPreviousDockState != Intent.EXTRA_DOCK_STATE_DESK
+ && mPreviousDockState != Intent.EXTRA_DOCK_STATE_LE_DESK
+ && mPreviousDockState != Intent.EXTRA_DOCK_STATE_HE_DESK) ||
mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
mPowerManager.userActivityWithForce(SystemClock.uptimeMillis(),
false, true);
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 4e4fe4a..da960ae 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)}.
@@ -505,15 +512,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);
}
- private void modifyRoute(String interfaceName, int action, RouteInfo route) {
+ public void addSecondaryRoute(String interfaceName, RouteInfo route) {
+ mContext.enforceCallingOrSelfPermission(CHANGE_NETWORK_STATE, TAG);
+ modifyRoute(interfaceName, ADD, route, SECONDARY);
+ }
+
+ 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;
@@ -521,12 +538,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:
@@ -833,14 +850,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");
}
@@ -850,10 +886,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");
}
@@ -1099,12 +1136,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub
final StringBuilder command = new StringBuilder();
command.append("bandwidth removeiquota ").append(iface);
+ mActiveQuotaIfaces.remove(iface);
+ mActiveAlertIfaces.remove(iface);
+
try {
// TODO: support quota shared across interfaces
mConnector.doCommand(command.toString());
- mActiveQuotaIfaces.remove(iface);
- mActiveAlertIfaces.remove(iface);
} catch (NativeDaemonConnectorException e) {
+ // TODO: include current iptables state
throw new IllegalStateException("Error communicating to native daemon", e);
}
}
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index e97ee7a..5788a31 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -100,10 +100,13 @@ public class PowerManagerService extends IPowerManager.Stub
private static final int LONG_KEYLIGHT_DELAY = 6000; // t+6 sec
private static final int LONG_DIM_TIME = 7000; // t+N-5 sec
- // How long to wait to debounce light sensor changes.
+ // How long to wait to debounce light sensor changes in milliseconds
private static final int LIGHT_SENSOR_DELAY = 2000;
- // For debouncing the proximity sensor.
+ // light sensor events rate in microseconds
+ private static final int LIGHT_SENSOR_RATE = 1000000;
+
+ // For debouncing the proximity sensor in milliseconds
private static final int PROXIMITY_SENSOR_DELAY = 1000;
// trigger proximity if distance is less than 5 cm
@@ -3048,7 +3051,7 @@ public class PowerManagerService extends IPowerManager.Stub
handleLightSensorValue(value);
}
mSensorManager.registerListener(mLightListener, mLightSensor,
- SensorManager.SENSOR_DELAY_NORMAL);
+ LIGHT_SENSOR_RATE);
} else {
mSensorManager.unregisterListener(mLightListener);
mHandler.removeCallbacks(mAutoBrightnessTask);
diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java
index b042da6..af9152d 100644
--- a/services/java/com/android/server/TextServicesManagerService.java
+++ b/services/java/com/android/server/TextServicesManagerService.java
@@ -40,6 +40,8 @@ import android.provider.Settings;
import android.service.textservice.SpellCheckerService;
import android.text.TextUtils;
import android.util.Slog;
+import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
import android.view.textservice.SpellCheckerInfo;
import android.view.textservice.SpellCheckerSubtype;
@@ -222,20 +224,40 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
if (hashCode == 0 && !allowImplicitlySelectedSubtype) {
return null;
}
- final String systemLocale =
- mContext.getResources().getConfiguration().locale.toString();
+ String candidateLocale = null;
+ if (hashCode == 0) {
+ // Spell checker language settings == "auto"
+ final InputMethodManager imm =
+ (InputMethodManager)mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+ if (imm != null) {
+ final InputMethodSubtype currentInputMethodSubtype =
+ imm.getCurrentInputMethodSubtype();
+ if (currentInputMethodSubtype != null) {
+ final String localeString = currentInputMethodSubtype.getLocale();
+ if (!TextUtils.isEmpty(localeString)) {
+ // 1. Use keyboard locale if available in the spell checker
+ candidateLocale = localeString;
+ }
+ }
+ }
+ if (candidateLocale == null) {
+ // 2. Use System locale if available in the spell checker
+ candidateLocale = mContext.getResources().getConfiguration().locale.toString();
+ }
+ }
SpellCheckerSubtype candidate = null;
for (int i = 0; i < sci.getSubtypeCount(); ++i) {
final SpellCheckerSubtype scs = sci.getSubtypeAt(i);
if (hashCode == 0) {
- if (systemLocale.equals(locale)) {
+ if (candidateLocale.equals(locale)) {
return scs;
} else if (candidate == null) {
final String scsLocale = scs.getLocale();
- if (systemLocale.length() >= 2
+ if (candidateLocale.length() >= 2
&& scsLocale.length() >= 2
- && systemLocale.substring(0, 2).equals(
+ && candidateLocale.substring(0, 2).equals(
scsLocale.substring(0, 2))) {
+ // Fall back to the applicable language
candidate = scs;
}
}
@@ -244,9 +266,13 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
Slog.w(TAG, "Return subtype " + scs.hashCode() + ", input= " + locale
+ ", " + scs.getLocale());
}
+ // 3. Use the user specified spell check language
return scs;
}
}
+ // 4. Fall back to the applicable language and return it if not null
+ // 5. Simply just return it even if it's null which means we could find no suitable
+ // spell check languages
return candidate;
}
}
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index 431cc39..280b329 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -123,6 +123,10 @@ class UiModeManagerService extends IUiModeManager.Stub {
@Override
public void onReceive(Context context, Intent intent) {
if (getResultCode() != Activity.RESULT_OK) {
+ if (LOG) {
+ Slog.v(TAG, "Handling broadcast result for action " + intent.getAction()
+ + ": canceled: " + getResultCode());
+ }
return;
}
@@ -151,6 +155,12 @@ class UiModeManagerService extends IUiModeManager.Stub {
category = Intent.CATEGORY_HOME;
}
}
+
+ if (LOG) {
+ Slog.v(TAG, String.format(
+ "Handling broadcast result for action %s: enable=0x%08x disable=0x%08x category=%s",
+ intent.getAction(), enableFlags, disableFlags, category));
+ }
if (category != null) {
// This is the new activity that will serve as home while
@@ -424,11 +434,22 @@ class UiModeManagerService extends IUiModeManager.Stub {
}
}
+ final static boolean isDeskDockState(int state) {
+ switch (state) {
+ case Intent.EXTRA_DOCK_STATE_DESK:
+ case Intent.EXTRA_DOCK_STATE_LE_DESK:
+ case Intent.EXTRA_DOCK_STATE_HE_DESK:
+ return true;
+ default:
+ return false;
+ }
+ }
+
final void updateConfigurationLocked(boolean sendIt) {
int uiMode = Configuration.UI_MODE_TYPE_NORMAL;
if (mCarModeEnabled) {
uiMode = Configuration.UI_MODE_TYPE_CAR;
- } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
+ } else if (isDeskDockState(mDockState)) {
uiMode = Configuration.UI_MODE_TYPE_DESK;
}
if (mCarModeEnabled) {
@@ -477,7 +498,7 @@ class UiModeManagerService extends IUiModeManager.Stub {
if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_CAR) {
adjustStatusBarCarModeLocked();
oldAction = UiModeManager.ACTION_EXIT_CAR_MODE;
- } else if (mLastBroadcastState == Intent.EXTRA_DOCK_STATE_DESK) {
+ } else if (isDeskDockState(mLastBroadcastState)) {
oldAction = UiModeManager.ACTION_EXIT_DESK_MODE;
}
@@ -491,12 +512,12 @@ class UiModeManagerService extends IUiModeManager.Stub {
mLastBroadcastState = Intent.EXTRA_DOCK_STATE_CAR;
action = UiModeManager.ACTION_ENTER_CAR_MODE;
}
- } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
- if (mLastBroadcastState != Intent.EXTRA_DOCK_STATE_DESK) {
+ } else if (isDeskDockState(mDockState)) {
+ if (!isDeskDockState(mLastBroadcastState)) {
if (oldAction != null) {
mContext.sendBroadcast(new Intent(oldAction));
}
- mLastBroadcastState = Intent.EXTRA_DOCK_STATE_DESK;
+ mLastBroadcastState = mDockState;
action = UiModeManager.ACTION_ENTER_DESK_MODE;
}
} else {
@@ -505,6 +526,12 @@ class UiModeManagerService extends IUiModeManager.Stub {
}
if (action != null) {
+ if (LOG) {
+ Slog.v(TAG, String.format(
+ "updateLocked: preparing broadcast: action=%s enable=0x%08x disable=0x%08x",
+ action, enableFlags, disableFlags));
+ }
+
// Send the ordered broadcast; the result receiver will receive after all
// broadcasts have been sent. If any broadcast receiver changes the result
// code from the initial value of RESULT_OK, then the result receiver will
@@ -526,7 +553,7 @@ class UiModeManagerService extends IUiModeManager.Stub {
if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
homeIntent = buildHomeIntent(Intent.CATEGORY_CAR_DOCK);
}
- } else if (mDockState == Intent.EXTRA_DOCK_STATE_DESK) {
+ } else if (isDeskDockState(mDockState)) {
if ((enableFlags&UiModeManager.ENABLE_CAR_MODE_GO_CAR_HOME) != 0) {
homeIntent = buildHomeIntent(Intent.CATEGORY_DESK_DOCK);
}
@@ -535,6 +562,12 @@ class UiModeManagerService extends IUiModeManager.Stub {
homeIntent = buildHomeIntent(Intent.CATEGORY_HOME);
}
}
+
+ if (LOG) {
+ Slog.v(TAG, "updateLocked: null action, mDockState="
+ + mDockState +", firing homeIntent: " + homeIntent);
+ }
+
if (homeIntent != null) {
try {
mContext.startActivity(homeIntent);
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 5bfe6f8..3c65255 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -619,12 +619,7 @@ public class WifiService extends IWifiManager.Stub {
*/
public WifiConfiguration getWifiApConfiguration() {
enforceAccessPermission();
- if (mWifiStateMachineChannel != null) {
- return mWifiStateMachine.syncGetWifiApConfiguration(mWifiStateMachineChannel);
- } else {
- Slog.e(TAG, "mWifiStateMachineChannel is not initialized");
- return null;
- }
+ return mWifiStateMachine.syncGetWifiApConfiguration();
}
/**
@@ -921,18 +916,14 @@ public class WifiService extends IWifiManager.Stub {
Slog.d(TAG, "ACTION_SCREEN_ON");
}
mAlarmManager.cancel(mIdleIntent);
- mDeviceIdle = false;
mScreenOff = false;
- // Once the screen is on, we are not keeping WIFI running
- // because of any locks so clear that tracking immediately.
- reportStartWorkSource();
evaluateTrafficStatsPolling();
mWifiStateMachine.enableRssiPolling(true);
if (mBackgroundScanSupported) {
mWifiStateMachine.enableBackgroundScanCommand(false);
}
mWifiStateMachine.enableAllNetworks();
- updateWifiState();
+ setDeviceIdleAndUpdateWifi(false);
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
if (DBG) {
Slog.d(TAG, "ACTION_SCREEN_OFF");
@@ -950,36 +941,17 @@ public class WifiService extends IWifiManager.Stub {
* or plugged in to AC).
*/
if (!shouldWifiStayAwake(stayAwakeConditions, mPluggedType)) {
- WifiInfo info = mWifiStateMachine.syncRequestConnectionInfo();
- if (info.getSupplicantState() != SupplicantState.COMPLETED) {
- // we used to go to sleep immediately, but this caused some race conditions
- // we don't have time to track down for this release. Delay instead,
- // but not as long as we would if connected (below)
- // TODO - fix the race conditions and switch back to the immediate turn-off
- long triggerTime = System.currentTimeMillis() + (2*60*1000); // 2 min
- if (DBG) {
- Slog.d(TAG, "setting ACTION_DEVICE_IDLE timer for 120,000 ms");
- }
- mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
- // // do not keep Wifi awake when screen is off if Wifi is not associated
- // mDeviceIdle = true;
- // updateWifiState();
+ //Delayed shutdown if wifi is connected
+ if (mNetworkInfo.getDetailedState() == DetailedState.CONNECTED) {
+ if (DBG) Slog.d(TAG, "setting ACTION_DEVICE_IDLE: " + idleMillis + " ms");
+ mAlarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
+ + idleMillis, mIdleIntent);
} else {
- long triggerTime = System.currentTimeMillis() + idleMillis;
- if (DBG) {
- Slog.d(TAG, "setting ACTION_DEVICE_IDLE timer for " + idleMillis
- + "ms");
- }
- mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
+ setDeviceIdleAndUpdateWifi(true);
}
}
} else if (action.equals(ACTION_DEVICE_IDLE)) {
- if (DBG) {
- Slog.d(TAG, "got ACTION_DEVICE_IDLE");
- }
- mDeviceIdle = true;
- reportStartWorkSource();
- updateWifiState();
+ setDeviceIdleAndUpdateWifi(true);
} else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
/*
* Set a timer to put Wi-Fi to sleep, but only if the screen is off
@@ -1056,6 +1028,12 @@ public class WifiService extends IWifiManager.Stub {
}
};
+ private void setDeviceIdleAndUpdateWifi(boolean deviceIdle) {
+ mDeviceIdle = deviceIdle;
+ reportStartWorkSource();
+ updateWifiState();
+ }
+
private synchronized void reportStartWorkSource() {
mTmpWorkSource.clear();
if (mDeviceIdle) {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 0c42926..cd63090 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;
@@ -857,9 +860,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() {
@@ -1199,6 +1204,71 @@ 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() {
+ StringBuilder dropBuilder = new StringBuilder(1024);
+ StringBuilder logBuilder = new StringBuilder(1024);
+ 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) {
+ logBuilder.append(line);
+ logBuilder.append('\n');
+ }
+ dropBuilder.append(line);
+ dropBuilder.append('\n');
+ }
+ converter.close();
+ } catch (IOException e) {
+ }
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ StringWriter catSw = new StringWriter();
+ PrintWriter catPw = new PrintWriter(catSw);
+ dumpApplicationMemoryUsage(null, pw, " ", new String[] { }, true, catPw);
+ String memUsage = sw.toString();
+ dropBuilder.append('\n');
+ dropBuilder.append(memUsage);
+ dropBuilder.append(catSw.toString());
+ logBuilder.append(memUsage);
+ addErrorToDropBox("watchdog", null, "system_server", null,
+ null, "Low on memory -- no more background processes",
+ dropBuilder.toString(), null, null);
+ Slog.i(TAG, logBuilder.toString());
+ synchronized (ActivityManagerService.this) {
+ long now = SystemClock.uptimeMillis();
+ if (mLastMemUsageReportTime < now) {
+ mLastMemUsageReportTime = now;
+ }
+ }
+ }
+ };
+ thread.start();
+ break;
+ }
}
}
};
@@ -1339,7 +1409,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
- mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args);
+ mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null);
}
}
@@ -1599,7 +1669,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final void setFocusedActivityLocked(ActivityRecord r) {
if (mFocusedActivity != r) {
mFocusedActivity = r;
- mWindowManager.setFocusedApp(r, true);
+ mWindowManager.setFocusedApp(r.appToken, true);
}
}
@@ -2276,7 +2346,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// XXX we are not dealing with propagating grantedUriPermissions...
// those are not yet exposed to user code, so there is no need.
int res = mMainStack.startActivityLocked(r.app.thread, intent,
- r.resolvedType, null, 0, aInfo, resultTo, resultWho,
+ r.resolvedType, null, 0, aInfo,
+ resultTo != null ? resultTo.appToken : null, resultWho,
requestCode, -1, r.launchedFromUid, false, false, null);
Binder.restoreCallingIdentity(origId);
@@ -2359,10 +2430,10 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
final long origId = Binder.clearCallingIdentity();
- mWindowManager.setAppOrientation(r, requestedOrientation);
+ mWindowManager.setAppOrientation(r.appToken, requestedOrientation);
Configuration config = mWindowManager.updateOrientationFromAppTokens(
mConfiguration,
- r.mayFreezeScreenLocked(r.app) ? r : null);
+ r.mayFreezeScreenLocked(r.app) ? r.appToken : null);
if (config != null) {
r.frozenBeforeDestroy = true;
if (!updateConfigurationLocked(config, r, false)) {
@@ -2379,7 +2450,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (r == null) {
return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
}
- return mWindowManager.getAppOrientation(r);
+ return mWindowManager.getAppOrientation(r.appToken);
}
}
@@ -2445,7 +2516,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int i=0; i<activities.size(); i++) {
ActivityRecord r = activities.get(i);
if (!r.finishing) {
- int index = mMainStack.indexOfTokenLocked(r);
+ int index = mMainStack.indexOfTokenLocked(r.appToken);
if (index >= 0) {
mMainStack.finishActivityLocked(r, index, Activity.RESULT_CANCELED,
null, "finish-heavy");
@@ -2547,7 +2618,7 @@ public final class ActivityManagerService extends ActivityManagerNative
int i;
for (i=mMainStack.mHistory.size()-1; i>=0; i--) {
ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
- if (r == token) {
+ if (r.appToken == token) {
return true;
}
if (r.fullscreen && !r.finishing) {
@@ -2635,9 +2706,9 @@ public final class ActivityManagerService extends ActivityManagerNative
r.makeFinishing();
mMainStack.mHistory.remove(i);
r.takeFromHistory();
- mWindowManager.removeAppToken(r);
+ mWindowManager.removeAppToken(r.appToken);
if (VALIDATE_TOKENS) {
- mWindowManager.validateAppTokens(mMainStack.mHistory);
+ mMainStack.validateAppTokensLocked();
}
r.removeUriPermissionsLocked();
@@ -2768,6 +2839,7 @@ public final class ActivityManagerService extends ActivityManagerNative
addProcessToGcListLocked(rec);
}
}
+ mHandler.sendEmptyMessage(REPORT_MEM_USAGE);
scheduleAppGcsLocked();
}
}
@@ -3136,7 +3208,49 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
killPackageProcessesLocked(packageName, pkgUid,
- ProcessList.SERVICE_ADJ, false, true, true, false);
+ ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
+
+ public void killAllBackgroundProcesses() {
+ if (checkCallingPermission(android.Manifest.permission.KILL_BACKGROUND_PROCESSES)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: killAllBackgroundProcesses() from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " requires " + android.Manifest.permission.KILL_BACKGROUND_PROCESSES;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+
+ long callingId = Binder.clearCallingIdentity();
+ try {
+ synchronized(this) {
+ ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
+ for (SparseArray<ProcessRecord> apps : mProcessNames.getMap().values()) {
+ final int NA = apps.size();
+ for (int ia=0; ia<NA; ia++) {
+ ProcessRecord app = apps.valueAt(ia);
+ if (app.persistent) {
+ // we don't kill persistent processes
+ continue;
+ }
+ if (app.removed) {
+ procs.add(app);
+ } else if (app.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
+ app.removed = true;
+ procs.add(app);
+ }
+ }
+ }
+
+ int N = procs.size();
+ for (int i=0; i<N; i++) {
+ removeProcessLocked(procs.get(i), false, true, "kill all background");
+ }
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -3308,7 +3422,7 @@ public final class ActivityManagerService extends ActivityManagerNative
private final boolean killPackageProcessesLocked(String packageName, int uid,
int minOomAdj, boolean callerWillRestart, boolean allowRestart, boolean doit,
- boolean evenPersistent) {
+ boolean evenPersistent, String reason) {
ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>();
// Remove all processes this package may have touched: all with the
@@ -3343,7 +3457,7 @@ public final class ActivityManagerService extends ActivityManagerNative
int N = procs.size();
for (int i=0; i<N; i++) {
- removeProcessLocked(procs.get(i), callerWillRestart, allowRestart);
+ removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason);
}
return N > 0;
}
@@ -3374,7 +3488,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
boolean didSomething = killPackageProcessesLocked(name, uid, -100,
- callerWillRestart, false, doit, evenPersistent);
+ callerWillRestart, false, doit, evenPersistent, "force stop");
TaskRecord lastTask = null;
for (i=0; i<mMainStack.mHistory.size(); i++) {
@@ -3462,11 +3576,11 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private final boolean removeProcessLocked(ProcessRecord app,
- boolean callerWillRestart, boolean allowRestart) {
+ boolean callerWillRestart, boolean allowRestart, String reason) {
final String name = app.processName;
final int uid = app.info.uid;
if (DEBUG_PROCESSES) Slog.d(
- TAG, "Force removing process " + app + " (" + name
+ TAG, "Force removing proc " + app.toShortString() + " (" + name
+ "/" + uid + ")");
mProcessNames.remove(name, uid);
@@ -3481,9 +3595,10 @@ public final class ActivityManagerService extends ActivityManagerNative
mPidsSelfLocked.remove(pid);
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
}
+ Slog.i(TAG, "Killing proc " + app.toShortString() + ": " + reason);
handleAppDiedLocked(app, true, allowRestart);
mLruProcesses.remove(app);
- Process.killProcess(pid);
+ Process.killProcessQuiet(pid);
if (app.persistent) {
if (!callerWillRestart) {
@@ -5059,10 +5174,10 @@ public final class ActivityManagerService extends ActivityManagerNative
if (topThumbnail != null) {
if (localLOGV) Slog.v(TAG, "Requesting top thumbnail");
try {
- topThumbnail.requestThumbnail(topRecord);
+ topThumbnail.requestThumbnail(topRecord.appToken);
} catch (Exception e) {
Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
- sendPendingThumbnail(null, topRecord, null, null, true);
+ sendPendingThumbnail(null, topRecord.appToken, null, null, true);
}
}
@@ -5433,7 +5548,7 @@ public final class ActivityManagerService extends ActivityManagerNative
TaskRecord lastTask = null;
for (int i=0; i<N; i++) {
ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
- if (r == token) {
+ if (r.appToken == token) {
if (!onlyRoot || lastTask != r.task) {
return r.task.taskId;
}
@@ -5454,7 +5569,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int i=0; i<N; i++) {
ActivityRecord r = (ActivityRecord)mMainStack.mHistory.get(i);
if (r.realActivity.equals(className)
- && r != token && lastTask != r.task) {
+ && r.appToken != token && lastTask != r.task) {
if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
null, "others")) {
i--;
@@ -6790,7 +6905,7 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int i=procsToKill.size()-1; i>=0; i--) {
ProcessRecord proc = procsToKill.get(i);
Slog.i(TAG, "Removing system update proc: " + proc);
- removeProcessLocked(proc, true, false);
+ removeProcessLocked(proc, true, false, "system update done");
}
}
@@ -6986,7 +7101,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// Don't let services in this process be restarted and potentially
// annoy the user repeatedly. Unless it is persistent, since those
// processes run critical code.
- removeProcessLocked(app, false, false);
+ removeProcessLocked(app, false, false, "crash");
mMainStack.resumeTopActivityLocked(null);
return false;
}
@@ -6998,7 +7113,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// process, then terminate it to avoid getting in a loop.
Slog.w(TAG, " Force finishing activity "
+ r.intent.getComponent().flattenToShortString());
- int index = mMainStack.indexOfTokenLocked(r);
+ int index = mMainStack.indexOfActivityLocked(r);
r.stack.finishActivityLocked(r, index,
Activity.RESULT_CANCELED, null, "crashed");
// Also terminate any activities below it that aren't yet
@@ -8517,8 +8632,8 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
TransferPipe tp = new TransferPipe();
try {
- r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
- innerPrefix, args);
+ r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
+ r.appToken, innerPrefix, args);
tp.go(fd);
} finally {
tp.kill();
@@ -8934,8 +9049,8 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
TransferPipe tp = new TransferPipe();
try {
- r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), r,
- innerPrefix, args);
+ r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
+ r.appToken, innerPrefix, args);
// Short timeout, since blocking here can
// deadlock with the application.
tp.go(fd, 2000);
@@ -9242,8 +9357,10 @@ 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,
+ PrintWriter categoryPw) {
boolean dumpAll = false;
+ boolean oomOnly = false;
int opti = 0;
while (opti < args.length) {
@@ -9254,9 +9371,12 @@ public final class ActivityManagerService extends ActivityManagerNative
opti++;
if ("-a".equals(opt)) {
dumpAll = true;
+ } else if ("--oom".equals(opt)) {
+ oomOnly = true;
} else if ("-h".equals(opt)) {
- pw.println("meminfo dump options: [-a] [process]");
+ pw.println("meminfo dump options: [-a] [--oom] [process]");
pw.println(" -a: include all available information for each process.");
+ pw.println(" --oom: only show processes organized by oom adj.");
pw.println("If [process] is specified it can be the name or ");
pw.println("pid of a specific process to dump.");
return;
@@ -9382,15 +9502,20 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- pw.println();
- pw.println("Total PSS by process:");
- dumpMemItems(pw, " ", procMems, true);
- pw.println();
+ if (!brief && !oomOnly) {
+ 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 (!oomOnly) {
+ PrintWriter out = categoryPw != null ? categoryPw : pw;
+ out.println();
+ out.println("Total PSS by category:");
+ dumpMemItems(out, " ", catMems, true);
+ }
pw.println();
pw.print("Total PSS: "); pw.print(totalPss); pw.println(" Kb");
}
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 00e6cb2..951a946 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -29,6 +29,7 @@ import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.os.Build;
import android.os.Bundle;
+import android.os.IBinder;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
@@ -48,9 +49,10 @@ import java.util.HashSet;
/**
* An entry in the history stack, representing an activity.
*/
-final class ActivityRecord extends IApplicationToken.Stub {
+final class ActivityRecord {
final ActivityManagerService service; // owner
final ActivityStack stack; // owner
+ final IApplicationToken.Stub appToken; // window manager token
final ActivityInfo info; // all about me
final int launchedFromUid; // always the uid who started the activity.
final Intent intent; // the original intent that generated us
@@ -200,6 +202,70 @@ final class ActivityRecord extends IApplicationToken.Stub {
}
}
+ static class Token extends IApplicationToken.Stub {
+ final WeakReference<ActivityRecord> weakActivity;
+
+ Token(ActivityRecord activity) {
+ weakActivity = new WeakReference<ActivityRecord>(activity);
+ }
+
+ @Override public void windowsDrawn() throws RemoteException {
+ ActivityRecord activity = weakActivity.get();
+ if (activity != null) {
+ activity.windowsDrawn();
+ }
+ }
+
+ @Override public void windowsVisible() throws RemoteException {
+ ActivityRecord activity = weakActivity.get();
+ if (activity != null) {
+ activity.windowsVisible();
+ }
+ }
+
+ @Override public void windowsGone() throws RemoteException {
+ ActivityRecord activity = weakActivity.get();
+ if (activity != null) {
+ activity.windowsGone();
+ }
+ }
+
+ @Override public boolean keyDispatchingTimedOut() throws RemoteException {
+ ActivityRecord activity = weakActivity.get();
+ if (activity != null) {
+ return activity.keyDispatchingTimedOut();
+ }
+ return false;
+ }
+
+ @Override public long getKeyDispatchingTimeout() throws RemoteException {
+ ActivityRecord activity = weakActivity.get();
+ if (activity != null) {
+ return activity.getKeyDispatchingTimeout();
+ }
+ return 0;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("Token{");
+ sb.append(Integer.toHexString(System.identityHashCode(this)));
+ sb.append(' ');
+ sb.append(weakActivity.get());
+ sb.append('}');
+ return sb.toString();
+ }
+ }
+
+ static ActivityRecord forToken(IBinder token) {
+ try {
+ return token != null ? ((Token)token).weakActivity.get() : null;
+ } catch (ClassCastException e) {
+ Slog.w(ActivityManagerService.TAG, "Bad activity token: " + token, e);
+ return null;
+ }
+ }
+
ActivityRecord(ActivityManagerService _service, ActivityStack _stack, ProcessRecord _caller,
int _launchedFromUid, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration,
@@ -207,6 +273,7 @@ final class ActivityRecord extends IApplicationToken.Stub {
boolean _componentSpecified) {
service = _service;
stack = _stack;
+ appToken = new Token(this);
info = aInfo;
launchedFromUid = _launchedFromUid;
intent = _intent;
@@ -445,7 +512,7 @@ final class ActivityRecord extends IApplicationToken.Stub {
ar.add(intent);
service.grantUriPermissionFromIntentLocked(callingUid, packageName,
intent, getUriPermissionsLocked());
- app.thread.scheduleNewIntent(ar, this);
+ app.thread.scheduleNewIntent(ar, appToken);
sent = true;
} catch (RemoteException e) {
Slog.w(ActivityManagerService.TAG,
@@ -470,14 +537,14 @@ final class ActivityRecord extends IApplicationToken.Stub {
void pauseKeyDispatchingLocked() {
if (!keysPaused) {
keysPaused = true;
- service.mWindowManager.pauseKeyDispatching(this);
+ service.mWindowManager.pauseKeyDispatching(appToken);
}
}
void resumeKeyDispatchingLocked() {
if (keysPaused) {
keysPaused = false;
- service.mWindowManager.resumeKeyDispatching(this);
+ service.mWindowManager.resumeKeyDispatching(appToken);
}
}
@@ -512,14 +579,14 @@ final class ActivityRecord extends IApplicationToken.Stub {
public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
if (mayFreezeScreenLocked(app)) {
- service.mWindowManager.startAppFreezingScreen(this, configChanges);
+ service.mWindowManager.startAppFreezingScreen(appToken, configChanges);
}
}
public void stopFreezingScreenLocked(boolean force) {
if (force || frozenBeforeDestroy) {
frozenBeforeDestroy = false;
- service.mWindowManager.stopAppFreezingScreen(this, force);
+ service.mWindowManager.stopAppFreezingScreen(appToken, force);
}
}
@@ -687,7 +754,7 @@ final class ActivityRecord extends IApplicationToken.Stub {
}
if (app != null && app.thread != null) {
try {
- app.thread.scheduleSleeping(this, _sleeping);
+ app.thread.scheduleSleeping(appToken, _sleeping);
if (sleeping && !stack.mGoingToSleepActivities.contains(this)) {
stack.mGoingToSleepActivities.add(this);
}
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 8435eaa..c892cb1 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -145,7 +145,12 @@ final class ActivityStack {
* running) activities. It contains HistoryRecord objects.
*/
final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();
-
+
+ /**
+ * Used for validating app tokens with window manager.
+ */
+ final ArrayList<IBinder> mValidateAppTokens = new ArrayList<IBinder>();
+
/**
* List of running activities, sorted by recent usage.
* The first entry in the list is the least recently used.
@@ -294,11 +299,11 @@ final class ActivityStack {
}
} break;
case PAUSE_TIMEOUT_MSG: {
- IBinder token = (IBinder)msg.obj;
+ ActivityRecord r = (ActivityRecord)msg.obj;
// We don't at this point know if the activity is fullscreen,
// so we need to be conservative and assume it isn't.
- Slog.w(TAG, "Activity pause timeout for " + token);
- activityPaused(token, true);
+ Slog.w(TAG, "Activity pause timeout for " + r);
+ activityPaused(r != null ? r.appToken : null, true);
} break;
case IDLE_TIMEOUT_MSG: {
if (mService.mDidDexOpt) {
@@ -310,20 +315,20 @@ final class ActivityStack {
}
// We don't at this point know if the activity is fullscreen,
// so we need to be conservative and assume it isn't.
- IBinder token = (IBinder)msg.obj;
- Slog.w(TAG, "Activity idle timeout for " + token);
- activityIdleInternal(token, true, null);
+ ActivityRecord r = (ActivityRecord)msg.obj;
+ Slog.w(TAG, "Activity idle timeout for " + r);
+ activityIdleInternal(r != null ? r.appToken : null, true, null);
} break;
case DESTROY_TIMEOUT_MSG: {
- IBinder token = (IBinder)msg.obj;
+ ActivityRecord r = (ActivityRecord)msg.obj;
// We don't at this point know if the activity is fullscreen,
// so we need to be conservative and assume it isn't.
- Slog.w(TAG, "Activity destroy timeout for " + token);
- activityDestroyed(token);
+ Slog.w(TAG, "Activity destroy timeout for " + r);
+ activityDestroyed(r != null ? r.appToken : null);
} break;
case IDLE_NOW_MSG: {
- IBinder token = (IBinder)msg.obj;
- activityIdleInternal(token, false, null);
+ ActivityRecord r = (ActivityRecord)msg.obj;
+ activityIdleInternal(r != null ? r.appToken : null, false, null);
} break;
case LAUNCH_TIMEOUT_MSG: {
if (mService.mDidDexOpt) {
@@ -397,7 +402,7 @@ final class ActivityStack {
while (i >= 0) {
ActivityRecord r = mHistory.get(i);
// Note: the taskId check depends on real taskId fields being non-zero
- if (!r.finishing && (token != r) && (taskId != r.task.taskId)) {
+ if (!r.finishing && (token != r.appToken) && (taskId != r.task.taskId)) {
return r;
}
i--;
@@ -406,23 +411,17 @@ final class ActivityStack {
}
final int indexOfTokenLocked(IBinder token) {
- try {
- ActivityRecord r = (ActivityRecord)token;
- return mHistory.indexOf(r);
- } catch (ClassCastException e) {
- Slog.w(TAG, "Bad activity token: " + token, e);
- return -1;
- }
+ return mHistory.indexOf(ActivityRecord.forToken(token));
+ }
+
+ final int indexOfActivityLocked(ActivityRecord r) {
+ return mHistory.indexOf(r);
}
final ActivityRecord isInStackLocked(IBinder token) {
- try {
- ActivityRecord r = (ActivityRecord)token;
- if (mHistory.contains(r)) {
- return r;
- }
- } catch (ClassCastException e) {
- Slog.w(TAG, "Bad activity token: " + token, e);
+ ActivityRecord r = ActivityRecord.forToken(token);
+ if (mHistory.contains(r)) {
+ return r;
}
return null;
}
@@ -517,7 +516,7 @@ final class ActivityStack {
throws RemoteException {
r.startFreezingScreenLocked(app, 0);
- mService.mWindowManager.setAppVisibility(r, true);
+ mService.mWindowManager.setAppVisibility(r.appToken, true);
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order. Note that
@@ -528,7 +527,7 @@ final class ActivityStack {
if (checkConfig) {
Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
- r.mayFreezeScreenLocked(app) ? r : null);
+ r.mayFreezeScreenLocked(app) ? r.appToken : null);
mService.updateConfigurationLocked(config, r, false);
}
@@ -590,7 +589,7 @@ final class ActivityStack {
profileFd = null;
}
}
- app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
+ app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, mService.mConfiguration,
r.compat, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
@@ -624,7 +623,7 @@ final class ActivityStack {
+ r.intent.getComponent().flattenToShortString()
+ ", giving up", e);
mService.appDiedLocked(app, app.pid, app.thread);
- requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
+ requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
"2nd-crash");
return false;
}
@@ -821,7 +820,7 @@ final class ActivityStack {
}
if (w > 0) {
- return mService.mWindowManager.screenshotApplications(who, w, h);
+ return mService.mWindowManager.screenshotApplications(who.appToken, w, h);
}
return null;
}
@@ -856,8 +855,8 @@ final class ActivityStack {
EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
System.identityHashCode(prev),
prev.shortComponentName);
- prev.app.thread.schedulePauseActivity(prev, prev.finishing, userLeaving,
- prev.configChangeFlags);
+ prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
+ userLeaving, prev.configChangeFlags);
if (mMainStack) {
mService.updateUsageStats(prev, false);
}
@@ -1129,7 +1128,7 @@ final class ActivityStack {
if (!r.visible) {
if (DEBUG_VISBILITY) Slog.v(
TAG, "Starting and making visible: " + r);
- mService.mWindowManager.setAppVisibility(r, true);
+ mService.mWindowManager.setAppVisibility(r.appToken, true);
}
if (r != starting) {
startSpecificActivityLocked(r, false, false);
@@ -1153,10 +1152,10 @@ final class ActivityStack {
if (DEBUG_VISBILITY) Slog.v(
TAG, "Making visible and scheduling visibility: " + r);
try {
- mService.mWindowManager.setAppVisibility(r, true);
+ mService.mWindowManager.setAppVisibility(r.appToken, true);
r.sleeping = false;
r.app.pendingUiClean = true;
- r.app.thread.scheduleWindowVisibility(r, true);
+ r.app.thread.scheduleWindowVisibility(r.appToken, true);
r.stopFreezingScreenLocked(false);
} catch (Exception e) {
// Just skip on any failure; we'll make it
@@ -1195,13 +1194,13 @@ final class ActivityStack {
TAG, "Making invisible: " + r);
r.visible = false;
try {
- mService.mWindowManager.setAppVisibility(r, false);
+ mService.mWindowManager.setAppVisibility(r.appToken, false);
if ((r.state == ActivityState.STOPPING
|| r.state == ActivityState.STOPPED)
&& r.app != null && r.app.thread != null) {
if (DEBUG_VISBILITY) Slog.v(
TAG, "Scheduling invisibility: " + r);
- r.app.thread.scheduleWindowVisibility(r, false);
+ r.app.thread.scheduleWindowVisibility(r.appToken, false);
}
} catch (Exception e) {
// Just skip on any failure; we'll make it
@@ -1351,7 +1350,7 @@ final class ActivityStack {
// previous should actually be hidden depending on whether the
// new one is found to be full-screen or not.
if (prev.finishing) {
- mService.mWindowManager.setAppVisibility(prev, false);
+ mService.mWindowManager.setAppVisibility(prev.appToken, false);
if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
+ prev + ", waitingVisible="
+ (prev != null ? prev.waitingVisible : null)
@@ -1399,8 +1398,8 @@ final class ActivityStack {
? WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE
: WindowManagerPolicy.TRANSIT_TASK_CLOSE, false);
}
- mService.mWindowManager.setAppWillBeHidden(prev);
- mService.mWindowManager.setAppVisibility(prev, false);
+ mService.mWindowManager.setAppWillBeHidden(prev.appToken);
+ mService.mWindowManager.setAppVisibility(prev.appToken, false);
} else {
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare open transition: prev=" + prev);
@@ -1414,8 +1413,8 @@ final class ActivityStack {
}
}
if (false) {
- mService.mWindowManager.setAppWillBeHidden(prev);
- mService.mWindowManager.setAppVisibility(prev, false);
+ mService.mWindowManager.setAppWillBeHidden(prev.appToken);
+ mService.mWindowManager.setAppVisibility(prev.appToken, false);
}
} else if (mHistory.size() > 1) {
if (DEBUG_TRANSITION) Slog.v(TAG,
@@ -1433,7 +1432,7 @@ final class ActivityStack {
if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
// This activity is now becoming visible.
- mService.mWindowManager.setAppVisibility(next, true);
+ mService.mWindowManager.setAppVisibility(next.appToken, true);
ActivityRecord lastResumedActivity = mResumedActivity;
ActivityState lastState = next.state;
@@ -1457,7 +1456,7 @@ final class ActivityStack {
synchronized (mService) {
Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
- next.mayFreezeScreenLocked(next.app) ? next : null);
+ next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
if (config != null) {
next.frozenBeforeDestroy = true;
}
@@ -1496,12 +1495,12 @@ final class ActivityStack {
if (DEBUG_RESULTS) Slog.v(
TAG, "Delivering results to " + next
+ ": " + a);
- next.app.thread.scheduleSendResult(next, a);
+ next.app.thread.scheduleSendResult(next.appToken, a);
}
}
if (next.newIntents != null) {
- next.app.thread.scheduleNewIntent(next.newIntents, next);
+ next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
}
EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
@@ -1511,7 +1510,7 @@ final class ActivityStack {
next.sleeping = false;
showAskCompatModeDialogLocked(next);
next.app.pendingUiClean = true;
- next.app.thread.scheduleResumeActivity(next,
+ next.app.thread.scheduleResumeActivity(next.appToken,
mService.isNextTransitionForward());
checkReadyForSleepLocked();
@@ -1528,7 +1527,7 @@ final class ActivityStack {
} else {
if (SHOW_APP_STARTING_PREVIEW && mMainStack) {
mService.mWindowManager.setAppStartingWindow(
- next, next.packageName, next.theme,
+ next.appToken, next.packageName, next.theme,
mService.compatibilityInfoForPackageLocked(
next.info.applicationInfo),
next.nonLocalizedLabel,
@@ -1549,7 +1548,7 @@ final class ActivityStack {
// If any exception gets thrown, toss away this
// activity and try the next one.
Slog.w(TAG, "Exception thrown during resume of " + next, e);
- requestFinishActivityLocked(next, Activity.RESULT_CANCELED, null,
+ requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
"resume-exception");
return true;
}
@@ -1567,7 +1566,7 @@ final class ActivityStack {
} else {
if (SHOW_APP_STARTING_PREVIEW) {
mService.mWindowManager.setAppStartingWindow(
- next, next.packageName, next.theme,
+ next.appToken, next.packageName, next.theme,
mService.compatibilityInfoForPackageLocked(
next.info.applicationInfo),
next.nonLocalizedLabel,
@@ -1610,10 +1609,10 @@ final class ActivityStack {
}
mHistory.add(addPos, r);
r.putInHistory();
- mService.mWindowManager.addAppToken(addPos, r, r.task.taskId,
+ mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
r.info.screenOrientation, r.fullscreen);
if (VALIDATE_TOKENS) {
- mService.mWindowManager.validateAppTokens(mHistory);
+ validateAppTokensLocked();
}
return;
}
@@ -1677,7 +1676,7 @@ final class ActivityStack {
mNoAnimActivities.remove(r);
}
mService.mWindowManager.addAppToken(
- addPos, r, r.task.taskId, r.info.screenOrientation, r.fullscreen);
+ addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen);
boolean doShow = true;
if (newTask) {
// Even though this activity is starting fresh, we still need
@@ -1705,19 +1704,20 @@ final class ActivityStack {
else if (prev.nowVisible) prev = null;
}
mService.mWindowManager.setAppStartingWindow(
- r, r.packageName, r.theme,
+ r.appToken, r.packageName, r.theme,
mService.compatibilityInfoForPackageLocked(
r.info.applicationInfo), r.nonLocalizedLabel,
- r.labelRes, r.icon, r.windowFlags, prev, showStartingIcon);
+ r.labelRes, r.icon, r.windowFlags,
+ prev != null ? prev.appToken : null, showStartingIcon);
}
} else {
// If this is the first activity, don't do any fancy animations,
// because there is nothing for it to animate on top of.
- mService.mWindowManager.addAppToken(addPos, r, r.task.taskId,
+ mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
r.info.screenOrientation, r.fullscreen);
}
if (VALIDATE_TOKENS) {
- mService.mWindowManager.validateAppTokens(mHistory);
+ validateAppTokensLocked();
}
if (doResume) {
@@ -1725,6 +1725,15 @@ final class ActivityStack {
}
}
+ final void validateAppTokensLocked() {
+ mValidateAppTokens.clear();
+ mValidateAppTokens.ensureCapacity(mHistory.size());
+ for (int i=0; i<mHistory.size(); i++) {
+ mValidateAppTokens.add(mHistory.get(i).appToken);
+ }
+ mService.mWindowManager.validateAppTokens(mValidateAppTokens);
+ }
+
/**
* Perform a reset of the given task, if needed as part of launching it.
* Returns the new HistoryRecord at the top of the task.
@@ -1826,7 +1835,7 @@ final class ActivityStack {
if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
+ " out to new task " + target.task);
}
- mService.mWindowManager.setAppGroupId(target, task.taskId);
+ mService.mWindowManager.setAppGroupId(target.appToken, task.taskId);
if (replyChainEnd < 0) {
replyChainEnd = targetI;
}
@@ -1849,11 +1858,11 @@ final class ActivityStack {
}
mHistory.remove(srcPos);
mHistory.add(dstPos, p);
- mService.mWindowManager.moveAppToken(dstPos, p);
- mService.mWindowManager.setAppGroupId(p, p.task.taskId);
+ mService.mWindowManager.moveAppToken(dstPos, p.appToken);
+ mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
dstPos++;
if (VALIDATE_TOKENS) {
- mService.mWindowManager.validateAppTokens(mHistory);
+ validateAppTokensLocked();
}
i++;
}
@@ -1985,10 +1994,10 @@ final class ActivityStack {
mHistory.add(lastReparentPos, p);
if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
+ " in to resetting task " + task);
- mService.mWindowManager.moveAppToken(lastReparentPos, p);
- mService.mWindowManager.setAppGroupId(p, p.task.taskId);
+ mService.mWindowManager.moveAppToken(lastReparentPos, p.appToken);
+ mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
if (VALIDATE_TOKENS) {
- mService.mWindowManager.validateAppTokens(mHistory);
+ validateAppTokensLocked();
}
}
replyChainEnd = -1;
@@ -2081,7 +2090,7 @@ final class ActivityStack {
if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
&& (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
if (!ret.finishing) {
- int index = indexOfTokenLocked(ret);
+ int index = indexOfTokenLocked(ret.appToken);
if (index >= 0) {
finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
null, "clear");
@@ -3007,7 +3016,7 @@ final class ActivityStack {
return res;
}
- resultTo = outActivity[0];
+ resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
}
}
} finally {
@@ -3065,7 +3074,7 @@ final class ActivityStack {
ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
list.add(new ResultInfo(resultWho, requestCode,
resultCode, data));
- r.app.thread.scheduleSendResult(r, list);
+ r.app.thread.scheduleSendResult(r.appToken, list);
return;
} catch (Exception e) {
Slog.w(TAG, "Exception thrown sending result to " + r, e);
@@ -3080,7 +3089,7 @@ final class ActivityStack {
if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
|| (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
if (!r.finishing) {
- requestFinishActivityLocked(r, Activity.RESULT_CANCELED, null,
+ requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
"no-history");
}
} else if (r.app != null && r.app.thread != null) {
@@ -3098,9 +3107,9 @@ final class ActivityStack {
if (DEBUG_VISBILITY) Slog.v(
TAG, "Stopping visible=" + r.visible + " for " + r);
if (!r.visible) {
- mService.mWindowManager.setAppVisibility(r, false);
+ mService.mWindowManager.setAppVisibility(r.appToken, false);
}
- r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
+ r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
if (mService.isSleeping()) {
r.setSleeping(true);
}
@@ -3145,7 +3154,7 @@ final class ActivityStack {
// normal flow and hide it once we determine that it is
// hidden by the activities in front of it.
if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
- mService.mWindowManager.setAppVisibility(s, false);
+ mService.mWindowManager.setAppVisibility(s.appToken, false);
}
}
if ((!s.waitingVisible || mService.isSleeping()) && remove) {
@@ -3186,14 +3195,14 @@ final class ActivityStack {
boolean enableScreen = false;
synchronized (mService) {
- if (token != null) {
- mHandler.removeMessages(IDLE_TIMEOUT_MSG, token);
+ ActivityRecord r = ActivityRecord.forToken(token);
+ if (r != null) {
+ mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
}
// Get the activity record.
- int index = indexOfTokenLocked(token);
+ int index = indexOfActivityLocked(r);
if (index >= 0) {
- ActivityRecord r = mHistory.get(index);
res = r;
if (fromTimeout) {
@@ -3413,7 +3422,7 @@ final class ActivityStack {
: WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE, false);
// Tell window manager to prepare for this one to be removed.
- mService.mWindowManager.setAppVisibility(r, false);
+ mService.mWindowManager.setAppVisibility(r.appToken, false);
if (mPausingActivity == null) {
if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
@@ -3440,7 +3449,7 @@ final class ActivityStack {
private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
int mode) {
- final int index = indexOfTokenLocked(r);
+ final int index = indexOfActivityLocked(r);
if (index < 0) {
return null;
}
@@ -3570,9 +3579,9 @@ final class ActivityStack {
if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
+ " (removed from history)");
r.state = ActivityState.DESTROYED;
- mService.mWindowManager.removeAppToken(r);
+ mService.mWindowManager.removeAppToken(r.appToken);
if (VALIDATE_TOKENS) {
- mService.mWindowManager.validateAppTokens(mHistory);
+ validateAppTokensLocked();
}
cleanUpActivityServicesLocked(r);
r.removeUriPermissionsLocked();
@@ -3653,7 +3662,7 @@ final class ActivityStack {
try {
if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
- r.app.thread.scheduleDestroyActivity(r, r.finishing,
+ r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
r.configChangeFlags);
} catch (Exception e) {
// We can just ignore exceptions here... if the process
@@ -3712,11 +3721,13 @@ final class ActivityStack {
final void activityDestroyed(IBinder token) {
synchronized (mService) {
- mHandler.removeMessages(DESTROY_TIMEOUT_MSG, token);
+ ActivityRecord r = ActivityRecord.forToken(token);
+ if (r != null) {
+ mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
+ }
- int index = indexOfTokenLocked(token);
+ int index = indexOfActivityLocked(r);
if (index >= 0) {
- ActivityRecord r = mHistory.get(index);
if (r.state == ActivityState.DESTROYING) {
final long origId = Binder.clearCallingIdentity();
removeActivityFromHistoryLocked(r);
@@ -3781,7 +3792,7 @@ final class ActivityStack {
return;
}
- ArrayList moved = new ArrayList();
+ ArrayList<IBinder> moved = new ArrayList<IBinder>();
// Applying the affinities may have removed entries from the history,
// so get the size again.
@@ -3803,7 +3814,7 @@ final class ActivityStack {
}
mHistory.remove(pos);
mHistory.add(top, r);
- moved.add(0, r);
+ moved.add(0, r.appToken);
top--;
}
pos--;
@@ -3826,7 +3837,7 @@ final class ActivityStack {
mService.mWindowManager.moveAppTokensToTop(moved);
if (VALIDATE_TOKENS) {
- mService.mWindowManager.validateAppTokens(mHistory);
+ validateAppTokensLocked();
}
finishTaskMoveLocked(task);
@@ -3873,7 +3884,7 @@ final class ActivityStack {
}
}
- ArrayList moved = new ArrayList();
+ ArrayList<IBinder> moved = new ArrayList<IBinder>();
if (DEBUG_TRANSITION) Slog.v(TAG,
"Prepare to back transition: task=" + task);
@@ -3898,7 +3909,7 @@ final class ActivityStack {
}
mHistory.remove(pos);
mHistory.add(bottom, r);
- moved.add(r);
+ moved.add(r.appToken);
bottom++;
}
pos++;
@@ -3918,7 +3929,7 @@ final class ActivityStack {
}
mService.mWindowManager.moveAppTokensToBottom(moved);
if (VALIDATE_TOKENS) {
- mService.mWindowManager.validateAppTokens(mHistory);
+ validateAppTokensLocked();
}
finishTaskMoveLocked(task);
@@ -4148,7 +4159,7 @@ final class ActivityStack {
if (r.app != null && r.app.thread != null) {
try {
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
- r.app.thread.scheduleActivityConfigurationChanged(r);
+ r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
} catch (RemoteException e) {
// If process died, whatever.
}
@@ -4178,7 +4189,7 @@ final class ActivityStack {
try {
if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
r.forceNewConfig = false;
- r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
+ r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
changes, !andResume, mService.mConfiguration);
// Note: don't need to call pauseIfSleepingLocked() here, because
// the caller will only pass in 'andResume' if this activity is
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 7bd29d9..c344bc6 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -73,7 +73,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
private Context mContext;
private final static String TAG = "Tethering";
private final static boolean DBG = true;
- private final static boolean VDBG = true;
+ private final static boolean VDBG = false;
// TODO - remove both of these - should be part of interface inspection/selection stuff
private String[] mTetherableUsbRegexs;
@@ -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) {
@@ -214,7 +228,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
if (isUsb(iface)) {
// ignore usb0 down after enabling RNDIS
// we will handle disconnect in interfaceRemoved instead
- if (VDBG) Log.d(TAG, "ignoring interface down for " + iface);
+ if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
} else if (sm != null) {
sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
mIfaces.remove(iface);
@@ -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");
@@ -278,12 +298,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
mIfaces.put(iface, sm);
sm.start();
}
- if (VDBG) Log.d(TAG, "interfaceAdded :" + iface);
}
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 +320,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 +338,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 +355,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 +383,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);
@@ -394,7 +414,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
erroredList);
mContext.sendStickyBroadcast(broadcast);
- if (VDBG) {
+ if (DBG) {
Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
activeList.size() + ", " + erroredList.size());
}
@@ -469,7 +489,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 +565,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
return true;
}
+ // TODO - return copies so people can't tamper
public String[] getTetherableUsbRegexs() {
return mTetherableUsbRegexs;
}
@@ -561,7 +582,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 +602,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 +617,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 +674,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 +687,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 +705,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 +804,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 {
@@ -826,7 +864,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
@Override
public boolean processMessage(Message message) {
- if (VDBG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
+ if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
boolean retValue = true;
switch (message.what) {
case CMD_TETHER_REQUESTED:
@@ -867,7 +905,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
}
@Override
public boolean processMessage(Message message) {
- if (VDBG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
+ if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
boolean retValue = true;
switch (message.what) {
// maybe a parent class?
@@ -910,6 +948,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 +960,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
@@ -945,7 +984,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
@Override
public boolean processMessage(Message message) {
- if (VDBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
+ if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
boolean retValue = true;
boolean error = false;
switch (message.what) {
@@ -987,6 +1026,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) {}
@@ -1020,7 +1060,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
break;
}
- if (VDBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
+ if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
sendTetherStateChangedBroadcast();
if (mUsb) {
if (!Tethering.this.configureUsbIface(false)) {
@@ -1150,13 +1190,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 +1216,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,32 +1270,32 @@ 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;
+ }
}
}
- if (VDBG) {
+ if (DBG) {
Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
+ mPreferredUpstreamMobileApn + ", got type=" + upType);
}
@@ -1283,7 +1319,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();
}
@@ -1291,7 +1327,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
}
protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
- if (VDBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
+ if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
mUpstreamIfaceName = ifaceName;
for (Object o : mNotifyList) {
TetherInterfaceSM sm = (TetherInterfaceSM)o;
@@ -1307,7 +1343,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
}
@Override
public boolean processMessage(Message message) {
- if (VDBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
+ if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
boolean retValue = true;
switch (message.what) {
case CMD_TETHER_MODE_REQUESTED:
@@ -1349,7 +1385,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
}
@Override
public boolean processMessage(Message message) {
- if (VDBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
+ if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
boolean retValue = true;
switch (message.what) {
case CMD_TETHER_MODE_REQUESTED:
@@ -1483,14 +1519,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/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 289ea1f..2a1b1db 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -190,6 +190,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final int MSG_METERED_IFACES_CHANGED = 2;
private static final int MSG_FOREGROUND_ACTIVITIES_CHANGED = 3;
private static final int MSG_PROCESS_DIED = 4;
+ private static final int MSG_LIMIT_REACHED = 5;
private final Context mContext;
private final IActivityManager mActivityManager;
@@ -225,8 +226,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
/** Set of currently active {@link Notification} tags. */
private HashSet<String> mActiveNotifs = Sets.newHashSet();
- /** Current values from {@link #setPolicyDataEnable(int, boolean)}. */
- private SparseBooleanArray mActiveNetworkEnabled = new SparseBooleanArray();
/** Foreground at both UID and PID granularity. */
private SparseBooleanArray mUidForeground = new SparseBooleanArray();
@@ -424,19 +423,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// only someone like NMS should be calling us
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- synchronized (mRulesLock) {
- if (mMeteredIfaces.contains(iface) && !LIMIT_GLOBAL_ALERT.equals(limitName)) {
- try {
- // force stats update to make sure we have numbers that
- // caused alert to trigger.
- mNetworkStats.forceUpdate();
- } catch (RemoteException e) {
- // ignored; service lives in system_server
- }
-
- updateNetworkEnabledLocked();
- updateNotificationsLocked();
- }
+ if (!LIMIT_GLOBAL_ALERT.equals(limitName)) {
+ mHandler.obtainMessage(MSG_LIMIT_REACHED, iface).sendToTarget();
}
}
};
@@ -1481,6 +1469,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
return true;
}
+ case MSG_LIMIT_REACHED: {
+ final String iface = (String) msg.obj;
+
+ synchronized (mRulesLock) {
+ if (mMeteredIfaces.contains(iface)) {
+ try {
+ // force stats update to make sure we have
+ // numbers that caused alert to trigger.
+ mNetworkStats.forceUpdate();
+ } catch (RemoteException e) {
+ // ignored; service lives in system_server
+ }
+
+ updateNetworkEnabledLocked();
+ updateNotificationsLocked();
+ }
+ }
+ return true;
+ }
default: {
return false;
}
@@ -1519,21 +1526,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
/**
- * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)},
- * dispatching only when actually changed.
+ * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}.
*/
private void setPolicyDataEnable(int networkType, boolean enabled) {
- synchronized (mActiveNetworkEnabled) {
- final boolean prevEnabled = mActiveNetworkEnabled.get(networkType, true);
- if (prevEnabled == enabled) return;
-
- try {
- mConnManager.setPolicyDataEnable(networkType, enabled);
- } catch (RemoteException e) {
- // ignored; service lives in system_server
- }
-
- mActiveNetworkEnabled.put(networkType, enabled);
+ try {
+ mConnManager.setPolicyDataEnable(networkType, enabled);
+ } catch (RemoteException e) {
+ // ignored; service lives in system_server
}
}
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 494c655..6365525 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -152,10 +152,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private static final String TAG_NETSTATS_ERROR = "netstats_error";
- private static final String DEV = "dev";
- private static final String XT = "xt";
- private static final String UID = "uid";
-
private final Context mContext;
private final INetworkManagementService mNetworkManager;
private final IAlarmManager mAlarmManager;
@@ -278,6 +274,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
readNetworkXtStatsLocked();
}
+ // bootstrap initial stats to prevent double-counting later
+ bootstrapStats();
+
// watch for network interfaces to be claimed
final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
@@ -311,9 +310,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
registerPollAlarmLocked();
registerGlobalAlert();
- // bootstrap initial stats to prevent double-counting later
- bootstrapStats();
-
mDropBox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
}
@@ -810,9 +806,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final NetworkStats networkDevSnapshot;
try {
// collect any tethering stats
- final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs();
- final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering(
- tetheredIfacePairs);
+ final NetworkStats tetherSnapshot = getNetworkStatsTethering();
// record uid stats, folding in tethering stats
uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
@@ -837,9 +831,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// persist when enough network data has occurred
final long persistNetworkDevDelta = computeStatsDelta(
- mLastPersistNetworkDevSnapshot, networkDevSnapshot, true, DEV).getTotalBytes();
+ mLastPersistNetworkDevSnapshot, networkDevSnapshot, true, "devp").getTotalBytes();
final long persistNetworkXtDelta = computeStatsDelta(
- mLastPersistNetworkXtSnapshot, networkXtSnapshot, true, XT).getTotalBytes();
+ mLastPersistNetworkXtSnapshot, networkXtSnapshot, true, "xtp").getTotalBytes();
final boolean networkOverThreshold = persistNetworkDevDelta > threshold
|| persistNetworkXtDelta > threshold;
if (persistForce || (persistNetwork && networkOverThreshold)) {
@@ -851,7 +845,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// persist when enough uid data has occurred
final long persistUidDelta = computeStatsDelta(
- mLastPersistUidSnapshot, uidSnapshot, true, UID).getTotalBytes();
+ mLastPersistUidSnapshot, uidSnapshot, true, "uidp").getTotalBytes();
if (persistForce || (persistUid && persistUidDelta > threshold)) {
writeUidStatsLocked();
mLastPersistUidSnapshot = uidSnapshot;
@@ -880,7 +874,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final HashSet<String> unknownIface = Sets.newHashSet();
final NetworkStats delta = computeStatsDelta(
- mLastPollNetworkDevSnapshot, networkDevSnapshot, false, DEV);
+ mLastPollNetworkDevSnapshot, networkDevSnapshot, false, "dev");
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
@@ -910,7 +904,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final HashSet<String> unknownIface = Sets.newHashSet();
final NetworkStats delta = computeStatsDelta(
- mLastPollNetworkXtSnapshot, networkXtSnapshot, false, XT);
+ mLastPollNetworkXtSnapshot, networkXtSnapshot, false, "xt");
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
@@ -940,9 +934,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
ensureUidStatsLoadedLocked();
final NetworkStats delta = computeStatsDelta(
- mLastPollUidSnapshot, uidSnapshot, false, UID);
+ mLastPollUidSnapshot, uidSnapshot, false, "uid");
final NetworkStats operationsDelta = computeStatsDelta(
- mLastPollOperationsSnapshot, mOperations, false, UID);
+ mLastPollOperationsSnapshot, mOperations, false, "uidop");
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
@@ -971,8 +965,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
mLastPollUidSnapshot = uidSnapshot;
- mLastPollOperationsSnapshot = mOperations;
- mOperations = new NetworkStats(0L, 10);
+ mLastPollOperationsSnapshot = mOperations.clone();
}
/**
@@ -1510,20 +1503,25 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
NetworkStats before, NetworkStats current, boolean collectStale, String type) {
if (before != null) {
try {
- return current.subtract(before);
+ return current.subtract(before, false);
} catch (NonMonotonicException e) {
Log.w(TAG, "found non-monotonic values; saving to dropbox");
// record error for debugging
final StringBuilder builder = new StringBuilder();
- builder.append("found non-monotonic " + type + "values at left[" + e.leftIndex
+ builder.append("found non-monotonic " + type + " values at left[" + e.leftIndex
+ "] - right[" + e.rightIndex + "]\n");
builder.append("left=").append(e.left).append('\n');
builder.append("right=").append(e.right).append('\n');
mDropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
- // return empty delta to avoid recording broken stats
- return new NetworkStats(0L, 10);
+ try {
+ // return clamped delta to help recover
+ return current.subtract(before, true);
+ } catch (NonMonotonicException e1) {
+ Log.wtf(TAG, "found non-monotonic values; returning empty delta", e1);
+ return new NetworkStats(0L, 10);
+ }
}
} else if (collectStale) {
// caller is okay collecting stale stats for first call.
@@ -1535,6 +1533,20 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
}
+ /**
+ * Return snapshot of current tethering statistics. Will return empty
+ * {@link NetworkStats} if any problems are encountered.
+ */
+ private NetworkStats getNetworkStatsTethering() throws RemoteException {
+ try {
+ final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs();
+ return mNetworkManager.getNetworkStatsTethering(tetheredIfacePairs);
+ } catch (IllegalStateException e) {
+ Log.wtf(TAG, "problem reading network stats", e);
+ return new NetworkStats(0L, 10);
+ }
+ }
+
private static NetworkStats computeNetworkXtSnapshotFromUid(NetworkStats uidSnapshot) {
return uidSnapshot.groupedByIface();
}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index bfe6613..36442a0 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -63,6 +63,8 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import libcore.io.IoUtils;
+
/**
* Holds information about dynamic settings.
*/
@@ -998,8 +1000,8 @@ final class Settings {
FileUtils.sync(fstr);
str.close();
journal.commit();
- }
- catch (Exception e) {
+ } catch (Exception e) {
+ IoUtils.closeQuietly(str);
journal.rollback();
}
diff --git a/services/java/com/android/server/wm/InputManager.java b/services/java/com/android/server/wm/InputManager.java
index df7e0e1..a4f0a0c 100644
--- a/services/java/com/android/server/wm/InputManager.java
+++ b/services/java/com/android/server/wm/InputManager.java
@@ -675,7 +675,13 @@ public class InputManager implements Watchdog.Monitor {
} catch (NumberFormatException e) {
}
if (result < 1) {
- result = 55;
+ // This number equates to the refresh rate * 1.5. The rate should be at least
+ // equal to the screen refresh rate. We increase the rate by 50% to compensate for
+ // the discontinuity between the actual rate that events come in at (they do
+ // not necessarily come in constantly and are not handled synchronously).
+ // Ideally, we would use Display.getRefreshRate(), but as this does not necessarily
+ // return a sensible result, we use '60' as our default assumed refresh rate.
+ result = 90;
}
return result;
}
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 131f11c..8fc9a70 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -88,13 +88,14 @@ class ScreenRotationAnimation {
try {
try {
mSurface = new Surface(session, 0, "FreezeSurface",
- -1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT);
+ -1, mWidth, mHeight, PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
if (mSurface == null || !mSurface.isValid()) {
// Screenshot failed, punt.
mSurface = null;
return;
}
mSurface.setLayer(FREEZE_LAYER + 1);
+ mSurface.show();
} catch (Surface.OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate freeze surface", e);
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 2cd3062..50321b3 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -3070,7 +3070,7 @@ public class WindowManagerService extends IWindowManager.Stub
// Application Window Tokens
// -------------------------------------------------------------
- public void validateAppTokens(List tokens) {
+ public void validateAppTokens(List<IBinder> tokens) {
int v = tokens.size()-1;
int m = mAppTokens.size()-1;
while (v >= 0 && m >= 0) {
@@ -5809,7 +5809,87 @@ public class WindowManagerService extends IWindowManager.Stub
return curSize;
}
- private int computeSmallestWidth(boolean rotated, int dw, int dh, float density) {
+ private int reduceConfigLayout(int curLayout, int rotation, float density,
+ int dw, int dh) {
+ // Get the app screen size at this rotation.
+ int w = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
+ int h = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
+
+ // Compute the screen layout size class for this rotation.
+ int screenLayoutSize;
+ boolean screenLayoutLong;
+ boolean screenLayoutCompatNeeded;
+ int longSize = w;
+ int shortSize = h;
+ if (longSize < shortSize) {
+ int tmp = longSize;
+ longSize = shortSize;
+ shortSize = tmp;
+ }
+ longSize = (int)(longSize/density);
+ shortSize = (int)(shortSize/density);
+
+ // These semi-magic numbers define our compatibility modes for
+ // applications with different screens. These are guarantees to
+ // app developers about the space they can expect for a particular
+ // configuration. DO NOT CHANGE!
+ if (longSize < 470) {
+ // This is shorter than an HVGA normal density screen (which
+ // is 480 pixels on its long side).
+ screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_SMALL;
+ screenLayoutLong = false;
+ screenLayoutCompatNeeded = false;
+ } else {
+ // What size is this screen screen?
+ if (longSize >= 960 && shortSize >= 720) {
+ // 1.5xVGA or larger screens at medium density are the point
+ // at which we consider it to be an extra large screen.
+ screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_XLARGE;
+ } else if (longSize >= 640 && shortSize >= 480) {
+ // VGA or larger screens at medium density are the point
+ // at which we consider it to be a large screen.
+ screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_LARGE;
+ } else {
+ screenLayoutSize = Configuration.SCREENLAYOUT_SIZE_NORMAL;
+ }
+
+ // If this screen is wider than normal HVGA, or taller
+ // than FWVGA, then for old apps we want to run in size
+ // compatibility mode.
+ if (shortSize > 321 || longSize > 570) {
+ screenLayoutCompatNeeded = true;
+ } else {
+ screenLayoutCompatNeeded = false;
+ }
+
+ // Is this a long screen?
+ if (((longSize*3)/5) >= (shortSize-1)) {
+ // Anything wider than WVGA (5:3) is considering to be long.
+ screenLayoutLong = true;
+ } else {
+ screenLayoutLong = false;
+ }
+ }
+
+ // Now reduce the last screenLayout to not be better than what we
+ // have found.
+ if (!screenLayoutLong) {
+ curLayout = (curLayout&~Configuration.SCREENLAYOUT_LONG_MASK)
+ | Configuration.SCREENLAYOUT_LONG_NO;
+ }
+ if (screenLayoutCompatNeeded) {
+ curLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
+ }
+ int curSize = curLayout&Configuration.SCREENLAYOUT_SIZE_MASK;
+ if (screenLayoutSize < curSize) {
+ curLayout = (curLayout&~Configuration.SCREENLAYOUT_SIZE_MASK)
+ | screenLayoutSize;
+ }
+ return curLayout;
+ }
+
+ private void computeSmallestWidthAndScreenLayout(boolean rotated, int dw, int dh,
+ float density, Configuration outConfig) {
// We need to determine the smallest width that will occur under normal
// operation. To this, start with the base screen size and compute the
// width under the different possible rotations. We need to un-rotate
@@ -5826,7 +5906,14 @@ public class WindowManagerService extends IWindowManager.Stub
sw = reduceConfigWidthSize(sw, Surface.ROTATION_90, density, unrotDh, unrotDw);
sw = reduceConfigWidthSize(sw, Surface.ROTATION_180, density, unrotDw, unrotDh);
sw = reduceConfigWidthSize(sw, Surface.ROTATION_270, density, unrotDh, unrotDw);
- return sw;
+ int sl = Configuration.SCREENLAYOUT_SIZE_XLARGE
+ | Configuration.SCREENLAYOUT_LONG_YES;
+ sl = reduceConfigLayout(sl, Surface.ROTATION_0, density, unrotDw, unrotDh);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_90, density, unrotDh, unrotDw);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_180, density, unrotDw, unrotDh);
+ sl = reduceConfigLayout(sl, Surface.ROTATION_270, density, unrotDh, unrotDw);
+ outConfig.smallestScreenWidthDp = sw;
+ outConfig.screenLayout = sl;
}
private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
@@ -5924,64 +6011,12 @@ public class WindowManagerService extends IWindowManager.Stub
/ dm.density);
config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
/ dm.density);
- config.smallestScreenWidthDp = computeSmallestWidth(rotated, dw, dh, dm.density);
+ computeSmallestWidthAndScreenLayout(rotated, dw, dh, dm.density, config);
config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
config.compatScreenHeightDp = (int)(config.screenHeightDp / mCompatibleScreenScale);
config.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, dm, dw, dh);
- // Compute the screen layout size class.
- int screenLayout;
- int longSize = mAppDisplayWidth;
- int shortSize = mAppDisplayHeight;
- if (longSize < shortSize) {
- int tmp = longSize;
- longSize = shortSize;
- shortSize = tmp;
- }
- longSize = (int)(longSize/dm.density);
- shortSize = (int)(shortSize/dm.density);
-
- // These semi-magic numbers define our compatibility modes for
- // applications with different screens. These are guarantees to
- // app developers about the space they can expect for a particular
- // configuration. DO NOT CHANGE!
- if (longSize < 470) {
- // This is shorter than an HVGA normal density screen (which
- // is 480 pixels on its long side).
- screenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL
- | Configuration.SCREENLAYOUT_LONG_NO;
- } else {
- // What size is this screen screen?
- if (longSize >= 960 && shortSize >= 720) {
- // 1.5xVGA or larger screens at medium density are the point
- // at which we consider it to be an extra large screen.
- screenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE;
- } else if (longSize >= 640 && shortSize >= 480) {
- // VGA or larger screens at medium density are the point
- // at which we consider it to be a large screen.
- screenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE;
- } else {
- screenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL;
- }
-
- // If this screen is wider than normal HVGA, or taller
- // than FWVGA, then for old apps we want to run in size
- // compatibility mode.
- if (shortSize > 321 || longSize > 570) {
- screenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED;
- }
-
- // Is this a long screen?
- if (((longSize*3)/5) >= (shortSize-1)) {
- // Anything wider than WVGA (5:3) is considering to be long.
- screenLayout |= Configuration.SCREENLAYOUT_LONG_YES;
- } else {
- screenLayout |= Configuration.SCREENLAYOUT_LONG_NO;
- }
- }
- config.screenLayout = screenLayout;
-
// Determine whether a hard keyboard is available and enabled.
boolean hardKeyboardAvailable = config.keyboard != Configuration.KEYBOARD_NOKEYS;
if (hardKeyboardAvailable != mHardKeyboardAvailable) {
@@ -8682,7 +8717,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.