Merge "Make drag handle tests stable."
diff --git a/api/current.txt b/api/current.txt
index 7ddd5af..d54b7fd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7441,12 +7441,16 @@
method public static boolean compareMimeTypes(java.lang.String, java.lang.String);
method public int describeContents();
method public java.lang.String[] filterMimeTypes(java.lang.String);
+ method public android.os.PersistableBundle getExtras();
method public java.lang.CharSequence getLabel();
method public java.lang.String getMimeType(int);
method public int getMimeTypeCount();
method public boolean hasMimeType(java.lang.String);
+ method public void setExtras(android.os.PersistableBundle);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.ClipDescription> CREATOR;
+ field public static final java.lang.String EXTRA_TARGET_COMPONENT_NAME = "android.content.extra.TARGET_COMPONENT_NAME";
+ field public static final java.lang.String EXTRA_USER_SERIAL_NUMBER = "android.content.extra.USER_SERIAL_NUMBER";
field public static final java.lang.String MIMETYPE_TEXT_HTML = "text/html";
field public static final java.lang.String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
field public static final java.lang.String MIMETYPE_TEXT_PLAIN = "text/plain";
@@ -7908,6 +7912,7 @@
field public static final int MODE_APPEND = 32768; // 0x8000
field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
field public static final deprecated int MODE_MULTI_PROCESS = 4; // 0x4
+ field public static final int MODE_NO_LOCALIZED_COLLATORS = 16; // 0x10
field public static final int MODE_PRIVATE = 0; // 0x0
field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
@@ -28060,6 +28065,7 @@
method public boolean isUserAGoat();
method public boolean isUserRunning(android.os.UserHandle);
method public boolean isUserRunningOrStopping(android.os.UserHandle);
+ method public boolean isUserRunningUnlocked(android.os.UserHandle);
method public deprecated boolean setRestrictionsChallenge(java.lang.String);
method public deprecated void setUserRestriction(java.lang.String, boolean);
method public deprecated void setUserRestrictions(android.os.Bundle);
diff --git a/api/system-current.txt b/api/system-current.txt
index edc9f18..2ea5ebb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -100,6 +100,7 @@
field public static final java.lang.String GET_APP_OPS_STATS = "android.permission.GET_APP_OPS_STATS";
field public static final java.lang.String GET_PACKAGE_IMPORTANCE = "android.permission.GET_PACKAGE_IMPORTANCE";
field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
+ field public static final java.lang.String GET_PROCESS_STATE_AND_OOM_SCORE = "android.permission.GET_PROCESS_STATE_AND_OOM_SCORE";
field public static final deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS";
field public static final java.lang.String GET_TOP_ACTIVITY_INFO = "android.permission.GET_TOP_ACTIVITY_INFO";
field public static final java.lang.String GLOBAL_SEARCH = "android.permission.GLOBAL_SEARCH";
@@ -7682,12 +7683,16 @@
method public static boolean compareMimeTypes(java.lang.String, java.lang.String);
method public int describeContents();
method public java.lang.String[] filterMimeTypes(java.lang.String);
+ method public android.os.PersistableBundle getExtras();
method public java.lang.CharSequence getLabel();
method public java.lang.String getMimeType(int);
method public int getMimeTypeCount();
method public boolean hasMimeType(java.lang.String);
+ method public void setExtras(android.os.PersistableBundle);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.ClipDescription> CREATOR;
+ field public static final java.lang.String EXTRA_TARGET_COMPONENT_NAME = "android.content.extra.TARGET_COMPONENT_NAME";
+ field public static final java.lang.String EXTRA_USER_SERIAL_NUMBER = "android.content.extra.USER_SERIAL_NUMBER";
field public static final java.lang.String MIMETYPE_TEXT_HTML = "text/html";
field public static final java.lang.String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
field public static final java.lang.String MIMETYPE_TEXT_PLAIN = "text/plain";
@@ -8155,6 +8160,7 @@
field public static final int MODE_APPEND = 32768; // 0x8000
field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
field public static final deprecated int MODE_MULTI_PROCESS = 4; // 0x4
+ field public static final int MODE_NO_LOCALIZED_COLLATORS = 16; // 0x10
field public static final int MODE_PRIVATE = 0; // 0x0
field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
@@ -30043,6 +30049,7 @@
method public boolean isUserAGoat();
method public boolean isUserRunning(android.os.UserHandle);
method public boolean isUserRunningOrStopping(android.os.UserHandle);
+ method public boolean isUserRunningUnlocked(android.os.UserHandle);
method public deprecated boolean setRestrictionsChallenge(java.lang.String);
method public deprecated void setUserRestriction(java.lang.String, boolean);
method public deprecated void setUserRestrictions(android.os.Bundle);
diff --git a/api/test-current.txt b/api/test-current.txt
index 4838702..904347d 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -7441,12 +7441,16 @@
method public static boolean compareMimeTypes(java.lang.String, java.lang.String);
method public int describeContents();
method public java.lang.String[] filterMimeTypes(java.lang.String);
+ method public android.os.PersistableBundle getExtras();
method public java.lang.CharSequence getLabel();
method public java.lang.String getMimeType(int);
method public int getMimeTypeCount();
method public boolean hasMimeType(java.lang.String);
+ method public void setExtras(android.os.PersistableBundle);
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.ClipDescription> CREATOR;
+ field public static final java.lang.String EXTRA_TARGET_COMPONENT_NAME = "android.content.extra.TARGET_COMPONENT_NAME";
+ field public static final java.lang.String EXTRA_USER_SERIAL_NUMBER = "android.content.extra.USER_SERIAL_NUMBER";
field public static final java.lang.String MIMETYPE_TEXT_HTML = "text/html";
field public static final java.lang.String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
field public static final java.lang.String MIMETYPE_TEXT_PLAIN = "text/plain";
@@ -7908,6 +7912,7 @@
field public static final int MODE_APPEND = 32768; // 0x8000
field public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 8; // 0x8
field public static final deprecated int MODE_MULTI_PROCESS = 4; // 0x4
+ field public static final int MODE_NO_LOCALIZED_COLLATORS = 16; // 0x10
field public static final int MODE_PRIVATE = 0; // 0x0
field public static final deprecated int MODE_WORLD_READABLE = 1; // 0x1
field public static final deprecated int MODE_WORLD_WRITEABLE = 2; // 0x2
@@ -28060,6 +28065,7 @@
method public boolean isUserAGoat();
method public boolean isUserRunning(android.os.UserHandle);
method public boolean isUserRunningOrStopping(android.os.UserHandle);
+ method public boolean isUserRunningUnlocked(android.os.UserHandle);
method public deprecated boolean setRestrictionsChallenge(java.lang.String);
method public deprecated void setUserRestriction(java.lang.String, boolean);
method public deprecated void setUserRestrictions(android.os.Bundle);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index daf01ec..2ad63b5 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -154,7 +154,7 @@
" am switch-user <USER_ID>\n" +
" am start-user <USER_ID>\n" +
" am unlock-user <USER_ID> [TOKEN_HEX]\n" +
- " am stop-user [-w] <USER_ID>\n" +
+ " am stop-user [-w] [-f] <USER_ID>\n" +
" am stack start <DISPLAY_ID> <INTENT>\n" +
" am stack movetask <TASK_ID> <STACK_ID> [true|false]\n" +
" am stack resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
@@ -290,6 +290,7 @@
"am stop-user: stop execution of USER_ID, not allowing it to run any\n" +
" code until a later explicit start or switch to it.\n" +
" -w: wait for stop-user to complete.\n" +
+ " -f: force stop even if there are related users that cannot be stopped.\n" +
"\n" +
"am stack start: start a new activity on <DISPLAY_ID> using <INTENT>.\n" +
"\n" +
@@ -1131,10 +1132,13 @@
private void runStopUser() throws Exception {
boolean wait = false;
- String opt = null;
+ boolean force = false;
+ String opt;
while ((opt = nextOption()) != null) {
if ("-w".equals(opt)) {
wait = true;
+ } else if ("-f".equals(opt)) {
+ force = true;
} else {
System.err.println("Error: unknown option: " + opt);
return;
@@ -1143,7 +1147,7 @@
int user = Integer.parseInt(nextArgRequired());
StopUserCallback callback = wait ? new StopUserCallback() : null;
- int res = mAm.stopUser(user, callback);
+ int res = mAm.stopUser(user, force, callback);
if (res != ActivityManager.USER_OP_SUCCESS) {
String txt = "";
switch (res) {
@@ -1153,6 +1157,13 @@
case ActivityManager.USER_OP_UNKNOWN_USER:
txt = " (Unknown user " + user + ")";
break;
+ case ActivityManager.USER_OP_ERROR_IS_SYSTEM:
+ txt = " (System user cannot be stopped)";
+ break;
+ case ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP:
+ txt = " (Can't stop user " + user
+ + " - one of its related users can't be stopped)";
+ break;
}
System.err.println("Switch failed: " + res + txt);
} else if (callback != null) {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index f1a7de8..c203854 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -265,6 +265,12 @@
/** @hide User operation call: given user id is the current user, can't be stopped. */
public static final int USER_OP_IS_CURRENT = -2;
+ /** @hide User operation call: system user can't be stopped. */
+ public static final int USER_OP_ERROR_IS_SYSTEM = -3;
+
+ /** @hide User operation call: one of related users cannot be stopped. */
+ public static final int USER_OP_ERROR_RELATED_USERS_CANNOT_STOP = -4;
+
/** @hide Process does not exist. */
public static final int PROCESS_STATE_NONEXISTENT = -1;
@@ -537,6 +543,11 @@
return stackId == FREEFORM_WORKSPACE_STACK_ID
|| stackId == FULLSCREEN_WORKSPACE_STACK_ID || stackId == DOCKED_STACK_ID;
}
+
+ /** Returns true if the windows in the stack can receive input keys. */
+ public static boolean canReceiveKeys(int stackId) {
+ return stackId != PINNED_STACK_ID;
+ }
}
/**
@@ -3085,6 +3096,8 @@
public static final int FLAG_OR_STOPPED = 1 << 0;
/** {@hide} */
public static final int FLAG_AND_LOCKED = 1 << 1;
+ /** {@hide} */
+ public static final int FLAG_AND_UNLOCKED = 1 << 2;
/**
* Return whether the given user is actively running. This means that
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 19d9fc2..c05d5e8 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1981,9 +1981,10 @@
case STOP_USER_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int userid = data.readInt();
+ boolean force = data.readInt() != 0;
IStopUserCallback callback = IStopUserCallback.Stub.asInterface(
data.readStrongBinder());
- int result = stopUser(userid, callback);
+ int result = stopUser(userid, force, callback);
reply.writeNoException();
reply.writeInt(result);
return true;
@@ -5287,11 +5288,13 @@
return result;
}
- public int stopUser(int userid, IStopUserCallback callback) throws RemoteException {
+ public int stopUser(int userid, boolean force, IStopUserCallback callback)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(userid);
+ data.writeInt(force ? 1 : 0);
data.writeStrongInterface(callback);
mRemote.transact(STOP_USER_TRANSACTION, data, reply, 0);
reply.readException();
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index bf2e13a..b569416 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -25,7 +25,6 @@
import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.os.WorkSource;
import android.text.TextUtils;
@@ -869,13 +868,19 @@
* {@link Intent#filterEquals}), will be canceled.
*
* @param operation IntentSender which matches a previously added
- * IntentSender.
+ * IntentSender. This parameter must not be {@code null}.
*
* @see #set
*/
public void cancel(PendingIntent operation) {
if (operation == null) {
- throw new NullPointerException("operation");
+ final String msg = "cancel() called with a null PendingIntent";
+ if (mTargetSdkVersion >= Build.VERSION_CODES.N) {
+ throw new NullPointerException(msg);
+ } else {
+ Log.e(TAG, msg);
+ return;
+ }
}
try {
@@ -891,7 +896,7 @@
*/
public void cancel(OnAlarmListener listener) {
if (listener == null) {
- throw new NullPointerException("listener");
+ throw new NullPointerException("cancel() called with a null OnAlarmListener");
}
ListenerWrapper wrapper = null;
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index c661107..23c4198 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -589,6 +589,9 @@
if ((mode & MODE_ENABLE_WRITE_AHEAD_LOGGING) != 0) {
flags |= SQLiteDatabase.ENABLE_WRITE_AHEAD_LOGGING;
}
+ if ((mode & MODE_NO_LOCALIZED_COLLATORS) != 0) {
+ flags |= SQLiteDatabase.NO_LOCALIZED_COLLATORS;
+ }
SQLiteDatabase db = SQLiteDatabase.openDatabase(f.getPath(), factory, flags, errorHandler);
setFilePermissionsFromMode(f.getPath(), mode, 0);
return db;
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 09c6c0b..38c7957 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -391,7 +391,7 @@
public boolean switchUser(int userid) throws RemoteException;
public boolean startUserInBackground(int userid) throws RemoteException;
public boolean unlockUser(int userid, byte[] token) throws RemoteException;
- public int stopUser(int userid, IStopUserCallback callback) throws RemoteException;
+ public int stopUser(int userid, boolean force, IStopUserCallback callback) throws RemoteException;
public UserInfo getCurrentUser() throws RemoteException;
public boolean isUserRunning(int userid, int flags) throws RemoteException;
public int[] getRunningUserIds() throws RemoteException;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index c1d5b19..c504ce3 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -93,6 +93,7 @@
AutomaticZenRule addAutomaticZenRule(in AutomaticZenRule automaticZenRule);
boolean updateAutomaticZenRule(in AutomaticZenRule automaticZenRule);
boolean removeAutomaticZenRule(String id);
+ boolean removeAutomaticZenRules(String packageName);
byte[] getBackupPayload(int user);
void applyRestore(in byte[] payload, int user);
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 3eb3e0f..89610e9 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -470,6 +470,20 @@
}
/**
+ * Deletes all automatic zen rules owned by the given package.
+ *
+ * @hide
+ */
+ public boolean removeAutomaticZenRules(String packageName) {
+ INotificationManager service = getService();
+ try {
+ return service.removeAutomaticZenRules(packageName);
+ } catch (RemoteException e) {
+ }
+ return false;
+ }
+
+ /**
* Checks the ability to read/modify notification policy for the calling package.
*
* <p>
diff --git a/core/java/android/content/ClipDescription.java b/core/java/android/content/ClipDescription.java
index e988516..1b024e2 100644
--- a/core/java/android/content/ClipDescription.java
+++ b/core/java/android/content/ClipDescription.java
@@ -18,6 +18,7 @@
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.PersistableBundle;
import android.text.TextUtils;
import java.util.ArrayList;
@@ -59,8 +60,35 @@
*/
public static final String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
+ /**
+ * The name of the extra used to define a component name when copying/dragging
+ * an app icon from Launcher.
+ * <p>
+ * Type: String
+ * </p>
+ * <p>
+ * Use {@link ComponentName#unflattenFromString(String)}
+ * and {@link ComponentName#flattenToString()} to convert the extra value
+ * to/from {@link ComponentName}.
+ * </p>
+ */
+ public static final String EXTRA_TARGET_COMPONENT_NAME =
+ "android.content.extra.TARGET_COMPONENT_NAME";
+
+ /**
+ * The name of the extra used to define a user serial number when copying/dragging
+ * an app icon from Launcher.
+ * <p>
+ * Type: long
+ * </p>
+ */
+ public static final String EXTRA_USER_SERIAL_NUMBER =
+ "android.content.extra.USER_SERIAL_NUMBER";
+
+
final CharSequence mLabel;
final String[] mMimeTypes;
+ private PersistableBundle mExtras;
/**
* Create a new clip.
@@ -173,6 +201,27 @@
return mMimeTypes[index];
}
+ /**
+ * Retrieve extended data from the clip description.
+ *
+ * @return the bundle containing extended data previously set with
+ * {@link #setExtras(PersistableBundle)}, or null if no extras have been set.
+ *
+ * @see #setExtras(PersistableBundle)
+ */
+ public PersistableBundle getExtras() {
+ return mExtras;
+ }
+
+ /**
+ * Add extended data to the clip description.
+ *
+ * @see #getExtras()
+ */
+ public void setExtras(PersistableBundle extras) {
+ mExtras = new PersistableBundle(extras);
+ }
+
/** @hide */
public void validate() {
if (mMimeTypes == null) {
@@ -211,6 +260,13 @@
b.append(mLabel);
b.append('"');
}
+ if (mExtras != null) {
+ if (!first) {
+ b.append(' ');
+ }
+ first = false;
+ b.append(mExtras.toString());
+ }
return !first;
}
@@ -236,11 +292,13 @@
public void writeToParcel(Parcel dest, int flags) {
TextUtils.writeToParcel(mLabel, dest, flags);
dest.writeStringArray(mMimeTypes);
+ dest.writePersistableBundle(mExtras);
}
ClipDescription(Parcel in) {
mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mMimeTypes = in.createStringArray();
+ mExtras = in.readPersistableBundle();
}
public static final Parcelable.Creator<ClipDescription> CREATOR =
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index b73fa50..6cc5497 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -159,6 +159,16 @@
*/
public static final int MODE_ENABLE_WRITE_AHEAD_LOGGING = 0x0008;
+ /**
+ * Database open flag: when set, the database is opened without support for
+ * localized collators.
+ *
+ * @see #openOrCreateDatabase(String, int, CursorFactory)
+ * @see #openOrCreateDatabase(String, int, CursorFactory, DatabaseErrorHandler)
+ * @see SQLiteDatabase#NO_LOCALIZED_COLLATORS
+ */
+ public static final int MODE_NO_LOCALIZED_COLLATORS = 0x0010;
+
/** @hide */
@IntDef(flag = true,
value = {
@@ -1271,6 +1281,7 @@
* default operation, {@link #MODE_WORLD_READABLE}
* and {@link #MODE_WORLD_WRITEABLE} to control permissions.
* Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
+ * Use {@link #MODE_NO_LOCALIZED_COLLATORS} to disable localized collators.
* @param factory An optional factory class that is called to instantiate a
* cursor when query is called.
*
@@ -1281,6 +1292,7 @@
* @see #MODE_WORLD_READABLE
* @see #MODE_WORLD_WRITEABLE
* @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
+ * @see #MODE_NO_LOCALIZED_COLLATORS
* @see #deleteDatabase
*/
public abstract SQLiteDatabase openOrCreateDatabase(String name,
@@ -1298,6 +1310,7 @@
* default operation, {@link #MODE_WORLD_READABLE}
* and {@link #MODE_WORLD_WRITEABLE} to control permissions.
* Use {@link #MODE_ENABLE_WRITE_AHEAD_LOGGING} to enable write-ahead logging by default.
+ * Use {@link #MODE_NO_LOCALIZED_COLLATORS} to disable localized collators.
* @param factory An optional factory class that is called to instantiate a
* cursor when query is called.
* @param errorHandler the {@link DatabaseErrorHandler} to be used when sqlite reports database
@@ -1309,6 +1322,7 @@
* @see #MODE_WORLD_READABLE
* @see #MODE_WORLD_WRITEABLE
* @see #MODE_ENABLE_WRITE_AHEAD_LOGGING
+ * @see #MODE_NO_LOCALIZED_COLLATORS
* @see #deleteDatabase
*/
public abstract SQLiteDatabase openOrCreateDatabase(String name,
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ecb1850..fd1e57b 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1068,19 +1068,20 @@
pkg.mSignatures = null;
pkg.mSigningKeys = null;
- collectCertificates(pkg, new File(pkg.baseCodePath), parseFlags);
+ collectCertificates(pkg, new File(pkg.baseCodePath), pkg.applicationInfo.flags, parseFlags);
if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) {
- for (String splitCodePath : pkg.splitCodePaths) {
- collectCertificates(pkg, new File(splitCodePath), parseFlags);
+ for (int i = 0; i < pkg.splitCodePaths.length; i++) {
+ collectCertificates(pkg, new File(pkg.splitCodePaths[i]), pkg.splitFlags[i],
+ parseFlags);
}
}
}
- private static void collectCertificates(Package pkg, File apkFile, int parseFlags)
+ private static void collectCertificates(Package pkg, File apkFile, int apkFlags, int parseFlags)
throws PackageParserException {
- final boolean requireCode = ((parseFlags & PARSE_ENFORCE_CODE) != 0)
- && ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) != 0);
+ final boolean hasCode = (apkFlags & ApplicationInfo.FLAG_HAS_CODE) != 0;
+ final boolean requireCode = ((parseFlags & PARSE_ENFORCE_CODE) != 0) && hasCode;
final String apkPath = apkFile.getAbsolutePath();
final boolean skipVerification = Build.IS_DEBUGGABLE
&& ((parseFlags & PARSE_SKIP_VERIFICATION) != 0);
@@ -1217,7 +1218,8 @@
// TODO: factor signature related items out of Package object
final Package tempPkg = new Package(null);
// TODO: fix b/25118622; pass in '0' for parse flags
- collectCertificates(tempPkg, apkFile, flags & PARSE_SKIP_VERIFICATION);
+ collectCertificates(tempPkg, apkFile, 0 /*apkFlags*/,
+ flags & PARSE_SKIP_VERIFICATION);
signatures = tempPkg.mSignatures;
} else {
signatures = null;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 1aa5c66..bce38f4 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -169,7 +169,7 @@
/**
* Current version of checkin data format.
*/
- static final String CHECKIN_VERSION = "16";
+ static final String CHECKIN_VERSION = "17";
/**
* Old version, we hit 9 and ran out of room, need to remove.
@@ -407,17 +407,23 @@
public abstract Timer getCameraTurnedOnTimer();
public abstract Timer getForegroundActivityTimer();
- // Time this uid has any processes in foreground state.
- public static final int PROCESS_STATE_FOREGROUND = 0;
- // Time this uid has any process in active state (not cached).
- public static final int PROCESS_STATE_ACTIVE = 1;
+ // Time this uid has any processes in the top state.
+ public static final int PROCESS_STATE_TOP = 0;
+ // Time this uid has any process with a started out bound foreground service.
+ public static final int PROCESS_STATE_FOREGROUND_SERVICE = 1;
+ // Time this uid has any process that is top while the device is sleeping.
+ public static final int PROCESS_STATE_TOP_SLEEPING = 2;
+ // Time this uid has any process in an active foreground state.
+ public static final int PROCESS_STATE_FOREGROUND = 3;
+ // Time this uid has any process in an active background state.
+ public static final int PROCESS_STATE_BACKGROUND = 4;
// Time this uid has any processes running at all.
- public static final int PROCESS_STATE_RUNNING = 2;
+ public static final int PROCESS_STATE_CACHED = 5;
// Total number of process states we track.
- public static final int NUM_PROCESS_STATE = 3;
+ public static final int NUM_PROCESS_STATE = 6;
static final String[] PROCESS_STATE_NAMES = {
- "Foreground", "Active", "Running"
+ "Top", "Fg Service", "Top Sleeping", "Foreground", "Background", "Cached"
};
public abstract long getProcessStateTime(int state, long elapsedRealtimeUs, int which);
@@ -2954,8 +2960,9 @@
final Object[] stateTimes = new Object[Uid.NUM_PROCESS_STATE];
long totalStateTime = 0;
for (int ips=0; ips<Uid.NUM_PROCESS_STATE; ips++) {
- totalStateTime += u.getProcessStateTime(ips, rawRealtime, which);
- stateTimes[ips] = (totalStateTime + 500) / 1000;
+ final long time = u.getProcessStateTime(ips, rawRealtime, which);
+ totalStateTime += time;
+ stateTimes[ips] = (time + 500) / 1000;
}
if (totalStateTime > 0) {
dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes);
@@ -4122,11 +4129,18 @@
sb.append(" ");
sb.append(Uid.PROCESS_STATE_NAMES[ips]);
sb.append(" for: ");
- formatTimeMs(sb, (totalStateTime + 500) / 1000);
+ formatTimeMs(sb, (time + 500) / 1000);
pw.println(sb.toString());
uidActivity = true;
}
}
+ if (totalStateTime > 0) {
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" Total running: ");
+ formatTimeMs(sb, (totalStateTime + 500) / 1000);
+ pw.println(sb.toString());
+ }
final long userCpuTimeUs = u.getUserCpuTimeUs(which);
final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index f26693c..79390d4 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -487,6 +487,19 @@
public static final String DISALLOW_RECORD_AUDIO = "no_record_audio";
/**
+ * Specifies if a user is not allowed to run in the background and should be stopped during
+ * user switch. The default value is <code>false</code>.
+ *
+ * <p>This restriction can be set by device owners and profile owners.
+ *
+ * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+ * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+ * @see #getUserRestrictions()
+ * @hide
+ */
+ public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
+
+ /**
* Specifies if a user is not allowed to use the camera.
*
* @see DevicePolicyManager#addUserRestriction(ComponentName, String)
@@ -742,6 +755,23 @@
}
/**
+ * Return whether the given user is running in an "unlocked" state. A user
+ * is unlocked only after they've entered their credentials (such as a lock
+ * pattern or PIN), and credential-encrypted private app data storage is
+ * available.
+ *
+ * @param user to retrieve the unlocked state for.
+ */
+ public boolean isUserRunningUnlocked(UserHandle user) {
+ try {
+ return ActivityManagerNative.getDefault().isUserRunning(
+ user.getIdentifier(), ActivityManager.FLAG_AND_UNLOCKED);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
* Returns the UserInfo object describing a specific user.
* Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
* @param userHandle the user handle of the user whose information is being requested.
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index b3399d0..541623d 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -1110,7 +1110,7 @@
if (!Objects.equals(id, to.id)) {
d.addLine(item, "id", id, to.id);
}
- if (creationTime == to.creationTime) {
+ if (creationTime != to.creationTime) {
d.addLine(item, "creationTime", creationTime, to.creationTime);
}
}
diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java
index f2b6041..5d9d929 100644
--- a/core/java/android/text/Hyphenator.java
+++ b/core/java/android/text/Hyphenator.java
@@ -166,7 +166,7 @@
sMap.put(null, null);
// TODO: replace this with a discovery-based method that looks into /system/usr/hyphen-data
- String[] availableLanguages = {"en-US", "eu", "hu", "hy", "nb", "nn", "und-Ethi"};
+ String[] availableLanguages = {"en-US", "es", "eu", "hu", "hy", "nb", "nn", "und-Ethi"};
for (int i = 0; i < availableLanguages.length; i++) {
String languageTag = availableLanguages[i];
Hyphenator h = loadHyphenator(languageTag);
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 0ed72e4d..0dd803a2 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1666,6 +1666,7 @@
ViewGroup.LayoutParams layoutParams = target.getLayoutParams();
if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
((ViewGroup.MarginLayoutParams) layoutParams).setMarginEnd(end);
+ target.setLayoutParams(layoutParams);
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 9391c60..4a969b2 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -105,7 +105,7 @@
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 136 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 138 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -2621,10 +2621,9 @@
}
}
- public void noteProcessStateLocked(String name, int uid, int state) {
+ public void noteUidProcessStateLocked(int uid, int state) {
uid = mapUid(uid);
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- getUidStatsLocked(uid).updateProcessStateLocked(name, state, elapsedRealtime);
+ getUidStatsLocked(uid).updateUidProcessStateLocked(state);
}
public void noteProcessFinishLocked(String name, int uid) {
@@ -2632,13 +2631,11 @@
if (!mActiveEvents.updateState(HistoryItem.EVENT_PROC_FINISH, name, uid, 0)) {
return;
}
- final long elapsedRealtime = SystemClock.elapsedRealtime();
- final long uptime = SystemClock.uptimeMillis();
- getUidStatsLocked(uid).updateProcessStateLocked(name, Uid.PROCESS_STATE_NONE,
- elapsedRealtime);
if (!mRecordAllHistory) {
return;
}
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+ final long uptime = SystemClock.uptimeMillis();
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_FINISH, name, uid);
}
@@ -4446,8 +4443,7 @@
StopwatchTimer mForegroundActivityTimer;
- static final int PROCESS_STATE_NONE = NUM_PROCESS_STATE;
- int mProcessState = PROCESS_STATE_NONE;
+ int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
StopwatchTimer[] mProcessStateTimer;
BatchTimer mVibratorOnTimer;
@@ -4812,21 +4808,6 @@
}
}
- void updateUidProcessStateLocked(int state, long elapsedRealtimeMs) {
- if (mProcessState == state) return;
-
- if (mProcessState != PROCESS_STATE_NONE) {
- mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtimeMs);
- }
- mProcessState = state;
- if (state != PROCESS_STATE_NONE) {
- if (mProcessStateTimer[state] == null) {
- makeProcessState(state, null);
- }
- mProcessStateTimer[state].startRunningLocked(elapsedRealtimeMs);
- }
- }
-
public BatchTimer createVibratorOnTimerLocked() {
if (mVibratorOnTimer == null) {
mVibratorOnTimer = new BatchTimer(Uid.this, VIBRATOR_ON, mOnBatteryTimeBase);
@@ -5167,7 +5148,7 @@
active |= !mProcessStateTimer[i].reset(false);
}
}
- active |= (mProcessState != PROCESS_STATE_NONE);
+ active |= (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT);
}
if (mVibratorOnTimer != null) {
if (mVibratorOnTimer.reset(false)) {
@@ -5261,14 +5242,9 @@
}
for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
Proc proc = mProcessStats.valueAt(ip);
- if (proc.mProcessState == PROCESS_STATE_NONE) {
- proc.detach();
- mProcessStats.removeAt(ip);
- } else {
- proc.reset();
- active = true;
- }
+ proc.detach();
}
+ mProcessStats.clear();
if (mPids.size() > 0) {
for (int i=mPids.size()-1; i>=0; i--) {
Pid pid = mPids.valueAt(i);
@@ -5697,7 +5673,7 @@
} else {
mForegroundActivityTimer = null;
}
- mProcessState = PROCESS_STATE_NONE;
+ mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
for (int i = 0; i < NUM_PROCESS_STATE; i++) {
if (in.readInt() != 0) {
makeProcessState(i, in);
@@ -6080,11 +6056,6 @@
*/
int mUnpluggedNumAnrs;
- /**
- * Current process state.
- */
- int mProcessState = PROCESS_STATE_NONE;
-
ArrayList<ExcessivePower> mExcessivePower;
Proc(String name) {
@@ -6104,16 +6075,6 @@
public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
}
- void reset() {
- mUserTime = mSystemTime = mForegroundTime = 0;
- mStarts = mNumCrashes = mNumAnrs = 0;
- mLoadedUserTime = mLoadedSystemTime = mLoadedForegroundTime = 0;
- mLoadedStarts = mLoadedNumCrashes = mLoadedNumAnrs = 0;
- mUnpluggedUserTime = mUnpluggedSystemTime = mUnpluggedForegroundTime = 0;
- mUnpluggedStarts = mUnpluggedNumCrashes = mUnpluggedNumAnrs = 0;
- mExcessivePower = null;
- }
-
void detach() {
mActive = false;
mOnBatteryTimeBase.remove(this);
@@ -6668,46 +6629,39 @@
return ps;
}
- public void updateProcessStateLocked(String procName, int state, long elapsedRealtimeMs) {
- int procState;
- if (state <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
- procState = PROCESS_STATE_FOREGROUND;
- } else if (state <= ActivityManager.PROCESS_STATE_RECEIVER) {
- procState = PROCESS_STATE_ACTIVE;
+ public void updateUidProcessStateLocked(int procState) {
+ int uidRunningState;
+ if (procState == ActivityManager.PROCESS_STATE_NONEXISTENT) {
+ uidRunningState = ActivityManager.PROCESS_STATE_NONEXISTENT;
+ } else if (procState == ActivityManager.PROCESS_STATE_TOP) {
+ uidRunningState = PROCESS_STATE_TOP;
+ } else if (procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
+ // Persistent and other foreground states go here.
+ uidRunningState = PROCESS_STATE_FOREGROUND_SERVICE;
+ } else if (procState <= ActivityManager.PROCESS_STATE_TOP_SLEEPING) {
+ uidRunningState = PROCESS_STATE_TOP_SLEEPING;
+ } else if (procState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
+ // Persistent and other foreground states go here.
+ uidRunningState = PROCESS_STATE_FOREGROUND;
+ } else if (procState <= ActivityManager.PROCESS_STATE_RECEIVER) {
+ uidRunningState = PROCESS_STATE_BACKGROUND;
} else {
- procState = PROCESS_STATE_RUNNING;
+ uidRunningState = PROCESS_STATE_CACHED;
}
- updateRealProcessStateLocked(procName, procState, elapsedRealtimeMs);
- }
- public void updateRealProcessStateLocked(String procName, int procState,
- long elapsedRealtimeMs) {
- Proc proc = getProcessStatsLocked(procName);
- if (proc.mProcessState != procState) {
- boolean changed;
- if (procState < proc.mProcessState) {
- // Has this process become more important? If so,
- // we may need to change the uid if the currrent uid proc state
- // is not as important as what we are now setting.
- changed = mProcessState > procState;
- } else {
- // Has this process become less important? If so,
- // we may need to change the uid if the current uid proc state
- // is the same importance as the old setting.
- changed = mProcessState == proc.mProcessState;
+ if (mProcessState == uidRunningState) return;
+
+ final long elapsedRealtime = SystemClock.elapsedRealtime();
+
+ if (mProcessState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
+ mProcessStateTimer[mProcessState].stopRunningLocked(elapsedRealtime);
+ }
+ mProcessState = uidRunningState;
+ if (uidRunningState != ActivityManager.PROCESS_STATE_NONEXISTENT) {
+ if (mProcessStateTimer[uidRunningState] == null) {
+ makeProcessState(uidRunningState, null);
}
- proc.mProcessState = procState;
- if (changed) {
- // uid's state may have changed; compute what the new state should be.
- int uidProcState = PROCESS_STATE_NONE;
- for (int ip=mProcessStats.size()-1; ip>=0; ip--) {
- proc = mProcessStats.valueAt(ip);
- if (proc.mProcessState < uidProcState) {
- uidProcState = proc.mProcessState;
- }
- }
- updateUidProcessStateLocked(uidProcState, elapsedRealtimeMs);
- }
+ mProcessStateTimer[uidRunningState].startRunningLocked(elapsedRealtime);
}
}
@@ -9423,7 +9377,7 @@
if (in.readInt() != 0) {
u.createForegroundActivityTimerLocked().readSummaryFromParcelLocked(in);
}
- u.mProcessState = Uid.PROCESS_STATE_NONE;
+ u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
if (in.readInt() != 0) {
u.makeProcessState(i, null);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 568b601..2940f6c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1460,6 +1460,12 @@
android:description="@string/permdesc_killBackgroundProcesses"
android:protectionLevel="normal" />
+ <!-- @SystemApi @hide Allows an application to query process states and current
+ OOM adjustment scores.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE"
+ android:protectionLevel="signature|privileged|development" />
+
<!-- @SystemApi @hide Allows an application to retrieve a package's importance.
This permission is not available to third party applications. -->
<permission android:name="android.permission.GET_PACKAGE_IMPORTANCE"
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index ab37519..51019cc 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -126,6 +126,7 @@
<assign-permission name="android.permission.WAKE_LOCK" uid="media" />
<assign-permission name="android.permission.UPDATE_DEVICE_STATS" uid="media" />
<assign-permission name="android.permission.UPDATE_APP_OPS_STATS" uid="media" />
+ <assign-permission name="android.permission.GET_PROCESS_STATE_AND_OOM_SCORE" uid="media" />
<assign-permission name="android.permission.ACCESS_SURFACE_FLINGER" uid="graphics" />
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index b0421b0..be3013b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -741,45 +741,45 @@
Selection selection = mSelectionManager.getSelection(new Selection());
- final int id = item.getItemId();
- if (id == R.id.menu_open) {
- openDocuments(selection);
- mode.finish();
- return true;
+ switch (item.getItemId()) {
+ case R.id.menu_open:
+ openDocuments(selection);
+ mode.finish();
+ return true;
- } else if (id == R.id.menu_share) {
- shareDocuments(selection);
- mode.finish();
- return true;
+ case R.id.menu_share:
+ shareDocuments(selection);
+ mode.finish();
+ return true;
- } else if (id == R.id.menu_delete) {
- // Exit selection mode first, so we avoid deselecting deleted documents.
- mode.finish();
- deleteDocuments(selection);
- return true;
+ case R.id.menu_delete:
+ // Exit selection mode first, so we avoid deselecting deleted documents.
+ mode.finish();
+ deleteDocuments(selection);
+ return true;
- } else if (id == R.id.menu_copy_to) {
- transferDocuments(selection, CopyService.TRANSFER_MODE_COPY);
- mode.finish();
- return true;
+ case R.id.menu_copy_to:
+ transferDocuments(selection, CopyService.TRANSFER_MODE_COPY);
+ mode.finish();
+ return true;
- } else if (id == R.id.menu_move_to) {
- // Exit selection mode first, so we avoid deselecting deleted documents.
- mode.finish();
- transferDocuments(selection, CopyService.TRANSFER_MODE_MOVE);
- return true;
+ case R.id.menu_move_to:
+ // Exit selection mode first, so we avoid deselecting deleted documents.
+ mode.finish();
+ transferDocuments(selection, CopyService.TRANSFER_MODE_MOVE);
+ return true;
- } else if (id == R.id.menu_copy_to_clipboard) {
- copySelectionToClipboard(selection);
- mode.finish();
- return true;
+ case R.id.menu_copy_to_clipboard:
+ copySelectionToClipboard(selection);
+ return true;
- } else if (id == R.id.menu_select_all) {
- selectAllFiles();
- return true;
+ case R.id.menu_select_all:
+ selectAllFiles();
+ return true;
- } else {
- return false;
+ default:
+ if (DEBUG) Log.d(TAG, "Unhandled menu item selected: " + item);
+ return false;
}
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardTile.java b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardTile.java
index 6fef134..347e9f7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardTile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/DashboardTile.java
@@ -74,6 +74,11 @@
*/
public int priority;
+ /**
+ * The metaData from the activity that defines this tile.
+ */
+ public Bundle metaData;
+
public DashboardTile() {
// Empty
}
@@ -107,6 +112,7 @@
dest.writeBundle(extras);
dest.writeString(category);
dest.writeInt(priority);
+ dest.writeBundle(metaData);
}
public void readFromParcel(Parcel in) {
@@ -125,6 +131,7 @@
extras = in.readBundle();
category = in.readString();
priority = in.readInt();
+ metaData = in.readBundle();
}
DashboardTile(Parcel in) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index 00dadb8..581c810 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -18,9 +18,15 @@
import android.annotation.LayoutRes;
import android.annotation.Nullable;
import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.TypedArray;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.widget.DrawerLayout;
+import android.util.Log;
import android.util.Pair;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -33,21 +39,30 @@
import android.widget.Toolbar;
import com.android.settingslib.R;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class SettingsDrawerActivity extends Activity {
+ protected static final boolean DEBUG_TIMING = false;
+ private static final String TAG = "SettingsDrawerActivity";
+
+ private static List<DashboardCategory> sDashboardCategories;
+ private static HashMap<Pair<String, String>, DashboardTile> sTileCache;
+
+ private final PackageReceiver mPackageReceiver = new PackageReceiver();
+ private final List<CategoryListener> mCategoryListeners = new ArrayList<>();
+
private SettingsDrawerAdapter mDrawerAdapter;
- // Hold on to a cache of tiles to avoid loading the info multiple times.
- private final HashMap<Pair<String, String>, DashboardTile> mTileCache = new HashMap<>();
- private List<DashboardCategory> mDashboardCategories;
private DrawerLayout mDrawerLayout;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ long startTime = System.currentTimeMillis();
+
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.setContentView(R.layout.settings_with_drawer);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
@@ -62,6 +77,10 @@
mDrawerLayout = null;
return;
}
+ if (sDashboardCategories == null) {
+ sTileCache = new HashMap<>();
+ sDashboardCategories = TileUtils.getCategories(this, sTileCache);
+ }
setActionBar(toolbar);
mDrawerAdapter = new SettingsDrawerAdapter(this);
ListView listView = (ListView) findViewById(R.id.left_drawer);
@@ -72,6 +91,8 @@
onTileClicked(mDrawerAdapter.getTile(position));
};
});
+ if (DEBUG_TIMING) Log.d(TAG, "onCreate took " + (System.currentTimeMillis() - startTime)
+ + " ms");
}
@Override
@@ -88,7 +109,29 @@
protected void onResume() {
super.onResume();
- updateDrawer();
+ final IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
+ filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+ filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+ filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+ filter.addDataScheme("package");
+ registerReceiver(mPackageReceiver, filter);
+
+ new CategoriesUpdater().execute();
+ }
+
+ @Override
+ protected void onPause() {
+ unregisterReceiver(mPackageReceiver);
+
+ super.onPause();
+ }
+
+ public void addCategoryListener(CategoryListener listener) {
+ mCategoryListeners.add(listener);
+ }
+
+ public void remCategoryListener(CategoryListener listener) {
+ mCategoryListeners.remove(listener);
}
public void openDrawer() {
@@ -134,11 +177,16 @@
}
}
- public List<DashboardCategory> getDashboardCategories(boolean force) {
- if (force) {
- mDashboardCategories = TileUtils.getCategories(this, mTileCache);
+ public List<DashboardCategory> getDashboardCategories() {
+ return sDashboardCategories;
+ }
+
+ protected void onCategoriesChanged() {
+ updateDrawer();
+ final int N = mCategoryListeners.size();
+ for (int i = 0; i < N; i++) {
+ mCategoryListeners.get(i).onCategoriesChanged();
}
- return mDashboardCategories;
}
public boolean openTile(DashboardTile tile) {
@@ -167,4 +215,28 @@
public void onProfileTileOpen() {
finish();
}
+
+ public interface CategoryListener {
+ void onCategoriesChanged();
+ }
+
+ private class CategoriesUpdater extends AsyncTask<Void, Void, List<DashboardCategory>> {
+ @Override
+ protected List<DashboardCategory> doInBackground(Void... params) {
+ return TileUtils.getCategories(SettingsDrawerActivity.this, sTileCache);
+ }
+
+ @Override
+ protected void onPostExecute(List<DashboardCategory> dashboardCategories) {
+ sDashboardCategories = dashboardCategories;
+ onCategoriesChanged();
+ }
+ }
+
+ private class PackageReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ new CategoriesUpdater().execute();
+ }
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
index fef716c..24c6ae8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerAdapter.java
@@ -38,7 +38,7 @@
}
void updateCategories() {
- List<DashboardCategory> categories = mActivity.getDashboardCategories(true);
+ List<DashboardCategory> categories = mActivity.getDashboardCategories();
mItems.clear();
for (int i = 0; i < categories.size(); i++) {
Item category = new Item();
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index 18e8d31..6b36680 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -14,6 +14,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
@@ -35,6 +36,7 @@
public class TileUtils {
private static final boolean DEBUG = false;
+ private static final boolean DEBUG_TIMING = true;
private static final String LOG_TAG = "TileUtils";
@@ -105,12 +107,9 @@
private static final String SETTING_PKG = "com.android.settings";
- public static List<DashboardCategory> getCategories(Context context) {
- return getCategories(context, new HashMap<Pair<String, String>, DashboardTile>());
- }
-
public static List<DashboardCategory> getCategories(Context context,
HashMap<Pair<String, String>, DashboardTile> cache) {
+ final long startTime = System.currentTimeMillis();
ArrayList<DashboardTile> tiles = new ArrayList<>();
UserManager userManager = UserManager.get(context);
for (UserHandle user : userManager.getUserProfiles()) {
@@ -143,6 +142,8 @@
Collections.sort(category.tiles, TILE_COMPARATOR);
}
Collections.sort(categories, CATEGORY_COMPARATOR);
+ if (DEBUG_TIMING) Log.d(LOG_TAG, "getCategories took "
+ + (System.currentTimeMillis() - startTime) + " ms");
return categories;
}
@@ -207,7 +208,9 @@
activityInfo.packageName, activityInfo.name);
tile.category = categoryKey;
tile.priority = requireSettings ? resolved.priority : 0;
- updateTileData(context, tile);
+ tile.metaData = activityInfo.metaData;
+ updateTileData(context, tile, activityInfo, activityInfo.applicationInfo,
+ pm);
if (DEBUG) Log.d(LOG_TAG, "Adding tile " + tile.title);
addedCache.put(key, tile);
@@ -231,64 +234,52 @@
return null;
}
- private static boolean updateTileData(Context context, DashboardTile tile) {
- Intent intent = tile.intent;
- if (intent != null) {
- // Find the activity that is in the system image
- PackageManager pm = context.getPackageManager();
- List<ResolveInfo> list = tile.userHandle.size() != 0
- ? pm.queryIntentActivitiesAsUser(intent, PackageManager.GET_META_DATA,
- tile.userHandle.get(0).getIdentifier())
- : pm.queryIntentActivities(intent, PackageManager.GET_META_DATA);
- int listSize = list.size();
- for (int i = 0; i < listSize; i++) {
- ResolveInfo resolveInfo = list.get(i);
- if (resolveInfo.activityInfo.applicationInfo.isSystemApp()) {
- int icon = 0;
- CharSequence title = null;
- String summary = null;
+ private static boolean updateTileData(Context context, DashboardTile tile,
+ ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm) {
+ if (applicationInfo.isSystemApp()) {
+ int icon = 0;
+ CharSequence title = null;
+ String summary = null;
- // Get the activity's meta-data
- try {
- Resources res = pm.getResourcesForApplication(
- resolveInfo.activityInfo.packageName);
- Bundle metaData = resolveInfo.activityInfo.metaData;
+ // Get the activity's meta-data
+ try {
+ Resources res = pm.getResourcesForApplication(
+ applicationInfo.packageName);
+ Bundle metaData = activityInfo.metaData;
- if (res != null && metaData != null) {
- if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
- icon = metaData.getInt(META_DATA_PREFERENCE_ICON);
- }
- if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
- title = metaData.getString(META_DATA_PREFERENCE_TITLE);
- }
- if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
- summary = metaData.getString(META_DATA_PREFERENCE_SUMMARY);
- }
- }
- } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
- if (DEBUG) Log.d(LOG_TAG, "Couldn't find info", e);
+ if (res != null && metaData != null) {
+ if (metaData.containsKey(META_DATA_PREFERENCE_ICON)) {
+ icon = metaData.getInt(META_DATA_PREFERENCE_ICON);
}
-
- // Set the preference title to the activity's label if no
- // meta-data is found
- if (TextUtils.isEmpty(title)) {
- title = resolveInfo.loadLabel(pm).toString();
+ if (metaData.containsKey(META_DATA_PREFERENCE_TITLE)) {
+ title = metaData.getString(META_DATA_PREFERENCE_TITLE);
}
- if (icon == 0) {
- icon = resolveInfo.activityInfo.icon;
+ if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
+ summary = metaData.getString(META_DATA_PREFERENCE_SUMMARY);
}
-
- // Set icon, title and summary for the preference
- tile.icon = Icon.createWithResource(resolveInfo.activityInfo.packageName, icon);
- tile.title = title;
- tile.summary = summary;
- // Replace the intent with this specific activity
- tile.intent = new Intent().setClassName(resolveInfo.activityInfo.packageName,
- resolveInfo.activityInfo.name);
-
- return true;
}
+ } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
+ if (DEBUG) Log.d(LOG_TAG, "Couldn't find info", e);
}
+
+ // Set the preference title to the activity's label if no
+ // meta-data is found
+ if (TextUtils.isEmpty(title)) {
+ title = activityInfo.loadLabel(pm).toString();
+ }
+ if (icon == 0) {
+ icon = activityInfo.icon;
+ }
+
+ // Set icon, title and summary for the preference
+ tile.icon = Icon.createWithResource(activityInfo.packageName, icon);
+ tile.title = title;
+ tile.summary = summary;
+ // Replace the intent with this specific activity
+ tile.intent = new Intent().setClassName(activityInfo.packageName,
+ activityInfo.name);
+
+ return true;
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
index 6f8cd8c..da3cd54 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -130,6 +130,7 @@
private final int mLowPriorityColor;
private boolean mIsBelowSpeedBump;
private FalsingManager mFalsingManager;
+ private boolean mTrackTouch;
public ActivatableNotificationView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -175,15 +176,30 @@
};
@Override
- public boolean onTouchEvent(MotionEvent event) {
- if (mDimmed) {
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ if (mDimmed && !mActivated) {
return handleTouchEventDimmed(event);
} else {
- return super.onTouchEvent(event);
+ return super.dispatchTouchEvent(event);
}
}
@Override
+ public boolean onTouchEvent(MotionEvent event) {
+ boolean result;
+ if (mDimmed && mActivated) {
+ result = handleTouchEventDimmed(event);
+ } else {
+ result = super.onTouchEvent(event);
+ }
+ if (mActivated && result && event.getAction() == MotionEvent.ACTION_UP) {
+ mFalsingManager.onNotificationDoubleTap();
+ removeCallbacks(mTapTimeoutRunnable);
+ }
+ return result;
+ }
+
+ @Override
public void drawableHotspotChanged(float x, float y) {
if (!mDimmed){
mBackgroundNormal.drawableHotspotChanged(x, y);
@@ -206,14 +222,15 @@
case MotionEvent.ACTION_DOWN:
mDownX = event.getX();
mDownY = event.getY();
+ mTrackTouch = true;
if (mDownY > getActualHeight()) {
- return false;
+ mTrackTouch = false;
}
break;
case MotionEvent.ACTION_MOVE:
if (!isWithinTouchSlop(event)) {
makeInactive(true /* animate */);
- return false;
+ mTrackTouch = false;
}
break;
case MotionEvent.ACTION_UP:
@@ -222,23 +239,23 @@
makeActive();
postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
} else {
- mFalsingManager.onNotificationDoubleTap();
- boolean performed = performClick();
- if (performed) {
- removeCallbacks(mTapTimeoutRunnable);
+ if (!performClick()) {
+ return false;
}
}
} else {
makeInactive(true /* animate */);
+ mTrackTouch = false;
}
break;
case MotionEvent.ACTION_CANCEL:
makeInactive(true /* animate */);
+ mTrackTouch = false;
break;
default:
break;
}
- return true;
+ return mTrackTouch;
}
private void makeActive() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 5d4c64e..3c7ff7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -116,7 +116,8 @@
public abstract class BaseStatusBar extends SystemUI implements
CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
- ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment {
+ ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
+ ExpandableNotificationRow.OnExpandClickListener {
public static final String TAG = "StatusBar";
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public static final boolean MULTIUSER_DEBUG = false;
@@ -1298,9 +1299,14 @@
// Since the number of notifications is determined based on the height of the view, we
// need to update them.
updateRowStates();
+ mStackScroller.onHeightChanged(null, false);
}
}
+ @Override
+ public void onExpandClicked(View clickedView, boolean nowExpanded) {
+ }
+
protected class H extends Handler {
public void handleMessage(Message m) {
switch (m.what) {
@@ -1381,6 +1387,7 @@
parent, false);
row.setExpansionLogger(this, entry.notification.getKey());
row.setGroupManager(mGroupManager);
+ row.setOnExpandClickListener(this);
}
workAroundBadLayerDrawableOpacity(row);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 81e20aa..7a94a58 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -104,14 +104,20 @@
private boolean mIconAnimationRunning;
private boolean mShowNoBackground;
private ExpandableNotificationRow mNotificationParent;
+ private OnExpandClickListener mOnExpandClickListener;
private OnClickListener mExpandClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
if (mGroupManager.isSummaryOfGroup(mStatusBarNotification)) {
mGroupManager.toggleGroupExpansion(mStatusBarNotification);
+ mOnExpandClickListener.onExpandClicked(ExpandableNotificationRow.this,
+ mGroupManager.isGroupExpanded(mStatusBarNotification));
} else {
- setUserExpanded(!isExpanded());
+ boolean nowExpanded = !isExpanded();
+ setUserExpanded(nowExpanded);
notifyHeightChanged(true);
+ mOnExpandClickListener.onExpandClicked(ExpandableNotificationRow.this,
+ nowExpanded);
}
}
};
@@ -421,6 +427,10 @@
mPrivateLayout.setSubTextVisible(visible);
}
+ public void setOnExpandClickListener(OnExpandClickListener onExpandClickListener) {
+ mOnExpandClickListener = onExpandClickListener;
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
@@ -986,4 +996,8 @@
mLogger.logNotificationExpansion(mLoggingKey, userAction, nowExpanded) ;
}
}
+
+ public interface OnExpandClickListener {
+ void onExpandClicked(View clickedView, boolean nowExpanded);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index c0e3ec1..73ee363 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -955,15 +955,7 @@
mQsTracking = false;
mTrackingPointer = -1;
trackMovement(event);
- float fraction = getQsExpansionFraction();
- if ((fraction != 0f || y >= mInitialTouchY)
- && (fraction != 1f || y <= mInitialTouchY)) {
- flingQsWithCurrentVelocity(y,
- event.getActionMasked() == MotionEvent.ACTION_CANCEL);
- } else {
- logQsSwipeDown(y);
- mScrollYOverride = -1;
- }
+ flingQsWithCurrentVelocity(y, event.getActionMasked() == MotionEvent.ACTION_CANCEL);
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 05660ec..685c4e5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -25,7 +25,6 @@
import android.app.IActivityManager;
import android.app.Notification;
import android.app.PendingIntent;
-import android.app.RemoteInput;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
@@ -3999,6 +3998,13 @@
}
}
+ @Override
+ public void onExpandClicked(View clickedView, boolean nowExpanded) {
+ if (mState == StatusBarState.KEYGUARD && nowExpanded) {
+ goToLockedShade(clickedView);
+ }
+ }
+
/**
* Goes back to the keyguard after hanging around in {@link StatusBarState#SHADE_LOCKED}.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index e00b890..b010761 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -342,7 +342,7 @@
private void stopUserId(int id) {
try {
- ActivityManagerNative.getDefault().stopUser(id, null);
+ ActivityManagerNative.getDefault().stopUser(id, /* force= */ false, null);
} catch (RemoteException e) {
Log.e(TAG, "Couldn't stop user.", e);
}
diff --git a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
index 76b2346..2fe6648 100644
--- a/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
+++ b/packages/VpnDialogs/src/com/android/vpndialogs/ManageDialog.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.DialogInterface;
import android.net.IConnectivityManager;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ServiceManager;
@@ -50,8 +51,8 @@
private Handler mHandler;
@Override
- protected void onResume() {
- super.onResume();
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
if (getCallingPackage() != null) {
Log.e(TAG, getCallingPackage() + " cannot start this activity");
@@ -108,11 +109,11 @@
}
@Override
- protected void onPause() {
- super.onPause();
+ protected void onDestroy() {
if (!isFinishing()) {
finish();
}
+ super.onDestroy();
}
@Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index bbf8652..ef623eb 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2771,57 +2771,60 @@
}
final void setFocusedActivityLocked(ActivityRecord r, String reason) {
- if (r != null && mFocusedActivity != r) {
- if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: r=" + r);
- ActivityRecord last = mFocusedActivity;
- mFocusedActivity = r;
- if (r.task.taskType != ActivityRecord.HOME_ACTIVITY_TYPE
- && r.task.taskType != ActivityRecord.RECENTS_ACTIVITY_TYPE) {
- if (mCurAppTimeTracker != r.appTimeTracker) {
- // We are switching app tracking. Complete the current one.
- if (mCurAppTimeTracker != null) {
- mCurAppTimeTracker.stop();
- mHandler.obtainMessage(REPORT_TIME_TRACKER_MSG,
- mCurAppTimeTracker).sendToTarget();
- mStackSupervisor.clearOtherAppTimeTrackers(r.appTimeTracker);
- mCurAppTimeTracker = null;
- }
- if (r.appTimeTracker != null) {
- mCurAppTimeTracker = r.appTimeTracker;
- startTimeTrackingFocusedActivityLocked();
- }
- } else {
+ if (r == null || mFocusedActivity == r) {
+ return;
+ }
+
+ if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedActivityLocked: r=" + r);
+ final ActivityRecord last = mFocusedActivity;
+ mFocusedActivity = r;
+ if (r.task.isApplicationTask()) {
+ if (mCurAppTimeTracker != r.appTimeTracker) {
+ // We are switching app tracking. Complete the current one.
+ if (mCurAppTimeTracker != null) {
+ mCurAppTimeTracker.stop();
+ mHandler.obtainMessage(
+ REPORT_TIME_TRACKER_MSG, mCurAppTimeTracker).sendToTarget();
+ mStackSupervisor.clearOtherAppTimeTrackers(r.appTimeTracker);
+ mCurAppTimeTracker = null;
+ }
+ if (r.appTimeTracker != null) {
+ mCurAppTimeTracker = r.appTimeTracker;
startTimeTrackingFocusedActivityLocked();
}
} else {
- r.appTimeTracker = null;
+ startTimeTrackingFocusedActivityLocked();
}
- if (r.task != null && r.task.voiceInteractor != null) {
- startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
- } else {
- finishRunningVoiceLocked();
- if (last != null && last.task.voiceSession != null) {
- // We had been in a voice interaction session, but now focused has
- // move to something different. Just finish the session, we can't
- // return to it and retain the proper state and synchronization with
- // the voice interaction service.
- finishVoiceTask(last.task.voiceSession);
- }
- }
- if (mStackSupervisor.setFocusedStack(r, reason + " setFocusedActivity")) {
- mWindowManager.setFocusedApp(r.appToken, true);
- }
- applyUpdateLockStateLocked(r);
- if (mFocusedActivity.userId != mLastFocusedUserId) {
- mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG);
- mHandler.sendMessage(mHandler.obtainMessage(FOREGROUND_PROFILE_CHANGED_MSG,
- mFocusedActivity.userId, 0));
- mLastFocusedUserId = mFocusedActivity.userId;
+ } else {
+ r.appTimeTracker = null;
+ }
+ if (r.task.voiceInteractor != null) {
+ startRunningVoiceLocked(r.task.voiceSession, r.info.applicationInfo.uid);
+ } else {
+ finishRunningVoiceLocked();
+ if (last != null && last.task.voiceSession != null) {
+ // We had been in a voice interaction session, but now focused has
+ // move to something different. Just finish the session, we can't
+ // return to it and retain the proper state and synchronization with
+ // the voice interaction service.
+ finishVoiceTask(last.task.voiceSession);
}
}
- EventLog.writeEvent(EventLogTags.AM_FOCUSED_ACTIVITY,
+ if (mStackSupervisor.setFocusedStack(r, reason + " setFocusedActivity")) {
+ mWindowManager.setFocusedApp(r.appToken, true);
+ }
+ applyUpdateLockStateLocked(r);
+ if (mFocusedActivity.userId != mLastFocusedUserId) {
+ mHandler.removeMessages(FOREGROUND_PROFILE_CHANGED_MSG);
+ mHandler.obtainMessage(
+ FOREGROUND_PROFILE_CHANGED_MSG, mFocusedActivity.userId, 0).sendToTarget();
+ mLastFocusedUserId = mFocusedActivity.userId;
+ }
+
+ EventLogTags.writeAmFocusedActivity(
mFocusedActivity == null ? -1 : mFocusedActivity.userId,
- mFocusedActivity == null ? "NULL" : mFocusedActivity.shortComponentName);
+ mFocusedActivity == null ? "NULL" : mFocusedActivity.shortComponentName,
+ reason);
}
final void clearFocusedActivity(ActivityRecord r) {
@@ -2837,7 +2840,7 @@
}
}
mFocusedActivity = null;
- EventLog.writeEvent(EventLogTags.AM_FOCUSED_ACTIVITY, -1, "NULL");
+ EventLogTags.writeAmFocusedActivity(-1, "NULL", "clearFocusedActivity");
}
}
@@ -5386,6 +5389,11 @@
removeUriPermissionsForPackageLocked(packageName, userId, true);
}
+ // Remove all zen rules created by this package; revoke it's zen access.
+ INotificationManager inm = NotificationManager.getService();
+ inm.removeAutomaticZenRules(packageName);
+ inm.setNotificationPolicyAccessGranted(packageName, false);
+
Intent intent = new Intent(Intent.ACTION_PACKAGE_DATA_CLEARED,
Uri.fromParts("package", packageName, null));
intent.putExtra(Intent.EXTRA_UID, pkgUid);
@@ -6069,6 +6077,8 @@
"No more processes in " + old.uidRecord);
enqueueUidChangeLocked(old.uidRecord, -1, UidRecord.CHANGE_GONE);
mActiveUids.remove(uid);
+ mBatteryStatsService.noteUidProcessState(uid,
+ ActivityManager.PROCESS_STATE_NONEXISTENT);
}
old.uidRecord = null;
}
@@ -6093,6 +6103,7 @@
if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
"Creating new process uid: " + uidRec);
mActiveUids.put(proc.uid, uidRec);
+ mBatteryStatsService.noteUidProcessState(uidRec.uid, uidRec.curProcState);
enqueueUidChangeLocked(uidRec, -1, UidRecord.CHANGE_ACTIVE);
}
proc.uidRecord = uidRec;
@@ -7227,6 +7238,11 @@
*/
public void getProcessStatesAndOomScoresForPIDs(
/*in*/ int[] pids, /*out*/ int[] states, /*out*/ int[] scores) {
+ if (scores != null) {
+ enforceCallingPermission(android.Manifest.permission.GET_PROCESS_STATE_AND_OOM_SCORE,
+ "getProcessStatesAndOomScoresForPIDs()");
+ }
+
if (pids == null) {
throw new NullPointerException("pids");
} else if (states == null) {
@@ -19494,10 +19510,6 @@
if (proc.baseProcessTracker != null) {
proc.baseProcessTracker.setState(proc.repProcState, memFactor, now, proc.pkgList);
}
- if (proc.repProcState >= 0) {
- mBatteryStatsService.noteProcessState(proc.processName, proc.info.uid,
- proc.repProcState);
- }
}
}
@@ -19997,6 +20009,7 @@
}
uidRec.setProcState = uidRec.curProcState;
enqueueUidChangeLocked(uidRec, -1, uidChange);
+ mBatteryStatsService.noteUidProcessState(uidRec.uid, uidRec.curProcState);
}
}
@@ -20424,8 +20437,8 @@
}
@Override
- public int stopUser(final int userId, final IStopUserCallback callback) {
- return mUserController.stopUser(userId, callback);
+ public int stopUser(final int userId, boolean force, final IStopUserCallback callback) {
+ return mUserController.stopUser(userId, force, callback);
}
void onUserRemovedLocked(int userId) {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index da2c8c5c..02a372a 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -54,7 +54,6 @@
import android.app.ResultInfo;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
@@ -73,7 +72,6 @@
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
-import android.provider.Settings;
import android.service.voice.IVoiceInteractionSession;
import android.util.EventLog;
import android.util.Slog;
@@ -2827,41 +2825,43 @@
}
private void adjustFocusedActivityLocked(ActivityRecord r, String reason) {
- if (mStackSupervisor.isFocusedStack(this) && mService.mFocusedActivity == r) {
- ActivityRecord next = topRunningActivityLocked();
- final String myReason = reason + " adjustFocus";
- if (next != r) {
- if (next != null && StackId.keepFocusInStackIfPossible(mStackId)) {
- // For freeform, docked, and pinned stacks we always keep the focus within the
- // stack as long as there is a running activity in the stack that we can adjust
- // focus to.
- mService.setFocusedActivityLocked(next, myReason);
- return;
- } else {
- final TaskRecord task = r.task;
- if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
- // For non-fullscreen stack, we want to move the focus to the next visible
- // stack to prevent the home screen from moving to the top and obscuring
- // other visible stacks.
- if (!mFullscreen
- && adjustFocusToNextVisibleStackLocked(null, myReason)) {
- return;
- }
- // Move the home stack to the top if this stack is fullscreen or there is no
- // other visible stack.
- if (mStackSupervisor.moveHomeStackTaskToTop(
- task.getTaskToReturnTo(), myReason)) {
- // Activity focus was already adjusted. Nothing else to do...
- return;
- }
+ if (!mStackSupervisor.isFocusedStack(this) || mService.mFocusedActivity != r) {
+ return;
+ }
+
+ final ActivityRecord next = topRunningActivityLocked();
+ final String myReason = reason + " adjustFocus";
+ if (next != r) {
+ if (next != null && StackId.keepFocusInStackIfPossible(mStackId)) {
+ // For freeform, docked, and pinned stacks we always keep the focus within the
+ // stack as long as there is a running activity in the stack that we can adjust
+ // focus to.
+ mService.setFocusedActivityLocked(next, myReason);
+ return;
+ } else {
+ final TaskRecord task = r.task;
+ if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
+ // For non-fullscreen stack, we want to move the focus to the next visible
+ // stack to prevent the home screen from moving to the top and obscuring
+ // other visible stacks.
+ if (!mFullscreen
+ && adjustFocusToNextVisibleStackLocked(null, myReason)) {
+ return;
+ }
+ // Move the home stack to the top if this stack is fullscreen or there is no
+ // other visible stack.
+ if (mStackSupervisor.moveHomeStackTaskToTop(
+ task.getTaskToReturnTo(), myReason)) {
+ // Activity focus was already adjusted. Nothing else to do...
+ return;
}
}
}
+ }
- final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
- if (top != null) {
- mService.setFocusedActivityLocked(top, myReason);
- }
+ final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
+ if (top != null) {
+ mService.setFocusedActivityLocked(top, myReason);
}
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c7228ce..f64b803 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -272,18 +272,18 @@
}
}
- void noteProcessState(String name, int uid, int state) {
- synchronized (mStats) {
- mStats.noteProcessStateLocked(name, uid, state);
- }
- }
-
void noteProcessFinish(String name, int uid) {
synchronized (mStats) {
mStats.noteProcessFinishLocked(name, uid);
}
}
+ void noteUidProcessState(int uid, int state) {
+ synchronized (mStats) {
+ mStats.noteUidProcessStateLocked(uid, state);
+ }
+ }
+
// Public interface...
public byte[] getStatistics() {
diff --git a/services/core/java/com/android/server/am/EventLogTags.logtags b/services/core/java/com/android/server/am/EventLogTags.logtags
index 78b5f33..0397553 100644
--- a/services/core/java/com/android/server/am/EventLogTags.logtags
+++ b/services/core/java/com/android/server/am/EventLogTags.logtags
@@ -91,7 +91,7 @@
30042 am_activity_fully_drawn_time (User|1|5),(Token|1|5),(Component Name|3),(time|2|3)
# Activity focused
-30043 am_focused_activity (User|1|5),(Component Name|3)
+30043 am_focused_activity (User|1|5),(Component Name|3),(Reason|3)
# Stack focus
30044 am_focused_stack (User|1|5),(Focused Stack Id|1|5),(Last Focused Stack Id|1|5),(Reason|3)
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 9c29149..3e0ae17 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -18,6 +18,8 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.app.ActivityManager.USER_OP_ERROR_IS_SYSTEM;
+import static android.app.ActivityManager.USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
import static android.app.ActivityManager.USER_OP_IS_CURRENT;
import static android.app.ActivityManager.USER_OP_SUCCESS;
import static android.os.Process.SYSTEM_UID;
@@ -34,6 +36,7 @@
import static com.android.server.am.ActivityManagerService.SYSTEM_USER_START_MSG;
import static com.android.server.am.ActivityManagerService.USER_SWITCH_TIMEOUT_MSG;
+import android.annotation.NonNull;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.Dialog;
@@ -56,11 +59,11 @@
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
+import android.util.IntArray;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -78,6 +81,8 @@
import java.util.List;
import java.util.Set;
+import libcore.util.EmptyArray;
+
/**
* Helper class for {@link ActivityManagerService} responsible for multi-user functionality.
*/
@@ -152,39 +157,44 @@
finishUserBoot(uss);
startProfilesLocked();
+ stopRunningUsersLocked(MAX_RUNNING_USERS);
+ }
+ }
- int num = mUserLru.size();
- int i = 0;
- while (num > MAX_RUNNING_USERS && i < mUserLru.size()) {
- Integer oldUserId = mUserLru.get(i);
- UserState oldUss = mStartedUsers.get(oldUserId);
- if (oldUss == null) {
- // Shouldn't happen, but be sane if it does.
- mUserLru.remove(i);
- num--;
- continue;
- }
- if (oldUss.mState == UserState.STATE_STOPPING
- || oldUss.mState == UserState.STATE_SHUTDOWN) {
- // This user is already stopping, doesn't count.
- num--;
- i++;
- continue;
- }
- if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId) {
- // Owner/System user and current user can't be stopped. We count it as running
- // when it is not a pure system user.
- if (UserInfo.isSystemOnly(oldUserId)) {
- num--;
- }
- i++;
- continue;
- }
- // This is a user to be stopped.
- stopUserLocked(oldUserId, null);
+ void stopRunningUsersLocked(int maxRunningUsers) {
+ int num = mUserLru.size();
+ int i = 0;
+ while (num > maxRunningUsers && i < mUserLru.size()) {
+ Integer oldUserId = mUserLru.get(i);
+ UserState oldUss = mStartedUsers.get(oldUserId);
+ if (oldUss == null) {
+ // Shouldn't happen, but be sane if it does.
+ mUserLru.remove(i);
+ num--;
+ continue;
+ }
+ if (oldUss.mState == UserState.STATE_STOPPING
+ || oldUss.mState == UserState.STATE_SHUTDOWN) {
+ // This user is already stopping, doesn't count.
num--;
i++;
+ continue;
}
+ if (oldUserId == UserHandle.USER_SYSTEM || oldUserId == mCurrentUserId) {
+ // Owner/System user and current user can't be stopped. We count it as running
+ // when it is not a pure system user.
+ if (UserInfo.isSystemOnly(oldUserId)) {
+ num--;
+ }
+ i++;
+ continue;
+ }
+ // This is a user to be stopped.
+ if (stopUsersLocked(oldUserId, false, null) != USER_OP_SUCCESS) {
+ num--;
+ }
+ num--;
+ i++;
}
}
@@ -205,7 +215,7 @@
}
}
- int stopUser(final int userId, final IStopUserCallback callback) {
+ int stopUser(final int userId, final boolean force, final IStopUserCallback callback) {
if (mService.checkCallingPermission(INTERACT_ACROSS_USERS_FULL)
!= PackageManager.PERMISSION_GRANTED) {
String msg = "Permission Denial: switchUser() from pid="
@@ -221,16 +231,44 @@
mService.enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES,
userId);
synchronized (mService) {
- return stopUserLocked(userId, callback);
+ return stopUsersLocked(userId, force, callback);
}
}
- private int stopUserLocked(final int userId, final IStopUserCallback callback) {
- if (DEBUG_MU) Slog.i(TAG, "stopUserLocked userId=" + userId);
- if (mCurrentUserId == userId && mTargetUserId == UserHandle.USER_NULL) {
+ /**
+ * Stops the user along with its related users. The method calls
+ * {@link #getUsersToStopLocked(int)} to determine the list of users that should be stopped.
+ */
+ private int stopUsersLocked(final int userId, boolean force, final IStopUserCallback callback) {
+ if (userId == UserHandle.USER_SYSTEM) {
+ return USER_OP_ERROR_IS_SYSTEM;
+ }
+ if (isCurrentUserLocked(userId)) {
return USER_OP_IS_CURRENT;
}
+ int[] usersToStop = getUsersToStopLocked(userId);
+ // If one of related users is system or current, no related users should be stopped
+ for (int i = 0; i < usersToStop.length; i++) {
+ int relatedUserId = usersToStop[i];
+ if ((UserHandle.USER_SYSTEM == relatedUserId) || isCurrentUserLocked(relatedUserId)) {
+ if (DEBUG_MU) Slog.i(TAG, "stopUsersLocked cannot stop related user "
+ + relatedUserId);
+ // We still need to stop the requested user if it's a force stop.
+ if (force) {
+ stopSingleUserLocked(userId, callback);
+ }
+ return USER_OP_ERROR_RELATED_USERS_CANNOT_STOP;
+ }
+ }
+ if (DEBUG_MU) Slog.i(TAG, "stopUsersLocked usersToStop=" + Arrays.toString(usersToStop));
+ for (int userIdToStop : usersToStop) {
+ stopSingleUserLocked(userIdToStop, userIdToStop == userId ? callback : null);
+ }
+ return USER_OP_SUCCESS;
+ }
+ private void stopSingleUserLocked(final int userId, final IStopUserCallback callback) {
+ if (DEBUG_MU) Slog.i(TAG, "stopSingleUserLocked userId=" + userId);
final UserState uss = mStartedUsers.get(userId);
if (uss == null) {
// User is not started, nothing to do... but we do need to
@@ -246,7 +284,7 @@
}
});
}
- return USER_OP_SUCCESS;
+ return;
}
if (callback != null) {
@@ -307,8 +345,6 @@
Binder.restoreCallingIdentity(ident);
}
}
-
- return USER_OP_SUCCESS;
}
void finishUserStop(UserState uss) {
@@ -350,6 +386,36 @@
}
}
+ /**
+ * Determines the list of users that should be stopped together with the specified
+ * {@code userId}. The returned list includes {@code userId}.
+ */
+ private @NonNull int[] getUsersToStopLocked(int userId) {
+ int startedUsersSize = mStartedUsers.size();
+ IntArray userIds = new IntArray();
+ userIds.add(userId);
+ synchronized (mUserProfileGroupIdsSelfLocked) {
+ int userGroupId = mUserProfileGroupIdsSelfLocked.get(userId,
+ UserInfo.NO_PROFILE_GROUP_ID);
+ for (int i = 0; i < startedUsersSize; i++) {
+ UserState uss = mStartedUsers.valueAt(i);
+ int startedUserId = uss.mHandle.getIdentifier();
+ // Skip unrelated users (profileGroupId mismatch)
+ int startedUserGroupId = mUserProfileGroupIdsSelfLocked.get(startedUserId,
+ UserInfo.NO_PROFILE_GROUP_ID);
+ boolean sameGroup = (userGroupId != UserInfo.NO_PROFILE_GROUP_ID)
+ && (userGroupId == startedUserGroupId);
+ // userId has already been added
+ boolean sameUserId = startedUserId == userId;
+ if (!sameGroup || sameUserId) {
+ continue;
+ }
+ userIds.add(startedUserId);
+ }
+ }
+ return userIds.toArray();
+ }
+
private void forceStopUserLocked(int userId, String reason) {
mService.forceStopPackageLocked(null, -1, false, false, true, false, false,
userId, reason);
@@ -362,7 +428,6 @@
null, false, false, MY_PID, SYSTEM_UID, UserHandle.USER_ALL);
}
-
/**
* Stops the guest user if it has gone to the background.
*/
@@ -380,7 +445,7 @@
UserInfo userInfo = getUserInfo(oldUserId);
if (userInfo.isGuest()) {
// This is a user to be stopped.
- stopUserLocked(oldUserId, null);
+ stopUsersLocked(oldUserId, true, null);
break;
}
}
@@ -476,7 +541,7 @@
// If the user we are switching to is not currently started, then
// we need to start it now.
if (mStartedUsers.get(userId) == null) {
- mStartedUsers.put(userId, new UserState(new UserHandle(userId)));
+ mStartedUsers.put(userId, new UserState(UserHandle.of(userId)));
updateStartedUserArrayLocked();
needStart = true;
}
@@ -695,6 +760,24 @@
mUserSwitchObservers.finishBroadcast();
}
+ private void stopBackgroundUsersIfEnforced(int oldUserId) {
+ // Never stop system user
+ if (oldUserId == UserHandle.USER_SYSTEM) {
+ return;
+ }
+ // For now, only check for user restriction. Additional checks can be added here
+ boolean disallowRunInBg = hasUserRestriction(UserManager.DISALLOW_RUN_IN_BACKGROUND,
+ oldUserId);
+ if (!disallowRunInBg) {
+ return;
+ }
+ synchronized (mService) {
+ if (DEBUG_MU) Slog.i(TAG, "stopBackgroundUsersIfEnforced stopping " + oldUserId
+ + " and related users");
+ stopUsersLocked(oldUserId, false, null);
+ }
+ }
+
void timeoutUserSwitch(UserState uss, int oldUserId, int newUserId) {
synchronized (mService) {
Slog.wtf(TAG, "User switch timeout: from " + oldUserId + " to " + newUserId);
@@ -747,7 +830,7 @@
}
void continueUserSwitch(UserState uss, int oldUserId, int newUserId) {
- completeSwitchAndInitialize(uss, newUserId, false, true);
+ completeSwitchAndInitialize(uss, oldUserId, newUserId, false, true);
}
void onUserInitialized(UserState uss, boolean foreground, int oldUserId, int newUserId) {
@@ -756,10 +839,10 @@
moveUserToForegroundLocked(uss, oldUserId, newUserId);
}
}
- completeSwitchAndInitialize(uss, newUserId, true, false);
+ completeSwitchAndInitialize(uss, oldUserId, newUserId, true, false);
}
- void completeSwitchAndInitialize(UserState uss, int newUserId,
+ void completeSwitchAndInitialize(UserState uss, int oldUserId, int newUserId,
boolean clearInitializing, boolean clearSwitching) {
boolean unfrozen = false;
synchronized (mService) {
@@ -781,6 +864,7 @@
newUserId, 0));
}
stopGuestUserIfBackground();
+ stopBackgroundUsersIfEnforced(oldUserId);
}
void moveUserToForegroundLocked(UserState uss, int oldUserId, int newUserId) {
@@ -1033,12 +1117,11 @@
if ((flags & ActivityManager.FLAG_OR_STOPPED) != 0) {
return true;
}
- if ((flags & ActivityManager.FLAG_AND_LOCKED) != 0) {
- // If user is currently locked, we fall through to default "running"
- // behavior below
- if (state.unlocked) {
- return false;
- }
+ if ((flags & ActivityManager.FLAG_AND_LOCKED) != 0 && state.unlocked) {
+ return false;
+ }
+ if ((flags & ActivityManager.FLAG_AND_UNLOCKED) != 0 && !state.unlocked) {
+ return false;
}
return state.mState != UserState.STATE_STOPPING
&& state.mState != UserState.STATE_SHUTDOWN;
@@ -1074,6 +1157,10 @@
return mCurrentUserId;
}
+ private boolean isCurrentUserLocked(int userId) {
+ return mCurrentUserId == userId || mTargetUserId == userId;
+ }
+
int setTargetUserIdLocked(int targetUserId) {
return mTargetUserId = targetUserId;
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 38893b8..e0b7370 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1634,6 +1634,14 @@
}
@Override
+ public boolean removeAutomaticZenRules(String packageName) throws RemoteException {
+ Preconditions.checkNotNull(packageName, "Package name is null");
+ enforceSystemOrSystemUI("removeAutomaticZenRules");
+
+ return mZenModeHelper.removeAutomaticZenRules(packageName, "removeAutomaticZenRules");
+ }
+
+ @Override
public void setInterruptionFilter(String pkg, int filter) throws RemoteException {
enforcePolicyAccess(pkg, "setInterruptionFilter");
final int zen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index dbdc3f4..3c891df 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -41,6 +41,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.Process;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings.Global;
@@ -274,7 +275,7 @@
newConfig = mConfig.copy();
}
final String ruleId = automaticZenRule.getId();
- ZenModeConfig.ZenRule rule = new ZenModeConfig.ZenRule();
+ ZenModeConfig.ZenRule rule;
if (ruleId == null) {
throw new IllegalArgumentException("Rule doesn't exist");
} else {
@@ -307,13 +308,32 @@
return setConfig(newConfig, reason, true);
}
+ public boolean removeAutomaticZenRules(String packageName, String reason) {
+ ZenModeConfig newConfig;
+ synchronized (mConfig) {
+ if (mConfig == null) return false;
+ newConfig = mConfig.copy();
+ }
+ for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
+ ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
+ if (rule.component.getPackageName().equals(packageName)
+ && canManageAutomaticZenRule(rule)) {
+ newConfig.automaticRules.removeAt(i);
+ }
+ }
+ return setConfig(newConfig, reason, true);
+ }
+
public boolean canManageAutomaticZenRule(ZenRule rule) {
- if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
+ return true;
+ } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
== PackageManager.PERMISSION_GRANTED) {
return true;
} else {
- String[] packages = mContext.getPackageManager().getPackagesForUid(
- Binder.getCallingUid());
+ String[] packages =
+ mContext.getPackageManager().getPackagesForUid(Binder.getCallingUid());
if (packages != null) {
final int packageCount = packages.length;
for (int i = 0; i < packageCount; i++) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index da10a94..b31d731 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -869,10 +869,8 @@
mHandler.post(new Runnable() {
@Override
public void run() {
- synchronized (mRestrictionsLock) {
- UserRestrictionsUtils.applyUserRestrictionsLR(
- mContext, userId, newRestrictionsFinal, prevRestrictionsFinal);
- }
+ UserRestrictionsUtils.applyUserRestrictions(
+ mContext, userId, newRestrictionsFinal, prevRestrictionsFinal);
final UserRestrictionsListener[] listeners;
synchronized (mUserRestrictionsListeners) {
@@ -1811,8 +1809,8 @@
if (DBG) Slog.i(LOG_TAG, "Stopping user " + userHandle);
int res;
try {
- res = ActivityManagerNative.getDefault().stopUser(userHandle,
- new IStopUserCallback.Stub() {
+ res = ActivityManagerNative.getDefault().stopUser(userHandle, /* force= */ true,
+ new IStopUserCallback.Stub() {
@Override
public void userStopped(int userId) {
finishRemoveUser(userId);
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 77abd3e..816903e 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -22,11 +22,14 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
import android.content.ContentResolver;
import android.content.Context;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
+import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
@@ -84,7 +87,8 @@
UserManager.DISALLOW_SAFE_BOOT,
UserManager.ALLOW_PARENT_PROFILE_APP_LINKING,
UserManager.DISALLOW_RECORD_AUDIO,
- UserManager.DISALLOW_CAMERA
+ UserManager.DISALLOW_CAMERA,
+ UserManager.DISALLOW_RUN_IN_BACKGROUND
);
/**
@@ -126,6 +130,7 @@
*/
private static final Set<String> GLOBAL_RESTRICTIONS = Sets.newArraySet(
UserManager.DISALLOW_ADJUST_VOLUME,
+ UserManager.DISALLOW_RUN_IN_BACKGROUND,
UserManager.DISALLOW_UNMUTE_MICROPHONE
);
@@ -263,34 +268,28 @@
* Takes a new use restriction set and the previous set, and apply the restrictions that have
* changed.
*
- * <p>Note this method is called by {@link UserManagerService} while holding
- * {@code mRestrictionLock}. Be aware when calling into other services, which could cause
- * a deadlock.
+ * <p>Note this method is called by {@link UserManagerService} without holding any locks.
*/
- public static void applyUserRestrictionsLR(Context context, int userId,
+ public static void applyUserRestrictions(Context context, int userId,
Bundle newRestrictions, Bundle prevRestrictions) {
for (String key : USER_RESTRICTIONS) {
final boolean newValue = newRestrictions.getBoolean(key);
final boolean prevValue = prevRestrictions.getBoolean(key);
if (newValue != prevValue) {
- applyUserRestrictionLR(context, userId, key, newValue);
+ applyUserRestriction(context, userId, key, newValue);
}
}
}
-
+
/**
* Apply each user restriction.
*
- * <p>Note this method is called by {@link UserManagerService} while holding
- * {@code mRestrictionLock}. Be aware when calling into other services, which could cause
- * a deadlock.
- *
* <p>See also {@link
* com.android.providers.settings.SettingsProvider#isGlobalOrSecureSettingRestrictedForUser},
* which should be in sync with this method.
*/
- private static void applyUserRestrictionLR(Context context, int userId, String key,
+ private static void applyUserRestriction(Context context, int userId, String key,
boolean newValue) {
if (UserManagerService.DBG) {
Log.d(TAG, "Applying user restriction: userId=" + userId
@@ -365,6 +364,17 @@
userId);
}
break;
+ case UserManager.DISALLOW_RUN_IN_BACKGROUND:
+ if (newValue) {
+ int currentUser = ActivityManager.getCurrentUser();
+ if (currentUser != userId && userId != UserHandle.USER_SYSTEM) {
+ try {
+ ActivityManagerNative.getDefault().stopUser(userId, false, null);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+ }
}
} finally {
Binder.restoreCallingIdentity(id);
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 3301c49..3d00e02 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -269,6 +269,10 @@
return candidate;
}
+ boolean stackCanReceiveKeys() {
+ return (windows.size() > 0) ? windows.get(windows.size() - 1).stackCanReceiveKeys() : false;
+ }
+
boolean isVisible() {
final int N = allAppWindows.size();
for (int i=0; i<N; i++) {
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 116c16e..611ad40 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -702,26 +702,4 @@
}
return false;
}
-
- /**
- * Returns true if this stack has a window that is fully visible, doesn't perform an entry
- * animation and is just positioned where it's supposed to be.
- */
- boolean hasWindowWithFinalVisibility() {
- for (int i = mTasks.size() - 1; i >= 0; i--) {
- Task task = mTasks.get(i);
- for (int j = task.mAppTokens.size() - 1; j >= 0; j--) {
- final AppWindowToken token = task.mAppTokens.get(j);
- if (token.mAppAnimator.animating || token.mWillReplaceWindow) {
- continue;
- }
- WindowState win = token.findMainWindow();
- if (win != null && !win.mWinAnimator.mEnterAnimationPending
- && !win.mWinAnimator.mEnteringAnimation) {
- return true;
- }
- }
- }
- return false;
- }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index dab195f..1bb5ad0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2528,10 +2528,12 @@
+ "attached to a parent win=" + win);
}
- win.mFrame.left = left;
- win.mFrame.top = top;
- win.mFrame.right = right;
- win.mFrame.bottom = bottom;
+ win.mAttrs.x = left;
+ win.mAttrs.y = top;
+ win.mAttrs.width = right - left;
+ win.mAttrs.height = bottom - top;
+
+ win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
win.mWinAnimator.computeShownFrameLocked();
@@ -9129,8 +9131,9 @@
if (wtoken == token) {
break;
}
- if (mFocusedApp == token) {
- // Whoops, we are below the focused app... no focus for you!
+ if (mFocusedApp == token && token.stackCanReceiveKeys()) {
+ // Whoops, we are below the focused app whose stack can receive keys...
+ // No focus for you!!!
if (localLOGV || DEBUG_FOCUS_LIGHT) Slog.v(TAG,
"findFocusedWindow: Reached focused app=" + mFocusedApp);
return null;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 29cadf3..cfa2bb3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -56,6 +56,7 @@
import java.io.PrintWriter;
import java.util.ArrayList;
+import static android.app.ActivityManager.StackId;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
@@ -1564,13 +1565,17 @@
}
}
- /**
- * @return true if this window desires key events.
- */
- public final boolean canReceiveKeys() {
+ /** @return true if this window desires key events. */
+ boolean canReceiveKeys() {
return isVisibleOrAdding()
&& (mViewVisibility == View.VISIBLE)
- && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
+ && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
+ && stackCanReceiveKeys();
+ }
+
+ boolean stackCanReceiveKeys() {
+ final TaskStack stack = getStack();
+ return stack != null && StackId.canReceiveKeys(stack.mStackId);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 66c7dbb..b4bca3e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -31,7 +31,8 @@
/** Test {@link UserManager} functionality. */
public class UserManagerTest extends AndroidTestCase {
-
+ private static final int REMOVE_CHECK_INTERVAL = 500;
+ private static final int REMOVE_TIMEOUT = 60 * 1000;
private UserManager mUserManager = null;
private final Object mUserLock = new Object();
private List<Integer> usersToRemove;
@@ -227,10 +228,16 @@
private void removeUser(int userId) {
synchronized (mUserLock) {
mUserManager.removeUser(userId);
+ long time = System.currentTimeMillis();
while (mUserManager.getUserInfo(userId) != null) {
try {
- mUserLock.wait(500);
+ mUserLock.wait(REMOVE_CHECK_INTERVAL);
} catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ return;
+ }
+ if (System.currentTimeMillis() - time > REMOVE_TIMEOUT) {
+ fail("Timeout waiting for removeUser. userId = " + userId);
}
}
}