auto import from //depot/cupcake/@136594
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 4b45828..a254081 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -54,6 +54,7 @@
import android.os.Message;
import android.os.Parcel;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.Settings;
@@ -619,7 +620,7 @@
}
if (mShowRequested) {
if (DEBUG) Log.v(TAG, "Attach new input asks to show input");
- showCurrentInputLocked(getAppShowFlags());
+ showCurrentInputLocked(getAppShowFlags(), null);
}
return needResult
? new InputBindResult(session.session, mCurId, mCurSeq)
@@ -908,7 +909,8 @@
}
}
- public void showSoftInput(IInputMethodClient client, int flags) {
+ public boolean showSoftInput(IInputMethodClient client, int flags,
+ ResultReceiver resultReceiver) {
long ident = Binder.clearCallingIdentity();
try {
synchronized (mMethodMap) {
@@ -920,21 +922,22 @@
// be made before input is started in it.
if (!mIWindowManager.inputMethodClientHasFocus(client)) {
Log.w(TAG, "Ignoring showSoftInput of: " + client);
- return;
+ return false;
}
} catch (RemoteException e) {
+ return false;
}
}
if (DEBUG) Log.v(TAG, "Client requesting input be shown");
- showCurrentInputLocked(flags);
+ return showCurrentInputLocked(flags, resultReceiver);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
- void showCurrentInputLocked(int flags) {
+ boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
mShowRequested = true;
if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
mShowExplicitlyRequested = true;
@@ -943,10 +946,13 @@
mShowExplicitlyRequested = true;
mShowForced = true;
}
+ boolean res = false;
if (mCurMethod != null) {
- executeOrSendMessage(mCurMethod, mCaller.obtainMessageIO(
- MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod));
+ executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
+ MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
+ resultReceiver));
mInputShown = true;
+ res = true;
} else if (mHaveConnection && SystemClock.uptimeMillis()
< (mLastBindTime+TIME_TO_RECONNECT)) {
// The client has asked to have the input method shown, but
@@ -958,9 +964,12 @@
mContext.unbindService(this);
mContext.bindService(mCurIntent, this, Context.BIND_AUTO_CREATE);
}
+
+ return res;
}
- public void hideSoftInput(IInputMethodClient client, int flags) {
+ public boolean hideSoftInput(IInputMethodClient client, int flags,
+ ResultReceiver resultReceiver) {
long ident = Binder.clearCallingIdentity();
try {
synchronized (mMethodMap) {
@@ -972,40 +981,46 @@
// be made before input is started in it.
if (!mIWindowManager.inputMethodClientHasFocus(client)) {
Log.w(TAG, "Ignoring hideSoftInput of: " + client);
- return;
+ return false;
}
} catch (RemoteException e) {
+ return false;
}
}
if (DEBUG) Log.v(TAG, "Client requesting input be hidden");
- hideCurrentInputLocked(flags);
+ return hideCurrentInputLocked(flags, resultReceiver);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}
- void hideCurrentInputLocked(int flags) {
+ boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
&& (mShowExplicitlyRequested || mShowForced)) {
if (DEBUG) Log.v(TAG,
"Not hiding: explicit show not cancelled by non-explicit hide");
- return;
+ return false;
}
if (mShowForced && (flags&InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
if (DEBUG) Log.v(TAG,
"Not hiding: forced show not cancelled by not-always hide");
- return;
+ return false;
}
+ boolean res;
if (mInputShown && mCurMethod != null) {
- executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
- MSG_HIDE_SOFT_INPUT, mCurMethod));
+ executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
+ MSG_HIDE_SOFT_INPUT, mCurMethod, resultReceiver));
+ res = true;
+ } else {
+ res = false;
}
mInputShown = false;
mShowRequested = false;
mShowExplicitlyRequested = false;
mShowForced = false;
+ return res;
}
public void windowGainedFocus(IInputMethodClient client,
@@ -1045,7 +1060,7 @@
// be behind any soft input window, so hide the
// soft input window if it is shown.
if (DEBUG) Log.v(TAG, "Unspecified window will hide input");
- hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS);
+ hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null);
}
} else if (isTextEditor && (softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
@@ -1055,7 +1070,7 @@
// There is a focus view, and we are navigating forward
// into the window, so show the input window for the user.
if (DEBUG) Log.v(TAG, "Unspecified window will show input");
- showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
+ showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
}
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
@@ -1065,23 +1080,23 @@
if ((softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
if (DEBUG) Log.v(TAG, "Window asks to hide input going forward");
- hideCurrentInputLocked(0);
+ hideCurrentInputLocked(0, null);
}
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
if (DEBUG) Log.v(TAG, "Window asks to hide input");
- hideCurrentInputLocked(0);
+ hideCurrentInputLocked(0, null);
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
if ((softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
if (DEBUG) Log.v(TAG, "Window asks to show input going forward");
- showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
+ showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
}
break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
if (DEBUG) Log.v(TAG, "Window asks to always show input");
- showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT);
+ showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
break;
}
}
@@ -1131,10 +1146,24 @@
Log.w(TAG, "Ignoring hideInputMethod of token: " + token);
return;
}
-
long ident = Binder.clearCallingIdentity();
try {
- hideCurrentInputLocked(flags);
+ hideCurrentInputLocked(flags, null);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ }
+
+ public void showMySoftInput(IBinder token, int flags) {
+ synchronized (mMethodMap) {
+ if (token == null || mCurToken != token) {
+ Log.w(TAG, "Ignoring hideInputMethod of token: " + token);
+ return;
+ }
+ long ident = Binder.clearCallingIdentity();
+ try {
+ showCurrentInputLocked(flags, null);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -1185,14 +1214,18 @@
}
return true;
case MSG_SHOW_SOFT_INPUT:
+ args = (HandlerCaller.SomeArgs)msg.obj;
try {
- ((IInputMethod)msg.obj).showSoftInput(msg.arg1);
+ ((IInputMethod)args.arg1).showSoftInput(msg.arg1,
+ (ResultReceiver)args.arg2);
} catch (RemoteException e) {
}
return true;
case MSG_HIDE_SOFT_INPUT:
+ args = (HandlerCaller.SomeArgs)msg.obj;
try {
- ((IInputMethod)msg.obj).hideSoftInput();
+ ((IInputMethod)args.arg1).hideSoftInput(0,
+ (ResultReceiver)args.arg2);
} catch (RemoteException e) {
}
return true;
@@ -1212,7 +1245,6 @@
} catch (RemoteException e) {
}
return true;
-
// ---------------------------------------------------------
case MSG_START_INPUT:
@@ -1486,7 +1518,7 @@
}
}
}
-
+
// ----------------------------------------------------------------------
@Override
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 9d69114..e48e047 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -221,6 +221,9 @@
// Wifi Manager
private WifiManager mWifiManager;
+ private int mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
+ private boolean mWifiEnabled = false;
+
/**
* A wrapper class holding either an ILocationListener or a PendingIntent to receive
* location updates.
@@ -597,16 +600,6 @@
// Create a wifi lock for future use
mWifiLock = getWifiWakelockLocked();
-
- // There might be an existing wifi scan available
- if (mWifiManager != null) {
- List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
- if (wifiScanResults != null && wifiScanResults.size() != 0) {
- if (mNetworkLocationInterface != null) {
- mNetworkLocationInterface.updateWifiScanResults(wifiScanResults);
- }
- }
- }
}
public void setInstallCallback(InstallCallback callback) {
@@ -625,6 +618,31 @@
mNetworkLocationProvider = (LocationProviderImpl)provider;
LocationProviderImpl.addProvider(mNetworkLocationProvider);
updateProvidersLocked();
+
+ // notify NetworkLocationProvider of any events it might have missed
+ synchronized (mLocationListeners) {
+ mNetworkLocationProvider.updateNetworkState(mNetworkState);
+ mNetworkLocationInterface.updateWifiEnabledState(mWifiEnabled);
+ mNetworkLocationInterface.updateCellLockStatus(mCellWakeLockAcquired);
+
+ if (mLastCellState != null) {
+ if (mCollector != null) {
+ mCollector.updateCellState(mLastCellState);
+ }
+ mNetworkLocationProvider.updateCellState(mLastCellState);
+ }
+
+ // There might be an existing wifi scan available
+ if (mWifiManager != null) {
+ List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
+ if (wifiScanResults != null && wifiScanResults.size() != 0) {
+ mNetworkLocationInterface.updateWifiScanResults(wifiScanResults);
+ if (mCollector != null) {
+ mCollector.updateWifiScanResults(wifiScanResults);
+ }
+ }
+ }
+ }
}
}
@@ -1992,12 +2010,12 @@
}
} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
- int networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
-
boolean noConnectivity =
intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (!noConnectivity) {
- networkState = LocationProvider.AVAILABLE;
+ mNetworkState = LocationProvider.AVAILABLE;
+ } else {
+ mNetworkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
}
// Notify location providers of current network state
@@ -2005,7 +2023,7 @@
List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
for (LocationProviderImpl provider : providers) {
if (provider.requiresNetwork()) {
- provider.updateNetworkState(networkState);
+ provider.updateNetworkState(mNetworkState);
}
}
}
@@ -2014,11 +2032,10 @@
int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
WifiManager.WIFI_STATE_UNKNOWN);
- boolean enabled;
if (state == WifiManager.WIFI_STATE_ENABLED) {
- enabled = true;
+ mWifiEnabled = true;
} else if (state == WifiManager.WIFI_STATE_DISABLED) {
- enabled = false;
+ mWifiEnabled = false;
} else {
return;
}
@@ -2026,7 +2043,7 @@
// Notify network provider of current wifi enabled state
synchronized (mLocationListeners) {
if (mNetworkLocationInterface != null) {
- mNetworkLocationInterface.updateWifiEnabledState(enabled);
+ mNetworkLocationInterface.updateWifiEnabledState(mWifiEnabled);
}
}
diff --git a/services/java/com/android/server/SensorService.java b/services/java/com/android/server/SensorService.java
index 29b45ab..b2530383f 100644
--- a/services/java/com/android/server/SensorService.java
+++ b/services/java/com/android/server/SensorService.java
@@ -45,7 +45,7 @@
private static final int SENSOR_DISABLE = -1;
/**
- * Battery statistics to be updated when sensors are enabled and diabled.
+ * Battery statistics to be updated when sensors are enabled and disabled.
*/
final IBatteryStats mBatteryStats = BatteryStatsService.getService();
@@ -119,7 +119,10 @@
}
Binder.restoreCallingIdentity(identity);
- if (binder == null) throw new NullPointerException("listener is null in enableSensor");
+ if (binder == null) {
+ Log.w(TAG, "listener is null (sensor=" + name + ", id=" + sensor + ")");
+ return false;
+ }
synchronized(mListeners) {
if (enable!=SENSOR_DISABLE && !_sensors_control_activate(sensor, true)) {
@@ -145,7 +148,11 @@
}
if (l == null) {
- throw new NullPointerException("no Listener object in enableSensor");
+ // by construction, this means we're disabling a listener we
+ // don't know about...
+ Log.w(TAG, "listener with binder " + binder +
+ ", doesn't exist (sensor=" + name + ", id=" + sensor + ")");
+ return false;
}
if (minDelay >= 0) {
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 21e5ee1..cb16c98 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -2076,6 +2076,7 @@
int curGroup = 0;
int lastOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
boolean haveGroup = false;
+ boolean lastFullscreen = false;
while (pos >= 0) {
AppWindowToken wtoken = mAppTokens.get(pos);
pos--;
@@ -2090,16 +2091,19 @@
} else if (curGroup != wtoken.groupId) {
// If we have hit a new application group, and the bottom
// of the previous group didn't explicitly say to use
- // the orientation behind it, then we'll stick with the
+ // the orientation behind it, and the last app was
+ // full screen, then we'll stick with the
// user's orientation.
- if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND) {
+ if (lastOrientation != ActivityInfo.SCREEN_ORIENTATION_BEHIND
+ && lastFullscreen) {
return lastOrientation;
}
}
int or = wtoken.requestedOrientation;
// If this application is fullscreen, then just take whatever
// orientation it has and ignores whatever is under it.
- if (wtoken.appFullscreen) {
+ lastFullscreen = wtoken.appFullscreen;
+ if (lastFullscreen) {
return or;
}
// If this application has requested an explicit orientation,
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 141569e..2ede783 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -263,6 +263,11 @@
final int HIDDEN_APP_MAX_ADJ;
static int HIDDEN_APP_MIN_ADJ;
+ // 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.
+ final int HOME_APP_ADJ;
+
// 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.
@@ -290,6 +295,7 @@
// Corresponding memory levels for above adjustments.
final int EMPTY_APP_MEM;
final int HIDDEN_APP_MEM;
+ final int HOME_APP_MEM;
final int SECONDARY_SERVER_MEM;
final int VISIBLE_APP_MEM;
final int FOREGROUND_APP_MEM;
@@ -487,6 +493,12 @@
= new ArrayList<ProcessRecord>();
/**
+ * This is the process holding what we currently consider to be
+ * the "home" activity.
+ */
+ private ProcessRecord mHomeProcess;
+
+ /**
* List of running activities, sorted by recent usage.
* The first entry in the list is the least recently used.
* It contains HistoryRecord objects.
@@ -871,6 +883,11 @@
Log.e(TAG, "App already has anr dialog: " + proc);
return;
}
+
+ broadcastIntentLocked(null, null, new Intent("android.intent.action.ANR"),
+ null, null, 0, null, null, null,
+ false, false, MY_PID, Process.SYSTEM_UID);
+
Dialog d = new AppNotRespondingDialog(ActivityManagerService.this,
mContext, proc, (HistoryRecord)data.get("activity"));
d.show();
@@ -1267,6 +1284,8 @@
Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_ADJ"));
SECONDARY_SERVER_ADJ =
Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_ADJ"));
+ HOME_APP_ADJ =
+ Integer.valueOf(SystemProperties.get("ro.HOME_APP_ADJ"));
HIDDEN_APP_MIN_ADJ =
Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MIN_ADJ"));
CONTENT_PROVIDER_ADJ =
@@ -1280,6 +1299,8 @@
Integer.valueOf(SystemProperties.get("ro.VISIBLE_APP_MEM"))*PAGE_SIZE;
SECONDARY_SERVER_MEM =
Integer.valueOf(SystemProperties.get("ro.SECONDARY_SERVER_MEM"))*PAGE_SIZE;
+ HOME_APP_MEM =
+ Integer.valueOf(SystemProperties.get("ro.HOME_APP_MEM"))*PAGE_SIZE;
HIDDEN_APP_MEM =
Integer.valueOf(SystemProperties.get("ro.HIDDEN_APP_MEM"))*PAGE_SIZE;
EMPTY_APP_MEM =
@@ -1548,6 +1569,9 @@
System.identityHashCode(r),
r.task.taskId, r.shortComponentName);
}
+ if (r.isHomeActivity) {
+ mHomeProcess = app;
+ }
app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
r.info, r.icicle, results, newIntents, !andResume,
isNextTransitionForward());
@@ -2188,7 +2212,7 @@
if (app == null || app.instrumentationClass == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivityLocked(null, intent, null, null, 0, aInfo,
- null, null, 0, 0, 0, false);
+ null, null, 0, 0, 0, false, false);
}
}
return true;
@@ -2669,7 +2693,8 @@
Uri[] grantedUriPermissions,
int grantedMode, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
- int callingPid, int callingUid, boolean onlyIfNeeded) {
+ int callingPid, int callingUid, boolean onlyIfNeeded,
+ boolean componentSpecified) {
Log.i(TAG, "Starting activity: " + intent);
HistoryRecord sourceRecord = null;
@@ -2784,7 +2809,7 @@
HistoryRecord r = new HistoryRecord(this, callerApp, callingUid,
intent, resolvedType, aInfo, mConfiguration,
- resultRecord, resultWho, requestCode);
+ resultRecord, resultWho, requestCode, componentSpecified);
r.startTime = SystemClock.uptimeMillis();
HistoryRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
@@ -3118,6 +3143,8 @@
throw new IllegalArgumentException("File descriptors passed in Intent");
}
+ final boolean componentSpecified = intent.getComponent() != null;
+
// Don't modify the client's object!
intent = new Intent(intent);
@@ -3157,7 +3184,7 @@
int res = startActivityLocked(caller, intent, resolvedType,
grantedUriPermissions, grantedMode, aInfo,
resultTo, resultWho, requestCode, -1, -1,
- onlyIfNeeded);
+ onlyIfNeeded, componentSpecified);
Binder.restoreCallingIdentity(origId);
return res;
}
@@ -3247,7 +3274,7 @@
// those are not yet exposed to user code, so there is no need.
int res = startActivityLocked(r.app.thread, intent,
r.resolvedType, null, 0, aInfo, resultTo, resultWho,
- requestCode, -1, r.launchedFromUid, false);
+ requestCode, -1, r.launchedFromUid, false, false);
Binder.restoreCallingIdentity(origId);
r.finishing = wasFinishing;
@@ -3261,6 +3288,8 @@
final int startActivityInPackage(int uid,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded) {
+ final boolean componentSpecified = intent.getComponent() != null;
+
// Don't modify the client's object!
intent = new Intent(intent);
@@ -3291,7 +3320,7 @@
synchronized(this) {
return startActivityLocked(null, intent, resolvedType,
null, 0, aInfo, resultTo, resultWho, requestCode, -1, uid,
- onlyIfNeeded);
+ onlyIfNeeded, componentSpecified);
}
}
@@ -5678,9 +5707,9 @@
public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
outInfo.availMem = Process.getFreeMemory();
- outInfo.threshold = SECONDARY_SERVER_MEM;
+ outInfo.threshold = HOME_APP_MEM;
outInfo.lowMemory = outInfo.availMem <
- (SECONDARY_SERVER_MEM + ((HIDDEN_APP_MEM-SECONDARY_SERVER_MEM)/2));
+ (HOME_APP_MEM + ((HIDDEN_APP_MEM-HOME_APP_MEM)/2));
}
// =========================================================
@@ -7798,7 +7827,10 @@
currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY;
} else if (adj >= HIDDEN_APP_MIN_ADJ) {
currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
- currApp.lru = adj - HIDDEN_APP_MIN_ADJ;
+ currApp.lru = adj - HIDDEN_APP_MIN_ADJ + 1;
+ } else if (adj >= HOME_APP_ADJ) {
+ currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
+ currApp.lru = 0;
} else if (adj >= SECONDARY_SERVER_ADJ) {
currApp.importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
} else if (adj >= VISIBLE_APP_ADJ) {
@@ -7997,6 +8029,7 @@
pw.println(" ");
pw.println(" Total persistent processes: " + numPers);
+ pw.println(" mHomeProcess: " + mHomeProcess);
pw.println(" mConfiguration: " + mConfiguration);
pw.println(" mStartRunning=" + mStartRunning
+ " mSystemReady=" + mSystemReady
@@ -8680,6 +8713,10 @@
}
mProcessesOnHold.remove(app);
+ if (app == mHomeProcess) {
+ mHomeProcess = null;
+ }
+
if (restart) {
// We have components that still need to be running in the
// process, so re-launch it.
@@ -11185,9 +11222,8 @@
app.isForeground = false;
- // Right now there are three interesting states: it is
- // either the foreground app, background with activities,
- // or background without activities.
+ // Determine the importance of the process, starting with most
+ // important to least, and assign an appropriate OOM adjustment.
int adj;
int N;
if (app == TOP_APP || app.instrumentationClass != null
@@ -11207,6 +11243,10 @@
} else if (app.foregroundServices || app.forcingToForeground != null) {
// The user is aware of this app, so make it visible.
adj = VISIBLE_APP_ADJ;
+ } else if (app == mHomeProcess) {
+ // This process is hosting what we currently consider to be the
+ // home app, so we don't want to let it go into the background.
+ adj = HOME_APP_ADJ;
} else if ((N=app.activities.size()) != 0) {
// This app is in the background with paused activities.
adj = hiddenAdj;
@@ -11222,7 +11262,7 @@
adj = EMPTY_APP_ADJ;
}
- // By default, we use the computed adjusted. It may be changed if
+ // By default, we use the computed adjustment. It may be changed if
// there are applications dependent on our services or providers, but
// this gives us a baseline and makes sure we don't get into an
// infinite recursion.
diff --git a/services/java/com/android/server/am/HistoryRecord.java b/services/java/com/android/server/am/HistoryRecord.java
index b407208..0f62471 100644
--- a/services/java/com/android/server/am/HistoryRecord.java
+++ b/services/java/com/android/server/am/HistoryRecord.java
@@ -55,6 +55,8 @@
final String taskAffinity; // as per ActivityInfo.taskAffinity
final boolean stateNotNeeded; // As per ActivityInfo.flags
final boolean fullscreen; // covers the full screen?
+ final boolean componentSpecified; // did caller specifiy an explicit component?
+ final boolean isHomeActivity; // do we consider this to be a home activity?
final String baseDir; // where activity source (resources etc) located
final String resDir; // where public activity source (public resources etc) located
final String dataDir; // where activity data should go
@@ -102,8 +104,8 @@
pw.println(prefix + this);
pw.println(prefix + "packageName=" + packageName
+ " processName=" + processName);
- pw.println(prefix + "app=" + app);
- pw.println(prefix + "launchedFromUid=" + launchedFromUid);
+ pw.println(prefix + "launchedFromUid=" + launchedFromUid
+ + " app=" + app);
pw.println(prefix + intent);
pw.println(prefix + "frontOfTask=" + frontOfTask + " task=" + task);
pw.println(prefix + "taskAffinity=" + taskAffinity);
@@ -112,6 +114,9 @@
pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes)
+ " icon=0x" + Integer.toHexString(icon)
+ " theme=0x" + Integer.toHexString(theme));
+ pw.println(prefix + "stateNotNeeded=" + stateNotNeeded
+ + " componentSpecified=" + componentSpecified
+ + " isHomeActivity=" + isHomeActivity);
pw.println(prefix + "configuration=" + configuration);
pw.println(prefix + "resultTo=" + resultTo
+ " resultWho=" + resultWho + " resultCode=" + requestCode);
@@ -140,13 +145,15 @@
HistoryRecord(ActivityManagerService _service, ProcessRecord _caller,
int _launchedFromUid, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration,
- HistoryRecord _resultTo, String _resultWho, int _reqCode) {
+ HistoryRecord _resultTo, String _resultWho, int _reqCode,
+ boolean _componentSpecified) {
service = _service;
info = aInfo;
launchedFromUid = _launchedFromUid;
intent = _intent;
shortComponentName = _intent.getComponent().flattenToShortString();
resolvedType = _resolvedType;
+ componentSpecified = _componentSpecified;
configuration = _configuration;
resultTo = _resultTo;
resultWho = _resultWho;
@@ -216,6 +223,29 @@
&& !ent.array.getBoolean(
com.android.internal.R.styleable.Window_windowIsTranslucent, false);
+ if (!_componentSpecified || _launchedFromUid == Process.myUid()
+ || _launchedFromUid == 0) {
+ // If we know the system has determined the component, then
+ // we can consider this to be a home activity...
+ if (Intent.ACTION_MAIN.equals(_intent.getAction()) &&
+ _intent.hasCategory(Intent.CATEGORY_HOME) &&
+ _intent.getCategories().size() == 1 &&
+ _intent.getData() == null &&
+ _intent.getType() == null &&
+ (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
+ !"android".equals(realActivity.getClassName())) {
+ // This sure looks like a home activity!
+ // Note the last check is so we don't count the resolver
+ // activity as being home... really, we don't care about
+ // doing anything special with something that comes from
+ // the core framework package.
+ isHomeActivity = true;
+ } else {
+ isHomeActivity = false;
+ }
+ } else {
+ isHomeActivity = false;
+ }
} else {
realActivity = null;
taskAffinity = null;
@@ -226,6 +256,7 @@
processName = null;
packageName = null;
fullscreen = true;
+ isHomeActivity = false;
}
}