Merge "Treat IME processes as hosting activities"
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 81a886a..134ffa9 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -242,6 +242,16 @@
public static final int BIND_ADJUST_WITH_ACTIVITY = 0x0080;
/**
+ * @hide Flag for {@link #bindService}: Treat the binding as hosting
+ * an activity, an unbinding as the activity going in the background.
+ * That is, when unbinding, the process when empty will go on the activity
+ * LRU list instead of the regular one, keeping it around more aggressively
+ * than it otherwise would be. This is intended for use with IMEs to try
+ * to keep IME processes around for faster keyboard switching.
+ */
+ public static final int BIND_TREAT_LIKE_ACTIVITY = 0x08000000;
+
+ /**
* @hide An idea that is not yet implemented.
* Flag for {@link #bindService}: If binding from an activity, consider
* this service to be visible like the binding activity is. That is,
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 6827b3f..af8a6e7 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1225,7 +1225,8 @@
mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
if (bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
- | Context.BIND_NOT_VISIBLE | Context.BIND_SHOWING_UI)) {
+ | Context.BIND_NOT_VISIBLE | Context.BIND_NOT_FOREGROUND
+ | Context.BIND_SHOWING_UI)) {
mLastBindTime = SystemClock.uptimeMillis();
mHaveConnection = true;
mCurId = info.getId();
@@ -1783,7 +1784,8 @@
mInputShown = true;
if (mHaveConnection && !mVisibleBound) {
bindCurrentInputMethodService(
- mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE);
+ mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE
+ | Context.BIND_TREAT_LIKE_ACTIVITY);
mVisibleBound = true;
}
res = true;
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index a845127..1345cfd 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -667,8 +667,7 @@
// what they are, so we can report this elsewhere for
// others to know why certain services are running.
try {
- clientIntent = (PendingIntent)service.getParcelableExtra(
- Intent.EXTRA_CLIENT_INTENT);
+ clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT);
} catch (RuntimeException e) {
}
if (clientIntent != null) {
@@ -682,6 +681,11 @@
}
}
+ if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
+ mAm.enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS,
+ "BIND_TREAT_LIKE_ACTIVITY");
+ }
+
final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
ServiceLookupResult res =
@@ -755,8 +759,12 @@
}
if (s.app != null) {
+ if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
+ s.app.treatLikeActivity = true;
+ }
// This could have made the service more important.
- mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities, b.client);
+ mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities
+ || s.app.treatLikeActivity, b.client);
mAm.updateOomAdjLocked(s.app);
}
@@ -858,6 +866,12 @@
if (r.binding.service.app != null) {
// This could have made the service less important.
+ if ((r.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
+ r.binding.service.app.treatLikeActivity = true;
+ mAm.updateLruProcessLocked(r.binding.service.app,
+ r.binding.service.app.hasClientActivities
+ || r.binding.service.app.treatLikeActivity, null);
+ }
mAm.updateOomAdjLocked(r.binding.service.app);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index b8ec3ab..5eaa3a1 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2314,11 +2314,12 @@
final void updateLruProcessLocked(ProcessRecord app, boolean activityChange,
ProcessRecord client) {
- final boolean hasActivity = app.activities.size() > 0 || app.hasClientActivities;
+ final boolean hasActivity = app.activities.size() > 0 || app.hasClientActivities
+ || app.treatLikeActivity;
final boolean hasService = false; // not impl yet. app.services.size() > 0;
if (!activityChange && hasActivity) {
- // The process has activties, so we are only going to allow activity-based
- // adjustments move it. It should be kept in the front of the list with other
+ // The process has activities, so we are only allowing activity-based adjustments
+ // to move it. It should be kept in the front of the list with other
// processes that have activities, and we don't want those to change their
// order except due to activity operations.
return;
@@ -12571,6 +12572,7 @@
updateProcessForegroundLocked(app, false, false);
app.foregroundActivities = false;
app.hasShownUi = false;
+ app.treatLikeActivity = false;
app.hasAboveClient = false;
mServices.killServicesLocked(app, allowRestart);
@@ -14862,6 +14864,9 @@
app.adjTarget = s.name;
}
}
+ if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
+ app.treatLikeActivity = true;
+ }
final ActivityRecord a = cr.activity;
if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&
@@ -14994,10 +14999,17 @@
}
}
- if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY && app.hasClientActivities) {
- // This is a cached process, but with client activities. Mark it so.
- procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
- app.adjType = "cch-client-act";
+ if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
+ if (app.hasClientActivities) {
+ // This is a cached process, but with client activities. Mark it so.
+ procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;
+ app.adjType = "cch-client-act";
+ } else if (app.treatLikeActivity) {
+ // This is a cached process, but somebody wants us to treat it like it has
+ // an activity, okay!
+ procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
+ app.adjType = "cch-as-act";
+ }
}
if (adj == ProcessList.SERVICE_ADJ) {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 10574ed..d04a6b2 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -95,6 +95,7 @@
boolean hasShownUi; // Has UI been shown in this process since it was started?
boolean pendingUiClean; // Want to clean up resources from showing UI?
boolean hasAboveClient; // Bound using BIND_ABOVE_CLIENT, so want to be lower
+ boolean treatLikeActivity; // Bound using BIND_TREAT_LIKE_ACTIVITY
boolean bad; // True if disabled in the bad process list
boolean killedByAm; // True when proc has been killed by activity manager, not for RAM
boolean procStateChanged; // Keep track of whether we changed 'setAdj'.
@@ -251,10 +252,11 @@
pw.print(" lastStateTime=");
TimeUtils.formatDuration(lastStateTime, now, pw);
pw.println();
- if (hasShownUi || pendingUiClean || hasAboveClient) {
+ if (hasShownUi || pendingUiClean || hasAboveClient || treatLikeActivity) {
pw.print(prefix); pw.print("hasShownUi="); pw.print(hasShownUi);
pw.print(" pendingUiClean="); pw.print(pendingUiClean);
- pw.print(" hasAboveClient="); pw.println(hasAboveClient);
+ pw.print(" hasAboveClient="); pw.print(hasAboveClient);
+ pw.print(" treatLikeActivity="); pw.println(treatLikeActivity);
}
if (setIsForeground || foregroundServices || forcingToForeground != null) {
pw.print(prefix); pw.print("setIsForeground="); pw.print(setIsForeground);