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/AppWidgetService.java5
-rw-r--r--services/java/com/android/server/ConnectivityService.java94
-rw-r--r--services/java/com/android/server/DockObserver.java4
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java63
-rw-r--r--services/java/com/android/server/NetworkManagementService.java11
-rw-r--r--services/java/com/android/server/PowerManagerService.java33
-rw-r--r--services/java/com/android/server/TextServicesManagerService.java45
-rw-r--r--services/java/com/android/server/UiModeManagerService.java45
-rw-r--r--services/java/com/android/server/Watchdog.java3
-rw-r--r--services/java/com/android/server/WifiService.java52
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java329
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java88
-rw-r--r--services/java/com/android/server/am/ActivityStack.java225
-rw-r--r--services/java/com/android/server/am/EventLogTags.logtags2
-rw-r--r--services/java/com/android/server/am/ProcessList.java46
-rw-r--r--services/java/com/android/server/am/ProcessRecord.java4
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java23
-rw-r--r--services/java/com/android/server/net/NetworkPolicyManagerService.java62
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java85
-rw-r--r--services/java/com/android/server/pm/Settings.java6
-rw-r--r--services/java/com/android/server/wm/AppWindowToken.java24
-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/Session.java10
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java199
-rw-r--r--services/java/com/android/server/wm/WindowState.java17
26 files changed, 1021 insertions, 465 deletions
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index eb75ebc..2af5103 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -751,10 +751,13 @@ class AppWidgetService extends IAppWidgetService.Stub
return;
}
ArrayList<AppWidgetId> instances = p.instances;
+ final int callingUid = getCallingUid();
final int N = instances.size();
for (int i=0; i<N; i++) {
AppWidgetId id = instances.get(i);
- updateAppWidgetInstanceLocked(id, views);
+ if (canAccessAppWidgetId(id, callingUid)) {
+ updateAppWidgetInstanceLocked(id, views);
+ }
}
}
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 8c42f31..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;
@@ -491,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);
@@ -501,7 +514,9 @@ 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);
@@ -531,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
@@ -1508,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
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/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 6ddbf5a..ddac35c 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -161,6 +161,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans =
new LruCache<SuggestionSpan, InputMethodInfo>(SECURE_SUGGESTION_SPANS_MAX_SIZE);
+ // Used to bring IME service up to visible adjustment while it is being shown.
+ final ServiceConnection mVisibleConnection = new ServiceConnection() {
+ @Override public void onServiceConnected(ComponentName name, IBinder service) {
+ }
+
+ @Override public void onServiceDisconnected(ComponentName name) {
+ }
+ };
+ boolean mVisibleBound = false;
+
// Ongoing notification
private NotificationManager mNotificationManager;
private KeyguardManager mKeyguardManager;
@@ -374,6 +384,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mScreenOn = true;
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
mScreenOn = false;
+ setImeWindowVisibilityStatusHiddenLocked();
} else if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
hideInputMethodMenu();
return;
@@ -468,8 +479,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// Uh oh, current input method is no longer around!
// Pick another one...
Slog.i(TAG, "Current input method removed: " + curInputMethodId);
- mImeWindowVis = 0;
- updateImeWindowStatusLocked();
+ setImeWindowVisibilityStatusHiddenLocked();
if (!chooseNewDefaultIMELocked()) {
changed = true;
curIm = null;
@@ -493,11 +503,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
- class MethodCallback extends IInputMethodCallback.Stub {
- final IInputMethod mMethod;
+ private static class MethodCallback extends IInputMethodCallback.Stub {
+ private final IInputMethod mMethod;
+ private final InputMethodManagerService mParentIMMS;
- MethodCallback(IInputMethod method) {
+ MethodCallback(final IInputMethod method, final InputMethodManagerService imms) {
mMethod = method;
+ mParentIMMS = imms;
}
@Override
@@ -506,7 +518,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public void sessionCreated(IInputMethodSession session) throws RemoteException {
- onSessionCreated(mMethod, session);
+ mParentIMMS.onSessionCreated(mMethod, session);
}
}
@@ -623,7 +635,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
- void updateImeWindowStatusLocked() {
+ private void setImeWindowVisibilityStatusHiddenLocked() {
+ mImeWindowVis = 0;
+ updateImeWindowStatusLocked();
+ }
+
+ private void updateImeWindowStatusLocked() {
setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition);
}
@@ -837,7 +854,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
MSG_CREATE_SESSION, mCurMethod,
- new MethodCallback(mCurMethod)));
+ new MethodCallback(mCurMethod, this)));
}
// Return to client, and we will get back with it when
// we have had a session made for it.
@@ -886,7 +903,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
com.android.internal.R.string.input_method_binding_label);
mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
- if (mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE)) {
+ if (mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE
+ | Context.BIND_NOT_VISIBLE)) {
mLastBindTime = SystemClock.uptimeMillis();
mHaveConnection = true;
mCurId = info.getId();
@@ -943,7 +961,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
+ mCurClient);
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
MSG_CREATE_SESSION, mCurMethod,
- new MethodCallback(mCurMethod)));
+ new MethodCallback(mCurMethod, this)));
}
}
}
@@ -968,6 +986,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
void unbindCurrentMethodLocked(boolean reportToClient) {
+ if (mVisibleBound) {
+ mContext.unbindService(mVisibleConnection);
+ mVisibleBound = false;
+ }
+
if (mHaveConnection) {
mContext.unbindService(this);
mHaveConnection = false;
@@ -997,8 +1020,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
sessionState.session.finishSession();
} catch (RemoteException e) {
Slog.w(TAG, "Session failed to close due to remote exception", e);
- mImeWindowVis = 0;
- updateImeWindowStatusLocked();
+ setImeWindowVisibilityStatusHiddenLocked();
}
}
}
@@ -1360,6 +1382,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
resultReceiver));
mInputShown = true;
+ if (mHaveConnection && !mVisibleBound) {
+ mContext.bindService(mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE);
+ mVisibleBound = true;
+ }
res = true;
} else if (mHaveConnection && SystemClock.uptimeMillis()
>= (mLastBindTime+TIME_TO_RECONNECT)) {
@@ -1371,7 +1397,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
SystemClock.uptimeMillis()-mLastBindTime,1);
Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
mContext.unbindService(this);
- mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE);
+ mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE
+ | Context.BIND_NOT_VISIBLE);
}
return res;
@@ -1393,13 +1420,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (!mIWindowManager.inputMethodClientHasFocus(client)) {
if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid "
+ uid + ": " + client);
- mImeWindowVis = 0;
- updateImeWindowStatusLocked();
+ setImeWindowVisibilityStatusHiddenLocked();
return false;
}
} catch (RemoteException e) {
- mImeWindowVis = 0;
- updateImeWindowStatusLocked();
+ setImeWindowVisibilityStatusHiddenLocked();
return false;
}
}
@@ -1432,6 +1457,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
} else {
res = false;
}
+ if (mHaveConnection && mVisibleBound) {
+ mContext.unbindService(mVisibleConnection);
+ mVisibleBound = false;
+ }
mInputShown = false;
mShowRequested = false;
mShowExplicitlyRequested = false;
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 4c26dbb..da960ae 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -247,6 +247,11 @@ public class NetworkManagementService extends INetworkManagementService.Stub
* Notify our observers of an interface removal.
*/
private void notifyInterfaceRemoved(String iface) {
+ // netd already clears out quota and alerts for removed ifaces; update
+ // our sanity-checking state.
+ mActiveAlertIfaces.remove(iface);
+ mActiveQuotaIfaces.remove(iface);
+
for (INetworkManagementEventObserver obs : mObservers) {
try {
obs.interfaceRemoved(iface);
@@ -1131,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 fdae4bd..6b23b33 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
@@ -2198,25 +2201,21 @@ public class PowerManagerService extends IPowerManager.Stub
}
public void run() {
- if (mAnimateScreenLights) {
- synchronized (mLocks) {
+ synchronized (mLocks) {
+ // we're turning off
+ final boolean turningOff = animating && targetValue == Power.BRIGHTNESS_OFF;
+ if (mAnimateScreenLights || !turningOff) {
long now = SystemClock.uptimeMillis();
boolean more = mScreenBrightness.stepLocked();
if (more) {
mScreenOffHandler.postAtTime(this, now+(1000/60));
}
- }
- } else {
- synchronized (mLocks) {
- // we're turning off
- final boolean animate = animating && targetValue == Power.BRIGHTNESS_OFF;
- if (animate) {
- // It's pretty scary to hold mLocks for this long, and we should
- // redesign this, but it works for now.
- nativeStartSurfaceFlingerAnimation(
- mScreenOffReason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
- ? 0 : mAnimationSetting);
- }
+ } else {
+ // It's pretty scary to hold mLocks for this long, and we should
+ // redesign this, but it works for now.
+ nativeStartSurfaceFlingerAnimation(
+ mScreenOffReason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
+ ? 0 : mAnimationSetting);
mScreenBrightness.jumpToTargetLocked();
}
}
@@ -3053,7 +3052,7 @@ public class PowerManagerService extends IPowerManager.Stub
try {
if (enable) {
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 1976eba..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;
}
}
@@ -635,7 +661,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
if (DBG) {
Slog.w(TAG, "Remove " + removeList.get(i));
}
- mListeners.remove(removeList.get(i));
+ final InternalDeathRecipient idr = removeList.get(i);
+ idr.mScListener.asBinder().unlinkToDeath(idr, 0);
+ mListeners.remove(idr);
}
cleanLocked();
}
@@ -664,6 +692,11 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
public void removeAll() {
Slog.e(TAG, "Remove the spell checker bind unexpectedly.");
synchronized(mSpellCheckerMap) {
+ final int size = mListeners.size();
+ for (int i = 0; i < size; ++i) {
+ final InternalDeathRecipient idr = mListeners.get(i);
+ idr.mScListener.asBinder().unlinkToDeath(idr, 0);
+ }
mListeners.clear();
cleanLocked();
}
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/Watchdog.java b/services/java/com/android/server/Watchdog.java
index 2d3ac00..728fb26 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -451,7 +451,8 @@ public class Watchdog extends Thread {
Thread dropboxThread = new Thread("watchdogWriteToDropbox") {
public void run() {
mActivity.addErrorToDropBox(
- "watchdog", null, null, null, name, null, stack, null);
+ "watchdog", null, "system_server", null, null,
+ name, null, stack, null);
}
};
dropboxThread.start();
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 2a867af..cd63090 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -296,7 +296,7 @@ public final class ActivityManagerService extends ActivityManagerNative
/**
* Historical data of past broadcasts, for debugging.
*/
- static final int MAX_BROADCAST_HISTORY = 100;
+ static final int MAX_BROADCAST_HISTORY = 25;
final BroadcastRecord[] mBroadcastHistory
= new BroadcastRecord[MAX_BROADCAST_HISTORY];
@@ -411,6 +411,12 @@ public final class ActivityManagerService extends ActivityManagerNative
ProcessRecord mHomeProcess;
/**
+ * This is the process holding the activity the user last visited that
+ * is in a different process from the one they are currently in.
+ */
+ ProcessRecord mPreviousProcess;
+
+ /**
* Packages that the user has asked to have run in screen size
* compatibility mode instead of filling the screen.
*/
@@ -724,6 +730,13 @@ public final class ActivityManagerService extends ActivityManagerNative
int mLruSeq = 0;
/**
+ * Keep track of the number of service processes we last found, to
+ * determine on the next iteration which should be B services.
+ */
+ int mNumServiceProcs = 0;
+ int mNewNumServiceProcs = 0;
+
+ /**
* System monitoring: number of processes that died since the last
* N procs were started.
*/
@@ -1207,6 +1220,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
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", });
@@ -1220,16 +1235,29 @@ public final class ActivityManagerService extends ActivityManagerNative
break;
}
if (line.length() > 0) {
- Slog.i(TAG, line);
+ 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);
- dumpApplicationMemoryUsage(null, pw, " ", new String[] { }, true);
- Slog.i(TAG, sw.toString());
+ 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) {
@@ -1381,7 +1409,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
- mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false);
+ mActivityManagerService.dumpApplicationMemoryUsage(fd, pw, " ", args, false, null);
}
}
@@ -1641,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);
}
}
@@ -2318,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);
@@ -2401,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)) {
@@ -2421,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);
}
}
@@ -2487,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");
@@ -2589,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) {
@@ -2677,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();
@@ -3034,7 +3063,8 @@ public final class ActivityManagerService extends ActivityManagerNative
Process.sendSignal(app.pid, Process.SIGNAL_QUIT);
}
- addErrorToDropBox("anr", app, activity, parent, annotation, cpuInfo, tracesFile, null);
+ addErrorToDropBox("anr", app, app.processName, activity, parent, annotation,
+ cpuInfo, tracesFile, null);
if (mController != null) {
try {
@@ -3178,7 +3208,49 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
killPackageProcessesLocked(packageName, pkgUid,
- ProcessList.SECONDARY_SERVER_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);
@@ -3350,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
@@ -3385,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;
}
@@ -3416,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++) {
@@ -3504,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);
@@ -3523,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) {
@@ -4977,7 +5050,7 @@ public final class ActivityManagerService extends ActivityManagerNative
outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
outInfo.hiddenAppThreshold = hiddenAppMem;
outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
- ProcessList.SECONDARY_SERVER_ADJ);
+ ProcessList.SERVICE_ADJ);
outInfo.visibleAppThreshold = mProcessList.getMemLevel(
ProcessList.VISIBLE_APP_ADJ);
outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
@@ -5101,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);
}
}
@@ -5475,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;
}
@@ -5496,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--;
@@ -6168,7 +6241,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT))
== (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) {
app.persistent = true;
- app.maxAdj = ProcessList.CORE_SERVER_ADJ;
+ app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ;
}
if (app.thread == null && mPersistentStartingProcesses.indexOf(app) < 0) {
mPersistentStartingProcesses.add(app);
@@ -6566,14 +6639,15 @@ public final class ActivityManagerService extends ActivityManagerNative
// If the worst oom_adj is somewhere in the hidden proc LRU range,
// then constrain it so we will kill all hidden procs.
- if (worstType < ProcessList.EMPTY_APP_ADJ && worstType > ProcessList.HIDDEN_APP_MIN_ADJ) {
+ if (worstType < ProcessList.HIDDEN_APP_MAX_ADJ
+ && worstType > ProcessList.HIDDEN_APP_MIN_ADJ) {
worstType = ProcessList.HIDDEN_APP_MIN_ADJ;
}
// If this is not a secure call, don't let it kill processes that
// are important.
- if (!secure && worstType < ProcessList.SECONDARY_SERVER_ADJ) {
- worstType = ProcessList.SECONDARY_SERVER_ADJ;
+ if (!secure && worstType < ProcessList.SERVICE_ADJ) {
+ worstType = ProcessList.SERVICE_ADJ;
}
Slog.w(TAG, "Killing processes " + reason + " at adjustment " + worstType);
@@ -6831,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");
}
}
@@ -7027,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;
}
@@ -7039,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
@@ -7138,16 +7212,18 @@ public final class ActivityManagerService extends ActivityManagerNative
*/
public void handleApplicationCrash(IBinder app, ApplicationErrorReport.CrashInfo crashInfo) {
ProcessRecord r = findAppProcess(app, "Crash");
+ final String processName = app == null ? "system_server"
+ : (r == null ? "unknown" : r.processName);
EventLog.writeEvent(EventLogTags.AM_CRASH, Binder.getCallingPid(),
- app == null ? "system" : (r == null ? "unknown" : r.processName),
+ processName,
r == null ? -1 : r.info.flags,
crashInfo.exceptionClassName,
crashInfo.exceptionMessage,
crashInfo.throwFileName,
crashInfo.throwLineNumber);
- addErrorToDropBox("crash", r, null, null, null, null, null, crashInfo);
+ addErrorToDropBox("crash", r, processName, null, null, null, null, null, crashInfo);
crashApplication(r, crashInfo);
}
@@ -7220,6 +7296,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final boolean isSystemApp = process == null ||
(process.info.flags & (ApplicationInfo.FLAG_SYSTEM |
ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0;
+ final String processName = process == null ? "unknown" : process.processName;
final String dropboxTag = isSystemApp ? "system_app_strictmode" : "data_app_strictmode";
final DropBoxManager dbox = (DropBoxManager)
mContext.getSystemService(Context.DROPBOX_SERVICE);
@@ -7232,7 +7309,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final StringBuilder sb = isSystemApp ? mStrictModeBuffer : new StringBuilder(1024);
synchronized (sb) {
bufferWasEmpty = sb.length() == 0;
- appendDropBoxProcessHeaders(process, sb);
+ appendDropBoxProcessHeaders(process, processName, sb);
sb.append("Build: ").append(Build.FINGERPRINT).append("\n");
sb.append("System-App: ").append(isSystemApp).append("\n");
sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n");
@@ -7334,13 +7411,15 @@ public final class ActivityManagerService extends ActivityManagerNative
public boolean handleApplicationWtf(IBinder app, String tag,
ApplicationErrorReport.CrashInfo crashInfo) {
ProcessRecord r = findAppProcess(app, "WTF");
+ final String processName = app == null ? "system_server"
+ : (r == null ? "unknown" : r.processName);
EventLog.writeEvent(EventLogTags.AM_WTF, Binder.getCallingPid(),
- app == null ? "system" : (r == null ? "unknown" : r.processName),
+ processName,
r == null ? -1 : r.info.flags,
tag, crashInfo.exceptionMessage);
- addErrorToDropBox("wtf", r, null, null, tag, null, null, crashInfo);
+ addErrorToDropBox("wtf", r, processName, null, null, tag, null, null, crashInfo);
if (r != null && r.pid != Process.myPid() &&
Settings.Secure.getInt(mContext.getContentResolver(),
@@ -7383,7 +7462,8 @@ public final class ActivityManagerService extends ActivityManagerNative
* Utility function for addErrorToDropBox and handleStrictModeViolation's logging
* to append various headers to the dropbox log text.
*/
- private void appendDropBoxProcessHeaders(ProcessRecord process, StringBuilder sb) {
+ private void appendDropBoxProcessHeaders(ProcessRecord process, String processName,
+ StringBuilder sb) {
// Watchdog thread ends up invoking this function (with
// a null ProcessRecord) to add the stack file to dropbox.
// Do not acquire a lock on this (am) in such cases, as it
@@ -7391,18 +7471,14 @@ public final class ActivityManagerService extends ActivityManagerNative
// is invoked due to unavailability of lock on am and it
// would prevent watchdog from killing system_server.
if (process == null) {
- sb.append("Process: system_server\n");
+ sb.append("Process: ").append(processName).append("\n");
return;
}
// Note: ProcessRecord 'process' is guarded by the service
// instance. (notably process.pkgList, which could otherwise change
// concurrently during execution of this method)
synchronized (this) {
- if (process.pid == MY_PID) {
- sb.append("Process: system_server\n");
- } else {
- sb.append("Process: ").append(process.processName).append("\n");
- }
+ sb.append("Process: ").append(processName).append("\n");
int flags = process.info.flags;
IPackageManager pm = AppGlobals.getPackageManager();
sb.append("Flags: 0x").append(Integer.toString(flags, 16)).append("\n");
@@ -7446,7 +7522,8 @@ public final class ActivityManagerService extends ActivityManagerNative
* @param crashInfo giving an application stack trace, null if absent
*/
public void addErrorToDropBox(String eventType,
- ProcessRecord process, ActivityRecord activity, ActivityRecord parent, String subject,
+ ProcessRecord process, String processName, ActivityRecord activity,
+ ActivityRecord parent, String subject,
final String report, final File logFile,
final ApplicationErrorReport.CrashInfo crashInfo) {
// NOTE -- this must never acquire the ActivityManagerService lock,
@@ -7460,7 +7537,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (dbox == null || !dbox.isTagEnabled(dropboxTag)) return;
final StringBuilder sb = new StringBuilder(1024);
- appendDropBoxProcessHeaders(process, sb);
+ appendDropBoxProcessHeaders(process, processName, sb);
if (activity != null) {
sb.append("Activity: ").append(activity.shortComponentName).append("\n");
}
@@ -7709,19 +7786,19 @@ public final class ActivityManagerService extends ActivityManagerNative
}
static int oomAdjToImportance(int adj, ActivityManager.RunningAppProcessInfo currApp) {
- if (adj >= ProcessList.EMPTY_APP_ADJ) {
- return ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
- } else if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
+ if (adj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
if (currApp != null) {
currApp.lru = adj - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
}
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
+ } else if (adj >= ProcessList.SERVICE_B_ADJ) {
+ return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
} else if (adj >= ProcessList.HOME_APP_ADJ) {
if (currApp != null) {
currApp.lru = 0;
}
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
- } else if (adj >= ProcessList.SECONDARY_SERVER_ADJ) {
+ } else if (adj >= ProcessList.SERVICE_ADJ) {
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
} else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
@@ -8158,6 +8235,7 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.println();
pw.println(" mHomeProcess: " + mHomeProcess);
+ pw.println(" mPreviousProcess: " + mPreviousProcess);
if (mHeavyWeightProcess != null) {
pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
}
@@ -8210,6 +8288,8 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.println(" mGoingToSleep=" + mMainStack.mGoingToSleep);
pw.println(" mLaunchingActivity=" + mMainStack.mLaunchingActivity);
pw.println(" mAdjSeq=" + mAdjSeq + " mLruSeq=" + mLruSeq);
+ pw.println(" mNumServiceProcs=" + mNumServiceProcs
+ + " mNewNumServiceProcs=" + mNewNumServiceProcs);
}
return true;
@@ -8246,16 +8326,18 @@ public final class ActivityManagerService extends ActivityManagerNative
needSep = true;
pw.println(" OOM levels:");
pw.print(" SYSTEM_ADJ: "); pw.println(ProcessList.SYSTEM_ADJ);
- pw.print(" CORE_SERVER_ADJ: "); pw.println(ProcessList.CORE_SERVER_ADJ);
+ pw.print(" PERSISTENT_PROC_ADJ: "); pw.println(ProcessList.PERSISTENT_PROC_ADJ);
pw.print(" FOREGROUND_APP_ADJ: "); pw.println(ProcessList.FOREGROUND_APP_ADJ);
pw.print(" VISIBLE_APP_ADJ: "); pw.println(ProcessList.VISIBLE_APP_ADJ);
pw.print(" PERCEPTIBLE_APP_ADJ: "); pw.println(ProcessList.PERCEPTIBLE_APP_ADJ);
pw.print(" HEAVY_WEIGHT_APP_ADJ: "); pw.println(ProcessList.HEAVY_WEIGHT_APP_ADJ);
pw.print(" BACKUP_APP_ADJ: "); pw.println(ProcessList.BACKUP_APP_ADJ);
- pw.print(" SECONDARY_SERVER_ADJ: "); pw.println(ProcessList.SECONDARY_SERVER_ADJ);
+ pw.print(" SERVICE_ADJ: "); pw.println(ProcessList.SERVICE_ADJ);
pw.print(" HOME_APP_ADJ: "); pw.println(ProcessList.HOME_APP_ADJ);
+ pw.print(" PREVIOUS_APP_ADJ: "); pw.println(ProcessList.PREVIOUS_APP_ADJ);
+ pw.print(" SERVICE_B_ADJ: "); pw.println(ProcessList.SERVICE_B_ADJ);
pw.print(" HIDDEN_APP_MIN_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MIN_ADJ);
- pw.print(" EMPTY_APP_ADJ: "); pw.println(ProcessList.EMPTY_APP_ADJ);
+ pw.print(" HIDDEN_APP_MAX_ADJ: "); pw.println(ProcessList.HIDDEN_APP_MAX_ADJ);
if (needSep) pw.println(" ");
needSep = true;
@@ -8269,6 +8351,7 @@ public final class ActivityManagerService extends ActivityManagerNative
pw.println();
pw.println(" mHomeProcess: " + mHomeProcess);
+ pw.println(" mPreviousProcess: " + mPreviousProcess);
if (mHeavyWeightProcess != null) {
pw.println(" mHeavyWeightProcess: " + mHeavyWeightProcess);
}
@@ -8549,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();
@@ -8966,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);
@@ -9046,14 +9129,16 @@ public final class ActivityManagerService extends ActivityManagerNative
for (int i=N; i>=0; i--) {
ProcessRecord r = list.get(i).first;
String oomAdj;
- if (r.setAdj >= ProcessList.EMPTY_APP_ADJ) {
- oomAdj = buildOomTag("empty", null, r.setAdj, ProcessList.EMPTY_APP_ADJ);
- } else if (r.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
+ if (r.setAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
oomAdj = buildOomTag("bak", " ", r.setAdj, ProcessList.HIDDEN_APP_MIN_ADJ);
+ } else if (r.setAdj >= ProcessList.SERVICE_B_ADJ) {
+ oomAdj = buildOomTag("svcb ", null, r.setAdj, ProcessList.SERVICE_B_ADJ);
+ } else if (r.setAdj >= ProcessList.PREVIOUS_APP_ADJ) {
+ oomAdj = buildOomTag("prev ", null, r.setAdj, ProcessList.PREVIOUS_APP_ADJ);
} else if (r.setAdj >= ProcessList.HOME_APP_ADJ) {
oomAdj = buildOomTag("home ", null, r.setAdj, ProcessList.HOME_APP_ADJ);
- } else if (r.setAdj >= ProcessList.SECONDARY_SERVER_ADJ) {
- oomAdj = buildOomTag("svc", " ", r.setAdj, ProcessList.SECONDARY_SERVER_ADJ);
+ } else if (r.setAdj >= ProcessList.SERVICE_ADJ) {
+ oomAdj = buildOomTag("svc ", null, r.setAdj, ProcessList.SERVICE_ADJ);
} else if (r.setAdj >= ProcessList.BACKUP_APP_ADJ) {
oomAdj = buildOomTag("bckup", null, r.setAdj, ProcessList.BACKUP_APP_ADJ);
} else if (r.setAdj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
@@ -9064,8 +9149,8 @@ public final class ActivityManagerService extends ActivityManagerNative
oomAdj = buildOomTag("vis ", null, r.setAdj, ProcessList.VISIBLE_APP_ADJ);
} else if (r.setAdj >= ProcessList.FOREGROUND_APP_ADJ) {
oomAdj = buildOomTag("fore ", null, r.setAdj, ProcessList.FOREGROUND_APP_ADJ);
- } else if (r.setAdj >= ProcessList.CORE_SERVER_ADJ) {
- oomAdj = buildOomTag("core ", null, r.setAdj, ProcessList.CORE_SERVER_ADJ);
+ } else if (r.setAdj >= ProcessList.PERSISTENT_PROC_ADJ) {
+ oomAdj = buildOomTag("pers ", null, r.setAdj, ProcessList.PERSISTENT_PROC_ADJ);
} else if (r.setAdj >= ProcessList.SYSTEM_ADJ) {
oomAdj = buildOomTag("sys ", null, r.setAdj, ProcessList.SYSTEM_ADJ);
} else {
@@ -9272,8 +9357,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
final void dumpApplicationMemoryUsage(FileDescriptor fd,
- PrintWriter pw, String prefix, String[] args, boolean brief) {
+ PrintWriter pw, String prefix, String[] args, boolean brief,
+ PrintWriter categoryPw) {
boolean dumpAll = false;
+ boolean oomOnly = false;
int opti = 0;
while (opti < args.length) {
@@ -9284,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;
@@ -9325,14 +9415,16 @@ public final class ActivityManagerService extends ActivityManagerNative
long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
final int[] oomAdj = new int[] {
- ProcessList.SYSTEM_ADJ, ProcessList.CORE_SERVER_ADJ, ProcessList.FOREGROUND_APP_ADJ,
+ ProcessList.SYSTEM_ADJ, ProcessList.PERSISTENT_PROC_ADJ, ProcessList.FOREGROUND_APP_ADJ,
ProcessList.VISIBLE_APP_ADJ, ProcessList.PERCEPTIBLE_APP_ADJ, ProcessList.HEAVY_WEIGHT_APP_ADJ,
- ProcessList.BACKUP_APP_ADJ, ProcessList.SECONDARY_SERVER_ADJ, ProcessList.HOME_APP_ADJ, ProcessList.EMPTY_APP_ADJ
+ ProcessList.BACKUP_APP_ADJ, ProcessList.SERVICE_ADJ, ProcessList.HOME_APP_ADJ,
+ ProcessList.PREVIOUS_APP_ADJ, ProcessList.SERVICE_B_ADJ, ProcessList.HIDDEN_APP_MAX_ADJ
};
final String[] oomLabel = new String[] {
"System", "Persistent", "Foreground",
"Visible", "Perceptible", "Heavy Weight",
- "Backup", "Services", "Home", "Background"
+ "Backup", "A Services", "Home", "Previous",
+ "B Services", "Background"
};
long oomPss[] = new long[oomLabel.length];
ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])new ArrayList[oomLabel.length];
@@ -9410,7 +9502,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- if (!brief) {
+ if (!brief && !oomOnly) {
pw.println();
pw.println("Total PSS by process:");
dumpMemItems(pw, " ", procMems, true);
@@ -9418,10 +9510,11 @@ public final class ActivityManagerService extends ActivityManagerNative
}
pw.println("Total PSS by OOM adjustment:");
dumpMemItems(pw, " ", oomMems, false);
- if (!brief) {
- 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");
@@ -9758,7 +9851,10 @@ public final class ActivityManagerService extends ActivityManagerNative
if (app == mHomeProcess) {
mHomeProcess = null;
}
-
+ if (app == mPreviousProcess) {
+ mPreviousProcess = null;
+ }
+
if (restart) {
// We have components that still need to be running in the
// process, so re-launch it.
@@ -12991,7 +13087,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// =========================================================
private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
- ProcessRecord TOP_APP, boolean recursed) {
+ ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
if (mAdjSeq == app.adjSeq) {
// This adjustment has already been computed. If we are calling
// from the top, we may have already computed our adjustment with
@@ -13006,7 +13102,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (app.thread == null) {
app.adjSeq = mAdjSeq;
app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
- return (app.curAdj=ProcessList.EMPTY_APP_ADJ);
+ return (app.curAdj=ProcessList.HIDDEN_APP_MAX_ADJ);
}
app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
@@ -13156,6 +13252,17 @@ public final class ActivityManagerService extends ActivityManagerNative
app.adjType = "home";
}
+ if (adj > ProcessList.PREVIOUS_APP_ADJ && app == mPreviousProcess
+ && app.activities.size() > 0) {
+ // This was the previous process that showed UI to the user.
+ // We want to try to keep it around more aggressively, to give
+ // a good experience around switching between two apps.
+ adj = ProcessList.PREVIOUS_APP_ADJ;
+ schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
+ app.hidden = false;
+ app.adjType = "previous";
+ }
+
if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj
+ " reason=" + app.adjType);
@@ -13190,7 +13297,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// go to the LRU list because it may be pretty heavy with
// UI stuff. We'll tag it with a label just to help
// debug and understand what is going on.
- if (adj > ProcessList.SECONDARY_SERVER_ADJ) {
+ if (adj > ProcessList.SERVICE_ADJ) {
app.adjType = "started-bg-ui-services";
}
} else {
@@ -13198,8 +13305,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// This service has seen some activity within
// recent memory, so we will keep its process ahead
// of the background processes.
- if (adj > ProcessList.SECONDARY_SERVER_ADJ) {
- adj = ProcessList.SECONDARY_SERVER_ADJ;
+ if (adj > ProcessList.SERVICE_ADJ) {
+ adj = ProcessList.SERVICE_ADJ;
app.adjType = "started-services";
app.hidden = false;
}
@@ -13207,7 +13314,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// If we have let the service slide into the background
// state, still have some text describing what it is doing
// even though the service no longer has an impact.
- if (adj > ProcessList.SECONDARY_SERVER_ADJ) {
+ if (adj > ProcessList.SERVICE_ADJ) {
app.adjType = "started-bg-services";
}
}
@@ -13241,7 +13348,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
clientAdj = computeOomAdjLocked(
- client, myHiddenAdj, TOP_APP, true);
+ client, myHiddenAdj, TOP_APP, true, doingAll);
String adjType = null;
if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {
// Not doing bind OOM management, so treat
@@ -13285,10 +13392,17 @@ public final class ActivityManagerService extends ActivityManagerNative
if ((cr.flags&(Context.BIND_ABOVE_CLIENT
|Context.BIND_IMPORTANT)) != 0) {
adj = clientAdj;
- } else if (clientAdj >= ProcessList.VISIBLE_APP_ADJ) {
+ } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0
+ && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ
+ && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
+ adj = ProcessList.PERCEPTIBLE_APP_ADJ;
+ } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {
adj = clientAdj;
} else {
- adj = ProcessList.VISIBLE_APP_ADJ;
+ app.pendingUiClean = true;
+ if (adj > ProcessList.VISIBLE_APP_ADJ) {
+ adj = ProcessList.VISIBLE_APP_ADJ;
+ }
}
if (!client.hidden) {
app.hidden = false;
@@ -13371,7 +13485,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
int clientAdj = computeOomAdjLocked(
- client, myHiddenAdj, TOP_APP, true);
+ client, myHiddenAdj, TOP_APP, true, doingAll);
if (adj > clientAdj) {
if (app.hasShownUi && app != mHomeProcess
&& clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
@@ -13442,11 +13556,23 @@ public final class ActivityManagerService extends ActivityManagerNative
adj = ProcessList.PERCEPTIBLE_APP_ADJ;
} else if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
adj = ProcessList.HIDDEN_APP_MIN_ADJ;
- } else if (adj < ProcessList.EMPTY_APP_ADJ) {
+ } else if (adj < ProcessList.HIDDEN_APP_MAX_ADJ) {
adj++;
}
}
+ if (adj == ProcessList.SERVICE_ADJ) {
+ if (doingAll) {
+ app.serviceb = mNewNumServiceProcs > (mNumServiceProcs/3);
+ mNewNumServiceProcs++;
+ }
+ if (app.serviceb) {
+ adj = ProcessList.SERVICE_B_ADJ;
+ }
+ } else {
+ app.serviceb = false;
+ }
+
app.curAdj = adj;
app.curSchedGroup = schedGroup;
@@ -13687,7 +13813,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private final boolean updateOomAdjLocked(
- ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) {
+ ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP, boolean doingAll) {
app.hiddenAdj = hiddenAdj;
if (app.thread == null) {
@@ -13698,7 +13824,7 @@ public final class ActivityManagerService extends ActivityManagerNative
boolean success = true;
- computeOomAdjLocked(app, hiddenAdj, TOP_APP, false);
+ computeOomAdjLocked(app, hiddenAdj, TOP_APP, false, doingAll);
if (app.curRawAdj != app.setRawAdj) {
if (false) {
@@ -13732,11 +13858,12 @@ public final class ActivityManagerService extends ActivityManagerNative
app.setRawAdj = app.curRawAdj;
}
+
if (app.curAdj != app.setAdj) {
if (Process.setOomAdj(app.pid, app.curAdj)) {
- if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
- TAG, "Set app " + app.processName +
- " oom adj to " + app.curAdj + " because " + app.adjType);
+ if (true || DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
+ TAG, "Set " + app.pid + " " + app.processName +
+ " adj " + app.curAdj + ": " + app.adjType);
app.setAdj = app.curAdj;
} else {
success = false;
@@ -13800,7 +13927,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mAdjSeq++;
- boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP);
+ boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP, false);
final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ
&& app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ;
if (nowHidden != wasHidden) {
@@ -13822,6 +13949,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
mAdjSeq++;
+ mNewNumServiceProcs = 0;
// Let's determine how many processes we have running vs.
// how many slots we have for background processes; we may want
@@ -13842,8 +13970,8 @@ public final class ActivityManagerService extends ActivityManagerNative
i--;
ProcessRecord app = mLruProcesses.get(i);
//Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
- updateOomAdjLocked(app, curHiddenAdj, TOP_APP);
- if (curHiddenAdj < ProcessList.EMPTY_APP_ADJ
+ updateOomAdjLocked(app, curHiddenAdj, TOP_APP, true);
+ if (curHiddenAdj < ProcessList.HIDDEN_APP_MAX_ADJ
&& app.curAdj == curHiddenAdj) {
step++;
if (step >= factor) {
@@ -13864,12 +13992,15 @@ public final class ActivityManagerService extends ActivityManagerNative
} else {
numBg++;
}
- } else if (app.curAdj >= ProcessList.HOME_APP_ADJ) {
+ } else if (app.curAdj >= ProcessList.HOME_APP_ADJ
+ && app.curAdj != ProcessList.SERVICE_B_ADJ) {
numBg++;
}
}
}
+ mNumServiceProcs = mNewNumServiceProcs;
+
// Now determine the memory trimming level of background processes.
// Unfortunately we need to start at the back of the list to do this
// properly. We only do this if the number of background apps we
@@ -13892,7 +14023,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
// For these apps we will also finish their activities
// to help them free memory.
- mMainStack.destroyActivitiesLocked(app, false);
+ mMainStack.destroyActivitiesLocked(app, false, "trim");
}
}
app.trimMemoryLevel = curLevel;
@@ -13956,7 +14087,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (mAlwaysFinishActivities) {
- mMainStack.destroyActivitiesLocked(null, false);
+ mMainStack.destroyActivitiesLocked(null, false, "always-finish");
}
}
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index ce45bfb..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,18 +579,18 @@ 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);
}
}
- public void windowsVisible() {
+ public void windowsDrawn() {
synchronized(service) {
if (launchTime != 0) {
final long curTime = SystemClock.uptimeMillis();
@@ -555,6 +622,11 @@ final class ActivityRecord extends IApplicationToken.Stub {
stack.mInitialStartTime = 0;
}
startTime = 0;
+ }
+ }
+
+ public void windowsVisible() {
+ synchronized(service) {
stack.reportActivityVisibleLocked(this);
if (ActivityManagerService.DEBUG_SWITCH) Log.v(
ActivityManagerService.TAG, "windowsVisible(): " + this);
@@ -682,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 28c3bae..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);
}
@@ -947,7 +946,7 @@ final class ActivityStack {
r.state = ActivityState.STOPPED;
if (!r.finishing) {
if (r.configDestroy) {
- destroyActivityLocked(r, true, false);
+ destroyActivityLocked(r, true, false, "stop-config");
resumeTopActivityLocked(null);
}
}
@@ -976,7 +975,7 @@ final class ActivityStack {
// instance right now, we need to first completely stop
// the current instance before starting the new one.
if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
- destroyActivityLocked(prev, true, false);
+ destroyActivityLocked(prev, true, false, "pause-config");
} else {
mStoppingActivities.add(prev);
if (mStoppingActivities.size() > 3) {
@@ -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)
@@ -1363,6 +1362,14 @@ final class ActivityStack {
+ ", nowVisible=" + next.nowVisible);
}
}
+
+ if (!prev.finishing && prev.app != null && prev.app != next.app
+ && prev.app != mService.mHomeProcess) {
+ // We are switching to a new activity that is in a different
+ // process than the previous one. Note the previous process,
+ // so we can try to keep it around.
+ mService.mPreviousProcess = prev.app;
+ }
}
// Launching this app's activity, make sure the app is no longer
@@ -1391,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);
@@ -1406,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,
@@ -1425,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;
@@ -1449,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;
}
@@ -1488,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,
@@ -1503,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();
@@ -1520,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,
@@ -1541,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;
}
@@ -1559,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,
@@ -1602,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;
}
@@ -1669,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
@@ -1697,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) {
@@ -1717,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.
@@ -1818,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;
}
@@ -1841,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++;
}
@@ -1977,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;
@@ -2073,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");
@@ -2999,7 +3016,7 @@ final class ActivityStack {
return res;
}
- resultTo = outActivity[0];
+ resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
}
}
} finally {
@@ -3057,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);
@@ -3072,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) {
@@ -3090,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);
}
@@ -3106,7 +3123,7 @@ final class ActivityStack {
if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
r.state = ActivityState.STOPPED;
if (r.configDestroy) {
- destroyActivityLocked(r, true, false);
+ destroyActivityLocked(r, true, false, "stop-except");
}
}
}
@@ -3137,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) {
@@ -3178,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) {
@@ -3281,7 +3298,7 @@ final class ActivityStack {
for (i=0; i<NF; i++) {
ActivityRecord r = (ActivityRecord)finishes.get(i);
synchronized (mService) {
- destroyActivityLocked(r, true, false);
+ destroyActivityLocked(r, true, false, "finish-idle");
}
}
@@ -3405,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);
@@ -3432,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;
}
@@ -3480,7 +3497,7 @@ final class ActivityStack {
|| prevState == ActivityState.INITIALIZING) {
// If this activity is already stopped, we can just finish
// it right now.
- return destroyActivityLocked(r, true, true) ? null : r;
+ return destroyActivityLocked(r, true, true, "finish-imm") ? null : r;
} else {
// Need to go through the full pause cycle to get this
// activity into the stopped state and then finish it.
@@ -3562,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();
@@ -3586,7 +3603,7 @@ final class ActivityStack {
}
}
- final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj) {
+ final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) {
for (int i=mHistory.size()-1; i>=0; i--) {
ActivityRecord r = mHistory.get(i);
if (owner != null && r.app != owner) {
@@ -3597,7 +3614,7 @@ final class ActivityStack {
if (r.app != null && r.haveState && !r.visible && r.stopped && !r.finishing
&& r.state != ActivityState.DESTROYING
&& r.state != ActivityState.DESTROYED) {
- destroyActivityLocked(r, true, oomAdj);
+ destroyActivityLocked(r, true, oomAdj, "trim");
}
}
}
@@ -3609,13 +3626,13 @@ final class ActivityStack {
* but then create a new client-side object for this same HistoryRecord.
*/
final boolean destroyActivityLocked(ActivityRecord r,
- boolean removeFromApp, boolean oomAdj) {
+ boolean removeFromApp, boolean oomAdj, String reason) {
if (DEBUG_SWITCH) Slog.v(
TAG, "Removing activity: token=" + r
+ ", app=" + (r.app != null ? r.app.processName : "(null)"));
EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
System.identityHashCode(r),
- r.task.taskId, r.shortComponentName);
+ r.task.taskId, r.shortComponentName, reason);
boolean removedFromHistory = false;
@@ -3645,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
@@ -3704,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);
@@ -3773,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.
@@ -3795,7 +3814,7 @@ final class ActivityStack {
}
mHistory.remove(pos);
mHistory.add(top, r);
- moved.add(0, r);
+ moved.add(0, r.appToken);
top--;
}
pos--;
@@ -3818,7 +3837,7 @@ final class ActivityStack {
mService.mWindowManager.moveAppTokensToTop(moved);
if (VALIDATE_TOKENS) {
- mService.mWindowManager.validateAppTokens(mHistory);
+ validateAppTokensLocked();
}
finishTaskMoveLocked(task);
@@ -3865,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);
@@ -3890,7 +3909,7 @@ final class ActivityStack {
}
mHistory.remove(pos);
mHistory.add(bottom, r);
- moved.add(r);
+ moved.add(r.appToken);
bottom++;
}
pos++;
@@ -3910,7 +3929,7 @@ final class ActivityStack {
}
mService.mWindowManager.moveAppTokensToBottom(moved);
if (VALIDATE_TOKENS) {
- mService.mWindowManager.validateAppTokens(mHistory);
+ validateAppTokensLocked();
}
finishTaskMoveLocked(task);
@@ -4102,7 +4121,7 @@ final class ActivityStack {
if (r.app == null || r.app.thread == null) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
"Switch is destroying non-running " + r);
- destroyActivityLocked(r, true, false);
+ destroyActivityLocked(r, true, false, "config");
} else if (r.state == ActivityState.PAUSING) {
// A little annoying: we are waiting for this activity to
// finish pausing. Let's not do anything now, but just
@@ -4140,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.
}
@@ -4170,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/am/EventLogTags.logtags b/services/java/com/android/server/am/EventLogTags.logtags
index aadd37d..a579f44 100644
--- a/services/java/com/android/server/am/EventLogTags.logtags
+++ b/services/java/com/android/server/am/EventLogTags.logtags
@@ -48,7 +48,7 @@ option java_package com.android.server.am
# Reporting to applications that memory is low
30017 am_low_memory (Num Processes|1|1)
# An activity is being destroyed:
-30018 am_destroy_activity (Token|1|5),(Task ID|1|5),(Component Name|3)
+30018 am_destroy_activity (Token|1|5),(Task ID|1|5),(Component Name|3),(Reason|3)
# An activity has been relaunched, resumed, and is now in the foreground:
30019 am_relaunch_resume_activity (Token|1|5),(Task ID|1|5),(Component Name|3)
# An activity has been relaunched:
diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java
index 131255f..af7b314 100644
--- a/services/java/com/android/server/am/ProcessList.java
+++ b/services/java/com/android/server/am/ProcessList.java
@@ -16,7 +16,6 @@
package com.android.server.am;
-import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -24,7 +23,6 @@ import com.android.internal.util.MemInfoReader;
import com.android.server.wm.WindowManagerService;
import android.graphics.Point;
-import android.os.StrictMode;
import android.util.Slog;
/**
@@ -37,27 +35,31 @@ class ProcessList {
// OOM adjustments for processes in various states:
- // This is a process without anything currently running in it. Definitely
- // the first to go! Value set in system/rootdir/init.rc on startup.
- // This value is initalized in the constructor, careful when refering to
- // this static variable externally.
- static final int EMPTY_APP_ADJ = 15;
-
// This is a process only hosting activities that are not visible,
- // so it can be killed without any disruption. Value set in
- // system/rootdir/init.rc on startup.
+ // so it can be killed without any disruption.
static final int HIDDEN_APP_MAX_ADJ = 15;
- static int HIDDEN_APP_MIN_ADJ = 7;
+ static int HIDDEN_APP_MIN_ADJ = 9;
+
+ // The B list of SERVICE_ADJ -- these are the old and decrepit
+ // services that aren't as shiny and interesting as the ones in the A list.
+ static final int SERVICE_B_ADJ = 8;
+
+ // This is the process of the previous application that the user was in.
+ // This process is kept above other things, because it is very common to
+ // switch back to the previous app. This is important both for recent
+ // task switch (toggling between the two top recent apps) as well as normal
+ // UI flow such as clicking on a URI in the e-mail app to view in the browser,
+ // and then pressing back to return to e-mail.
+ static final int PREVIOUS_APP_ADJ = 7;
// This is a process holding the home application -- we want to try
// avoiding killing it, even if it would normally be in the background,
// because the user interacts with it so much.
static final int HOME_APP_ADJ = 6;
- // This is a process holding a secondary server -- killing it will not
- // have much of an impact as far as the user is concerned. Value set in
- // system/rootdir/init.rc on startup.
- static final int SECONDARY_SERVER_ADJ = 5;
+ // This is a process holding an application service -- killing it will not
+ // have much of an impact as far as the user is concerned.
+ static final int SERVICE_ADJ = 5;
// This is a process currently hosting a backup operation. Killing it
// is not entirely fatal but is generally a bad idea.
@@ -70,22 +72,20 @@ class ProcessList {
// This is a process only hosting components that are perceptible to the
// user, and we really want to avoid killing them, but they are not
- // immediately visible. An example is background music playback. Value set in
- // system/rootdir/init.rc on startup.
+ // immediately visible. An example is background music playback.
static final int PERCEPTIBLE_APP_ADJ = 2;
// This is a process only hosting activities that are visible to the
- // user, so we'd prefer they don't disappear. Value set in
- // system/rootdir/init.rc on startup.
+ // user, so we'd prefer they don't disappear.
static final int VISIBLE_APP_ADJ = 1;
// This is the process running the current foreground app. We'd really
- // rather not kill it! Value set in system/rootdir/init.rc on startup.
+ // rather not kill it!
static final int FOREGROUND_APP_ADJ = 0;
- // This is a process running a core server, such as telephony. Definitely
+ // This is a system persistent process, such as telephony. Definitely
// don't want to kill it, but doing so is not completely fatal.
- static final int CORE_SERVER_ADJ = -12;
+ static final int PERSISTENT_PROC_ADJ = -12;
// The system process runs at the default adjustment.
static final int SYSTEM_ADJ = -16;
@@ -115,7 +115,7 @@ class ProcessList {
// can't give it a different value for every possible kind of process.
private final int[] mOomAdj = new int[] {
FOREGROUND_APP_ADJ, VISIBLE_APP_ADJ, PERCEPTIBLE_APP_ADJ,
- BACKUP_APP_ADJ, HIDDEN_APP_MIN_ADJ, EMPTY_APP_ADJ
+ BACKUP_APP_ADJ, HIDDEN_APP_MIN_ADJ, HIDDEN_APP_MAX_ADJ
};
// These are the low-end OOM level limits. This is appropriate for an
// HVGA or smaller phone with less than 512MB. Values are in KB.
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 9392bb4..72292be 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -63,6 +63,7 @@ class ProcessRecord {
int curSchedGroup; // Currently desired scheduling class
int setSchedGroup; // Last set to background scheduling class
int trimMemoryLevel; // Last selected memory trimming level
+ boolean serviceb; // Process currently is on the service B list
boolean keeping; // Actively running code so don't kill due to that?
boolean setIsForeground; // Running foreground UI when last set?
boolean foregroundServices; // Running any services that are foreground?
@@ -179,6 +180,7 @@ class ProcessRecord {
pw.print(prefix); pw.print("lastActivityTime=");
TimeUtils.formatDuration(lastActivityTime, now, pw);
pw.print(" lruWeight="); pw.print(lruWeight);
+ pw.print(" serviceb="); pw.print(serviceb);
pw.print(" keeping="); pw.print(keeping);
pw.print(" hidden="); pw.print(hidden);
pw.print(" empty="); pw.println(empty);
@@ -271,7 +273,7 @@ class ProcessRecord {
processName = _processName;
pkgList.add(_info.packageName);
thread = _thread;
- maxAdj = ProcessList.EMPTY_APP_ADJ;
+ maxAdj = ProcessList.HIDDEN_APP_MAX_ADJ;
hiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
curRawAdj = setRawAdj = -100;
curAdj = setAdj = -100;
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index 423a78f..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;
@@ -228,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);
@@ -298,7 +298,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
mIfaces.put(iface, sm);
sm.start();
}
- if (VDBG) Log.d(TAG, "interfaceAdded :" + iface);
}
public void interfaceRemoved(String iface) {
@@ -415,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());
}
@@ -865,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:
@@ -906,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?
@@ -985,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) {
@@ -1061,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)) {
@@ -1296,7 +1295,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
}
}
- if (VDBG) {
+ if (DBG) {
Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
+ mPreferredUpstreamMobileApn + ", got type=" + upType);
}
@@ -1328,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;
@@ -1344,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:
@@ -1386,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:
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index bdad82a..2a1b1db 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -19,7 +19,6 @@ package com.android.server.net;
import static android.Manifest.permission.ACCESS_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.DUMP;
-import static android.Manifest.permission.MANAGE_APP_TOKENS;
import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.Manifest.permission.READ_PHONE_STATE;
@@ -93,6 +92,7 @@ import android.os.HandlerThread;
import android.os.INetworkManagementService;
import android.os.IPowerManager;
import android.os.Message;
+import android.os.MessageQueue.IdleHandler;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.provider.Settings;
@@ -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
}
}
@@ -1583,6 +1582,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return intent;
}
+ // @VisibleForTesting
+ public void addIdleHandler(IdleHandler handler) {
+ mHandler.getLooper().getQueue().addIdleHandler(handler);
+ }
+
private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
final int size = source.size();
for (int i = 0; i < size; i++) {
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 789681e..6365525 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -32,7 +32,6 @@ import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.SET_FOREGROUND;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
-import static android.net.NetworkStatsHistory.randomLong;
import static android.net.NetworkTemplate.buildTemplateMobileAll;
import static android.net.NetworkTemplate.buildTemplateWifi;
import static android.net.TrafficStats.UID_REMOVED;
@@ -49,7 +48,6 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
-import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
@@ -73,9 +71,11 @@ import android.net.NetworkIdentity;
import android.net.NetworkInfo;
import android.net.NetworkState;
import android.net.NetworkStats;
+import android.net.NetworkStats.NonMonotonicException;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.os.Binder;
+import android.os.DropBoxManager;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
@@ -150,6 +150,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
/** Sample recent usage after each poll event. */
private static final boolean ENABLE_SAMPLE_AFTER_POLL = true;
+ private static final String TAG_NETSTATS_ERROR = "netstats_error";
+
private final Context mContext;
private final INetworkManagementService mNetworkManager;
private final IAlarmManager mAlarmManager;
@@ -160,6 +162,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private final PowerManager.WakeLock mWakeLock;
private IConnectivityManager mConnManager;
+ private DropBoxManager mDropBox;
// @VisibleForTesting
public static final String ACTION_NETWORK_STATS_POLL =
@@ -271,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);
@@ -304,8 +310,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
registerPollAlarmLocked();
registerGlobalAlert();
- // bootstrap initial stats to prevent double-counting later
- bootstrapStats();
+ mDropBox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
}
private void shutdownLocked() {
@@ -621,7 +626,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// broadcast.
final int uid = intent.getIntExtra(EXTRA_UID, 0);
synchronized (mStatsLock) {
- // TODO: perform one last stats poll for UID
mWakeLock.acquire();
try {
removeUidLocked(uid);
@@ -802,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);
@@ -829,9 +831,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// persist when enough network data has occurred
final long persistNetworkDevDelta = computeStatsDelta(
- mLastPersistNetworkDevSnapshot, networkDevSnapshot, true).getTotalBytes();
+ mLastPersistNetworkDevSnapshot, networkDevSnapshot, true, "devp").getTotalBytes();
final long persistNetworkXtDelta = computeStatsDelta(
- mLastPersistNetworkXtSnapshot, networkXtSnapshot, true).getTotalBytes();
+ mLastPersistNetworkXtSnapshot, networkXtSnapshot, true, "xtp").getTotalBytes();
final boolean networkOverThreshold = persistNetworkDevDelta > threshold
|| persistNetworkXtDelta > threshold;
if (persistForce || (persistNetwork && networkOverThreshold)) {
@@ -842,8 +844,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
// persist when enough uid data has occurred
- final long persistUidDelta = computeStatsDelta(mLastPersistUidSnapshot, uidSnapshot, true)
- .getTotalBytes();
+ final long persistUidDelta = computeStatsDelta(
+ mLastPersistUidSnapshot, uidSnapshot, true, "uidp").getTotalBytes();
if (persistForce || (persistUid && persistUidDelta > threshold)) {
writeUidStatsLocked();
mLastPersistUidSnapshot = uidSnapshot;
@@ -872,7 +874,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final HashSet<String> unknownIface = Sets.newHashSet();
final NetworkStats delta = computeStatsDelta(
- mLastPollNetworkDevSnapshot, networkDevSnapshot, false);
+ mLastPollNetworkDevSnapshot, networkDevSnapshot, false, "dev");
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
@@ -902,7 +904,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final HashSet<String> unknownIface = Sets.newHashSet();
final NetworkStats delta = computeStatsDelta(
- mLastPollNetworkXtSnapshot, networkXtSnapshot, false);
+ mLastPollNetworkXtSnapshot, networkXtSnapshot, false, "xt");
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
@@ -931,9 +933,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private void performUidPollLocked(NetworkStats uidSnapshot, long currentTime) {
ensureUidStatsLoadedLocked();
- final NetworkStats delta = computeStatsDelta(mLastPollUidSnapshot, uidSnapshot, false);
+ final NetworkStats delta = computeStatsDelta(
+ mLastPollUidSnapshot, uidSnapshot, false, "uid");
final NetworkStats operationsDelta = computeStatsDelta(
- mLastPollOperationsSnapshot, mOperations, false);
+ mLastPollOperationsSnapshot, mOperations, false, "uidop");
final long timeStart = currentTime - delta.getElapsedRealtime();
NetworkStats.Entry entry = null;
@@ -962,8 +965,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
mLastPollUidSnapshot = uidSnapshot;
- mLastPollOperationsSnapshot = mOperations;
- mOperations = new NetworkStats(0L, 10);
+ mLastPollOperationsSnapshot = mOperations.clone();
}
/**
@@ -1014,6 +1016,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private void removeUidLocked(int uid) {
ensureUidStatsLoadedLocked();
+ // perform one last poll before removing
+ performPollLocked(FLAG_PERSIST_ALL);
+
final ArrayList<UidStatsKey> knownKeys = Lists.newArrayList();
knownKeys.addAll(mUidStats.keySet());
@@ -1031,6 +1036,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
}
+ // clear UID from current stats snapshot
+ mLastPollUidSnapshot = mLastPollUidSnapshot.withoutUid(uid);
+ mLastPollNetworkXtSnapshot = computeNetworkXtSnapshotFromUid(mLastPollUidSnapshot);
+
// clear kernel stats associated with UID
resetKernelUidStats(uid);
@@ -1490,10 +1499,30 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
* Return the delta between two {@link NetworkStats} snapshots, where {@code
* before} can be {@code null}.
*/
- private static NetworkStats computeStatsDelta(
- NetworkStats before, NetworkStats current, boolean collectStale) {
+ private NetworkStats computeStatsDelta(
+ NetworkStats before, NetworkStats current, boolean collectStale, String type) {
if (before != null) {
- return current.subtractClamped(before);
+ try {
+ 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
+ + "] - 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());
+
+ 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.
return current;
@@ -1504,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/AppWindowToken.java b/services/java/com/android/server/wm/AppWindowToken.java
index 61c96bb..0e3d20a 100644
--- a/services/java/com/android/server/wm/AppWindowToken.java
+++ b/services/java/com/android/server/wm/AppWindowToken.java
@@ -77,6 +77,9 @@ class AppWindowToken extends WindowToken {
// Last visibility state we reported to the app token.
boolean reportedVisible;
+ // Last drawn state we reported to the app token.
+ boolean reportedDrawn;
+
// Set to true when the token has been removed from the window mgr.
boolean removed;
@@ -277,6 +280,7 @@ class AppWindowToken extends WindowToken {
int numInteresting = 0;
int numVisible = 0;
+ int numDrawn = 0;
boolean nowGone = true;
if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Update reported visibility: " + this);
@@ -307,6 +311,7 @@ class AppWindowToken extends WindowToken {
}
numInteresting++;
if (win.isDrawnLw()) {
+ numDrawn++;
if (!win.isAnimating()) {
numVisible++;
}
@@ -316,9 +321,27 @@ class AppWindowToken extends WindowToken {
}
}
+ boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting;
+ if (!nowGone) {
+ // If the app is not yet gone, then it can only become visible/drawn.
+ if (!nowDrawn) {
+ nowDrawn = reportedDrawn;
+ }
+ if (!nowVisible) {
+ nowVisible = reportedVisible;
+ }
+ }
if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "VIS " + this + ": interesting="
+ numInteresting + " visible=" + numVisible);
+ if (nowDrawn != reportedDrawn) {
+ if (nowDrawn) {
+ Message m = service.mH.obtainMessage(
+ H.REPORT_APPLICATION_TOKEN_DRAWN, this);
+ service.mH.sendMessage(m);
+ }
+ reportedDrawn = nowDrawn;
+ }
if (nowVisible != reportedVisible) {
if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(
WindowManagerService.TAG, "Visibility changed in " + this
@@ -360,6 +383,7 @@ class AppWindowToken extends WindowToken {
pw.print(prefix); pw.print("hiddenRequested="); pw.print(hiddenRequested);
pw.print(" clientHidden="); pw.print(clientHidden);
pw.print(" willBeHidden="); pw.print(willBeHidden);
+ pw.print(" reportedDrawn="); pw.print(reportedDrawn);
pw.print(" reportedVisible="); pw.println(reportedVisible);
if (paused || freezingScreen) {
pw.print(prefix); pw.print("paused="); pw.print(paused);
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/Session.java b/services/java/com/android/server/wm/Session.java
index 03b7546..ee62a56 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -306,7 +306,15 @@ final class Session extends IWindowSession.Stub
synchronized (mService.mWindowMap) {
long ident = Binder.clearCallingIdentity();
try {
- if (mService.mDragState == null || mService.mDragState.mToken != token) {
+ if (mService.mDragState == null) {
+ // Most likely the drop recipient ANRed and we ended the drag
+ // out from under it. Log the issue and move on.
+ Slog.w(WindowManagerService.TAG, "Drop result given but no drag in progress");
+ return;
+ }
+
+ if (mService.mDragState.mToken != token) {
+ // We're in a drag, but the wrong window has responded.
Slog.w(WindowManagerService.TAG, "Invalid drop-result claim by " + window);
throw new IllegalStateException("reportDropResult() by non-recipient");
}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 122d515..50321b3 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -1836,7 +1836,8 @@ public class WindowManagerService extends IWindowManager.Stub
rawChanged = true;
}
- if (rawChanged) {
+ if (rawChanged && (wallpaperWin.getAttrs().privateFlags &
+ WindowManager.LayoutParams.PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS) != 0) {
try {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Report new wp offset "
+ wallpaperWin + " x=" + wallpaperWin.mWallpaperX
@@ -1886,12 +1887,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- boolean updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
+ void updateWallpaperOffsetLocked(WindowState changingTarget, boolean sync) {
final int dw = mAppDisplayWidth;
final int dh = mAppDisplayHeight;
- boolean changed = false;
-
WindowState target = mWallpaperTarget;
if (target != null) {
if (target.mWallpaperX >= 0) {
@@ -1916,14 +1915,31 @@ public class WindowManagerService extends IWindowManager.Stub
WindowState wallpaper = token.windows.get(curWallpaperIndex);
if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
wallpaper.computeShownFrameLocked();
- changed = true;
+ // No need to lay out the windows - we can just set the wallpaper position
+ // directly.
+ if (wallpaper.mSurfaceX != wallpaper.mShownFrame.left
+ || wallpaper.mSurfaceY != wallpaper.mShownFrame.top) {
+ Surface.openTransaction();
+ try {
+ if (SHOW_TRANSACTIONS) logSurface(wallpaper,
+ "POS " + wallpaper.mShownFrame.left
+ + ", " + wallpaper.mShownFrame.top, null);
+ wallpaper.mSurfaceX = wallpaper.mShownFrame.left;
+ wallpaper.mSurfaceY = wallpaper.mShownFrame.top;
+ wallpaper.mSurface.setPosition(wallpaper.mShownFrame.left,
+ wallpaper.mShownFrame.top);
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error positioning surface of " + wallpaper
+ + " pos=(" + wallpaper.mShownFrame.left
+ + "," + wallpaper.mShownFrame.top + ")", e);
+ }
+ Surface.closeTransaction();
+ }
// We only want to be synchronous with one wallpaper.
sync = false;
}
}
}
-
- return changed;
}
void updateWallpaperVisibilityLocked() {
@@ -2436,9 +2452,7 @@ public class WindowManagerService extends IWindowManager.Stub
window.mWallpaperY = y;
window.mWallpaperXStep = xStep;
window.mWallpaperYStep = yStep;
- if (updateWallpaperOffsetLocked(window, true)) {
- performLayoutAndPlaceSurfacesLocked();
- }
+ updateWallpaperOffsetLocked(window, true);
}
}
@@ -2578,11 +2592,7 @@ public class WindowManagerService extends IWindowManager.Stub
(win.mAppToken == null || !win.mAppToken.clientHidden)) {
displayed = !win.isVisibleLw();
if (win.mExiting) {
- win.mExiting = false;
- if (win.mAnimation != null) {
- win.mAnimation.cancel();
- win.mAnimation = null;
- }
+ win.cancelExitAnimationForNextAnimationLocked();
}
if (win.mDestroying) {
win.mDestroying = false;
@@ -3060,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) {
@@ -5799,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
@@ -5816,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,
@@ -5914,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) {
@@ -6376,6 +6421,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int REMOVE_STARTING = 6;
public static final int FINISHED_STARTING = 7;
public static final int REPORT_APPLICATION_TOKEN_WINDOWS = 8;
+ public static final int REPORT_APPLICATION_TOKEN_DRAWN = 9;
public static final int WINDOW_FREEZE_TIMEOUT = 11;
public static final int HOLD_SCREEN_CHANGED = 12;
public static final int APP_TRANSITION_TIMEOUT = 13;
@@ -6589,6 +6635,17 @@ public class WindowManagerService extends IWindowManager.Stub
}
} break;
+ case REPORT_APPLICATION_TOKEN_DRAWN: {
+ final AppWindowToken wtoken = (AppWindowToken)msg.obj;
+
+ try {
+ if (DEBUG_VISIBILITY) Slog.v(
+ TAG, "Reporting drawn in " + wtoken);
+ wtoken.appToken.windowsDrawn();
+ } catch (RemoteException ex) {
+ }
+ } break;
+
case REPORT_APPLICATION_TOKEN_WINDOWS: {
final AppWindowToken wtoken = (AppWindowToken)msg.obj;
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index e9875a5..23ec2d9 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -596,11 +596,24 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
}
+ // TODO: Fix and call finishExit() instead of cancelExitAnimationForNextAnimationLocked()
+ // for avoiding the code duplication.
+ void cancelExitAnimationForNextAnimationLocked() {
+ if (!mExiting) return;
+ if (mAnimation != null) {
+ mAnimation.cancel();
+ mAnimation = null;
+ destroySurfaceLocked();
+ }
+ mExiting = false;
+ }
+
Surface createSurfaceLocked() {
if (mSurface == null) {
mReportDestroySurface = false;
mSurfacePendingDestroy = false;
- Slog.i(WindowManagerService.TAG, "createSurface " + this + ": DRAW NOW PENDING");
+ if (WindowManagerService.DEBUG_ORIENTATION) Slog.i(WindowManagerService.TAG,
+ "createSurface " + this + ": DRAW NOW PENDING");
mDrawPending = true;
mCommitDrawPending = false;
mReadyToShow = false;
@@ -1745,4 +1758,4 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
return mStringNameCache;
}
-} \ No newline at end of file
+}