Merge "Add findPath method to MtpDocumentsProvider."
diff --git a/Android.mk b/Android.mk
index db63739..b34d2ff 100644
--- a/Android.mk
+++ b/Android.mk
@@ -118,9 +118,10 @@
core/java/android/bluetooth/IBluetoothPan.aidl \
core/java/android/bluetooth/IBluetoothManager.aidl \
core/java/android/bluetooth/IBluetoothManagerCallback.aidl \
+ core/java/android/bluetooth/IBluetoothMap.aidl \
+ core/java/android/bluetooth/IBluetoothMapClient.aidl \
core/java/android/bluetooth/IBluetoothPbap.aidl \
core/java/android/bluetooth/IBluetoothPbapClient.aidl \
- core/java/android/bluetooth/IBluetoothMap.aidl \
core/java/android/bluetooth/IBluetoothSap.aidl \
core/java/android/bluetooth/IBluetoothStateChangeCallback.aidl \
core/java/android/bluetooth/IBluetoothHeadsetClient.aidl \
diff --git a/api/current.txt b/api/current.txt
index 47968de..5077168 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5335,16 +5335,20 @@
}
public final class NotificationChannel implements android.os.Parcelable {
- ctor public NotificationChannel(java.lang.String, java.lang.CharSequence);
+ ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
ctor protected NotificationChannel(android.os.Parcel);
method public boolean canBypassDnd();
method public int describeContents();
- method public android.net.Uri getDefaultRingtone();
method public java.lang.String getId();
method public int getImportance();
+ method public int getLockscreenVisibility();
method public java.lang.CharSequence getName();
- method public void setDefaultRingtone(android.net.Uri);
+ method public android.net.Uri getRingtone();
+ method public void setBypassDnd(boolean);
+ method public void setImportance(int);
method public void setLights(boolean);
+ method public void setLockscreenVisibility(int);
+ method public void setRingtone(android.net.Uri);
method public void setVibration(boolean);
method public boolean shouldShowLights();
method public boolean shouldVibrate();
@@ -5376,7 +5380,6 @@
method public final void setInterruptionFilter(int);
method public void setNotificationPolicy(android.app.NotificationManager.Policy);
method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
- method public void updateNotificationChannel(android.app.NotificationChannel);
field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
@@ -37562,6 +37565,7 @@
method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
+ method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
@@ -37626,6 +37630,12 @@
field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
+ public static abstract class TelephonyManager.OnReceiveUssdResponseCallback {
+ ctor public TelephonyManager.OnReceiveUssdResponseCallback();
+ method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence);
+ method public void onReceiveUssdResponseFailed(java.lang.String, int);
+ }
+
}
package android.telephony.cdma {
diff --git a/api/system-current.txt b/api/system-current.txt
index ff5e8735..35024b7 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5481,22 +5481,23 @@
}
public final class NotificationChannel implements android.os.Parcelable {
- ctor public NotificationChannel(java.lang.String, java.lang.CharSequence);
+ ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
ctor protected NotificationChannel(android.os.Parcel);
method public boolean canBypassDnd();
method public int describeContents();
- method public android.net.Uri getDefaultRingtone();
method public java.lang.String getId();
method public int getImportance();
method public int getLockscreenVisibility();
method public java.lang.CharSequence getName();
+ method public android.net.Uri getRingtone();
+ method public int getUserLockedFields();
+ method public void lockFields(int);
method public void populateFromXml(org.xmlpull.v1.XmlPullParser);
method public void setBypassDnd(boolean);
- method public void setDefaultRingtone(android.net.Uri);
method public void setImportance(int);
method public void setLights(boolean);
method public void setLockscreenVisibility(int);
- method public void setName(java.lang.CharSequence);
+ method public void setRingtone(android.net.Uri);
method public void setVibration(boolean);
method public boolean shouldShowLights();
method public boolean shouldVibrate();
@@ -5505,6 +5506,12 @@
method public void writeXml(org.xmlpull.v1.XmlSerializer) throws java.io.IOException;
field public static final android.os.Parcelable.Creator<android.app.NotificationChannel> CREATOR;
field public static final java.lang.String DEFAULT_CHANNEL_ID = "miscellaneous";
+ field public static final int USER_LOCKED_IMPORTANCE = 4; // 0x4
+ field public static final int USER_LOCKED_LIGHTS = 8; // 0x8
+ field public static final int USER_LOCKED_PRIORITY = 1; // 0x1
+ field public static final int USER_LOCKED_RINGTONE = 32; // 0x20
+ field public static final int USER_LOCKED_VIBRATION = 16; // 0x10
+ field public static final int USER_LOCKED_VISIBILITY = 2; // 0x2
}
public class NotificationManager {
@@ -5530,7 +5537,6 @@
method public final void setInterruptionFilter(int);
method public void setNotificationPolicy(android.app.NotificationManager.Policy);
method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
- method public void updateNotificationChannel(android.app.NotificationChannel);
field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
@@ -40702,6 +40708,7 @@
method public void listen(android.telephony.PhoneStateListener, int);
method public boolean needsOtaServiceProvisioning();
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
+ method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
method public void setDataEnabled(boolean);
method public void setDataEnabled(int, boolean);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
@@ -40792,6 +40799,12 @@
field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
+ public static abstract class TelephonyManager.OnReceiveUssdResponseCallback {
+ ctor public TelephonyManager.OnReceiveUssdResponseCallback();
+ method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence);
+ method public void onReceiveUssdResponseFailed(java.lang.String, int);
+ }
+
}
package android.telephony.cdma {
diff --git a/api/test-current.txt b/api/test-current.txt
index 907f9a4..acb74e7 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5338,16 +5338,20 @@
}
public final class NotificationChannel implements android.os.Parcelable {
- ctor public NotificationChannel(java.lang.String, java.lang.CharSequence);
+ ctor public NotificationChannel(java.lang.String, java.lang.CharSequence, int);
ctor protected NotificationChannel(android.os.Parcel);
method public boolean canBypassDnd();
method public int describeContents();
- method public android.net.Uri getDefaultRingtone();
method public java.lang.String getId();
method public int getImportance();
+ method public int getLockscreenVisibility();
method public java.lang.CharSequence getName();
- method public void setDefaultRingtone(android.net.Uri);
+ method public android.net.Uri getRingtone();
+ method public void setBypassDnd(boolean);
+ method public void setImportance(int);
method public void setLights(boolean);
+ method public void setLockscreenVisibility(int);
+ method public void setRingtone(android.net.Uri);
method public void setVibration(boolean);
method public boolean shouldShowLights();
method public boolean shouldVibrate();
@@ -5379,7 +5383,6 @@
method public final void setInterruptionFilter(int);
method public void setNotificationPolicy(android.app.NotificationManager.Policy);
method public boolean updateAutomaticZenRule(java.lang.String, android.app.AutomaticZenRule);
- method public void updateNotificationChannel(android.app.NotificationChannel);
field public static final java.lang.String ACTION_INTERRUPTION_FILTER_CHANGED = "android.app.action.INTERRUPTION_FILTER_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
field public static final java.lang.String ACTION_NOTIFICATION_POLICY_CHANGED = "android.app.action.NOTIFICATION_POLICY_CHANGED";
@@ -37644,6 +37647,7 @@
method public boolean isWorldPhone();
method public void listen(android.telephony.PhoneStateListener, int);
method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
+ method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.OnReceiveUssdResponseCallback, android.os.Handler);
method public boolean setLine1NumberForDisplay(java.lang.String, java.lang.String);
method public boolean setOperatorBrandOverride(java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
@@ -37708,6 +37712,12 @@
field public static final java.lang.String VVM_TYPE_OMTP = "vvm_type_omtp";
}
+ public static abstract class TelephonyManager.OnReceiveUssdResponseCallback {
+ ctor public TelephonyManager.OnReceiveUssdResponseCallback();
+ method public void onReceiveUssdResponse(java.lang.String, java.lang.CharSequence);
+ method public void onReceiveUssdResponseFailed(java.lang.String, int);
+ }
+
}
package android.telephony.cdma {
diff --git a/cmds/am/am b/cmds/am/am
index 1d426bc..54c2d39 100755
--- a/cmds/am/am
+++ b/cmds/am/am
@@ -1,9 +1,9 @@
#!/system/bin/sh
-#
-# Script to start "am" on the device, which has a very rudimentary
-# shell.
-#
-base=/system
-export CLASSPATH=$base/framework/am.jar
-exec app_process $base/bin com.android.commands.am.Am "$@"
+if [ "$1" != "instrument" ] ; then
+ cmd activity "$@"
+else
+ base=/system
+ export CLASSPATH=$base/framework/am.jar
+ exec app_process $base/bin com.android.commands.am.Am "$@"
+fi
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 91a4549..470a0fa 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -84,34 +84,9 @@
public class Am extends BaseCommand {
- private static final String SHELL_PACKAGE_NAME = "com.android.shell";
-
- // Is the object moving in a positive direction?
- private static final boolean MOVING_FORWARD = true;
- // Is the object moving in the horizontal plan?
- private static final boolean MOVING_HORIZONTALLY = true;
- // Is the object current point great then its target point?
- private static final boolean GREATER_THAN_TARGET = true;
- // Amount we reduce the stack size by when testing a task re-size.
- private static final int STACK_BOUNDS_INSET = 10;
-
- public static final String NO_CLASS_ERROR_CODE = "Error type 3";
private IActivityManager mAm;
private IPackageManager mPm;
- private int mStartFlags = 0;
- private boolean mWaitOption = false;
- private boolean mStopOption = false;
-
- private int mRepeat = 0;
- private int mUserId;
- private String mReceiverPermission;
-
- private String mProfileFile;
- private int mSamplingInterval;
- private boolean mAutoStop;
- private int mStackId;
-
/**
* Command-line entry point.
*
@@ -123,249 +98,11 @@
@Override
public void onShowUsage(PrintStream out) {
- PrintWriter pw = new PrintWriter(out);
- pw.println(
- "usage: am [subcommand] [options]\n" +
- "usage: am start [-D] [-N] [-W] [-P <FILE>] [--start-profiler <FILE>]\n" +
- " [--sampling INTERVAL] [-R COUNT] [-S]\n" +
- " [--track-allocation] [--user <USER_ID> | current] <INTENT>\n" +
- " am startservice [--user <USER_ID> | current] <INTENT>\n" +
- " am stopservice [--user <USER_ID> | current] <INTENT>\n" +
- " am force-stop [--user <USER_ID> | all | current] <PACKAGE>\n" +
- " am kill [--user <USER_ID> | all | current] <PACKAGE>\n" +
- " am kill-all\n" +
- " am broadcast [--user <USER_ID> | all | current] <INTENT>\n" +
- " am instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]\n" +
- " [--user <USER_ID> | current]\n" +
- " [--no-window-animation] [--abi <ABI>] <COMPONENT>\n" +
- " am profile start [--user <USER_ID> current] [--sampling INTERVAL] <PROCESS> <FILE>\n" +
- " am profile stop [--user <USER_ID> current] [<PROCESS>]\n" +
- " am dumpheap [--user <USER_ID> current] [-n] <PROCESS> <FILE>\n" +
- " am set-debug-app [-w] [--persistent] <PACKAGE>\n" +
- " am clear-debug-app\n" +
- " am set-watch-heap <PROCESS> <MEM-LIMIT>\n" +
- " am clear-watch-heap\n" +
- " am bug-report [--progress]\n" +
- " am monitor [--gdb <port>]\n" +
- " am hang [--allow-restart]\n" +
- " am restart\n" +
- " am idle-maintenance\n" +
- " am screen-compat [on|off] <PACKAGE>\n" +
- " am package-importance <PACKAGE>\n" +
- " am to-uri [INTENT]\n" +
- " am to-intent-uri [INTENT]\n" +
- " am to-app-uri [INTENT]\n" +
- " am switch-user <USER_ID>\n" +
- " am start-user <USER_ID>\n" +
- " am unlock-user <USER_ID> [TOKEN_HEX]\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" +
- " am stack resize-animated <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
- " am stack resize-docked-stack <LEFT,TOP,RIGHT,BOTTOM> [<TASK_LEFT,TASK_TOP,TASK_RIGHT,TASK_BOTTOM>]\n" +
- " am stack size-docked-stack-test: <STEP_SIZE> <l|t|r|b> [DELAY_MS]\n" +
- " am stack move-top-activity-to-pinned-stack: <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
- " am stack positiontask <TASK_ID> <STACK_ID> <POSITION>\n" +
- " am stack list\n" +
- " am stack info <STACK_ID>\n" +
- " am stack remove <STACK_ID>\n" +
- " am task lock <TASK_ID>\n" +
- " am task lock stop\n" +
- " am task resizeable <TASK_ID> [0 (unresizeable) | 1 (crop_windows) | 2 (resizeable) | 3 (resizeable_and_pipable)]\n" +
- " am task resize <TASK_ID> <LEFT,TOP,RIGHT,BOTTOM>\n" +
- " am task drag-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS] \n" +
- " am task size-task-test <TASK_ID> <STEP_SIZE> [DELAY_MS] \n" +
- " am get-config\n" +
- " am suppress-resize-config-changes <true|false>\n" +
- " am set-inactive [--user <USER_ID>] <PACKAGE> true|false\n" +
- " am get-inactive [--user <USER_ID>] <PACKAGE>\n" +
- " am send-trim-memory [--user <USER_ID>] <PROCESS>\n" +
- " [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]\n" +
- " am get-current-user\n" +
- "\n" +
- "am start: start an Activity. Options are:\n" +
- " -D: enable debugging\n" +
- " -N: enable native debugging\n" +
- " -W: wait for launch to complete\n" +
- " --start-profiler <FILE>: start profiler and send results to <FILE>\n" +
- " --sampling INTERVAL: use sample profiling with INTERVAL microseconds\n" +
- " between samples (use with --start-profiler)\n" +
- " -P <FILE>: like above, but profiling stops when app goes idle\n" +
- " -R: repeat the activity launch <COUNT> times. Prior to each repeat,\n" +
- " the top activity will be finished.\n" +
- " -S: force stop the target app before starting the activity\n" +
- " --track-allocation: enable tracking of object allocations\n" +
- " --user <USER_ID> | current: Specify which user to run as; if not\n" +
- " specified then run as the current user.\n" +
- " --stack <STACK_ID>: Specify into which stack should the activity be put.\n" +
- "\n" +
- "am startservice: start a Service. Options are:\n" +
- " --user <USER_ID> | current: Specify which user to run as; if not\n" +
- " specified then run as the current user.\n" +
- "\n" +
- "am stopservice: stop a Service. Options are:\n" +
- " --user <USER_ID> | current: Specify which user to run as; if not\n" +
- " specified then run as the current user.\n" +
- "\n" +
- "am force-stop: force stop everything associated with <PACKAGE>.\n" +
- " --user <USER_ID> | all | current: Specify user to force stop;\n" +
- " all users if not specified.\n" +
- "\n" +
- "am kill: Kill all processes associated with <PACKAGE>. Only kills.\n" +
- " processes that are safe to kill -- that is, will not impact the user\n" +
- " experience.\n" +
- " --user <USER_ID> | all | current: Specify user whose processes to kill;\n" +
- " all users if not specified.\n" +
- "\n" +
- "am kill-all: Kill all background processes.\n" +
- "\n" +
- "am broadcast: send a broadcast Intent. Options are:\n" +
- " --user <USER_ID> | all | current: Specify which user to send to; if not\n" +
- " specified then send to all users.\n" +
- " --receiver-permission <PERMISSION>: Require receiver to hold permission.\n" +
- "\n" +
- "am instrument: start an Instrumentation. Typically this target <COMPONENT>\n" +
- " is the form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there \n" +
- " is only one instrumentation. Options are:\n" +
- " -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with\n" +
- " [-e perf true] to generate raw output for performance measurements.\n" +
- " -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a\n" +
- " common form is [-e <testrunner_flag> <value>[,<value>...]].\n" +
- " -p <FILE>: write profiling data to <FILE>\n" +
- " -m: Write output as protobuf (machine readable)\n" +
- " -w: wait for instrumentation to finish before returning. Required for\n" +
- " test runners.\n" +
- " --user <USER_ID> | current: Specify user instrumentation runs in;\n" +
- " current user if not specified.\n" +
- " --no-window-animation: turn off window animations while running.\n" +
- " --abi <ABI>: Launch the instrumented process with the selected ABI.\n" +
- " This assumes that the process supports the selected ABI.\n" +
- "\n" +
- "am trace-ipc: Trace IPC transactions.\n" +
- " start: start tracing IPC transactions.\n" +
- " stop: stop tracing IPC transactions and dump the results to file.\n" +
- " --dump-file <FILE>: Specify the file the trace should be dumped to.\n" +
- "\n" +
- "am profile: start and stop profiler on a process. The given <PROCESS> argument\n" +
- " may be either a process name or pid. Options are:\n" +
- " --user <USER_ID> | current: When supplying a process name,\n" +
- " specify user of process to profile; uses current user if not specified.\n" +
- "\n" +
- "am dumpheap: dump the heap of a process. The given <PROCESS> argument may\n" +
- " be either a process name or pid. Options are:\n" +
- " -n: dump native heap instead of managed heap\n" +
- " --user <USER_ID> | current: When supplying a process name,\n" +
- " specify user of process to dump; uses current user if not specified.\n" +
- "\n" +
- "am set-debug-app: set application <PACKAGE> to debug. Options are:\n" +
- " -w: wait for debugger when application starts\n" +
- " --persistent: retain this value\n" +
- "\n" +
- "am clear-debug-app: clear the previously set-debug-app.\n" +
- "\n" +
- "am set-watch-heap: start monitoring pss size of <PROCESS>, if it is at or\n" +
- " above <HEAP-LIMIT> then a heap dump is collected for the user to report\n" +
- "\n" +
- "am clear-watch-heap: clear the previously set-watch-heap.\n" +
- "\n" +
- "am bug-report: request bug report generation; will launch a notification\n" +
- " when done to select where it should be delivered. Options are: \n" +
- " --progress: will launch a notification right away to show its progress.\n" +
- "\n" +
- "am monitor: start monitoring for crashes or ANRs.\n" +
- " --gdb: start gdbserv on the given port at crash/ANR\n" +
- "\n" +
- "am hang: hang the system.\n" +
- " --allow-restart: allow watchdog to perform normal system restart\n" +
- "\n" +
- "am restart: restart the user-space system.\n" +
- "\n" +
- "am idle-maintenance: perform idle maintenance now.\n" +
- "\n" +
- "am screen-compat: control screen compatibility mode of <PACKAGE>.\n" +
- "\n" +
- "am package-importance: print current importance of <PACKAGE>.\n" +
- "\n" +
- "am to-uri: print the given Intent specification as a URI.\n" +
- "\n" +
- "am to-intent-uri: print the given Intent specification as an intent: URI.\n" +
- "\n" +
- "am to-app-uri: print the given Intent specification as an android-app: URI.\n" +
- "\n" +
- "am switch-user: switch to put USER_ID in the foreground, starting\n" +
- " execution of that user if it is currently stopped.\n" +
- "\n" +
- "am start-user: start USER_ID in background if it is currently stopped,\n" +
- " use switch-user if you want to start the user in foreground.\n" +
- "\n" +
- "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" +
- "am stack movetask: move <TASK_ID> from its current stack to the top (true) or" +
- " bottom (false) of <STACK_ID>.\n" +
- "\n" +
- "am stack resize: change <STACK_ID> size and position to <LEFT,TOP,RIGHT,BOTTOM>.\n" +
- "\n" +
- "am stack resize-docked-stack: change docked stack to <LEFT,TOP,RIGHT,BOTTOM>\n" +
- " and supplying temporary different task bounds indicated by\n" +
- " <TASK_LEFT,TOP,RIGHT,BOTTOM>\n" +
- "\n" +
- "am stack size-docked-stack-test: test command for sizing docked stack by\n" +
- " <STEP_SIZE> increments from the side <l>eft, <t>op, <r>ight, or <b>ottom\n" +
- " applying the optional [DELAY_MS] between each step.\n" +
- "\n" +
- "am stack move-top-activity-to-pinned-stack: moves the top activity from\n" +
- " <STACK_ID> to the pinned stack using <LEFT,TOP,RIGHT,BOTTOM> for the\n" +
- " bounds of the pinned stack.\n" +
- "\n" +
- "am stack positiontask: place <TASK_ID> in <STACK_ID> at <POSITION>" +
- "\n" +
- "am stack list: list all of the activity stacks and their sizes.\n" +
- "\n" +
- "am stack info: display the information about activity stack <STACK_ID>.\n" +
- "\n" +
- "am stack remove: remove stack <STACK_ID>.\n" +
- "\n" +
- "am task lock: bring <TASK_ID> to the front and don't allow other tasks to run.\n" +
- "\n" +
- "am task lock stop: end the current task lock.\n" +
- "\n" +
- "am task resizeable: change resizeable mode of <TASK_ID>.\n" +
- " 0 (unresizeable) | 1 (crop_windows) | 2 (resizeable) | 3 (resizeable_and_pipable)\n" +
- "\n" +
- "am task resize: makes sure <TASK_ID> is in a stack with the specified bounds.\n" +
- " Forces the task to be resizeable and creates a stack if no existing stack\n" +
- " has the specified bounds.\n" +
- "\n" +
- "am task drag-task-test: test command for dragging/moving <TASK_ID> by\n" +
- " <STEP_SIZE> increments around the screen applying the optional [DELAY_MS]\n" +
- " between each step.\n" +
- "\n" +
- "am task size-task-test: test command for sizing <TASK_ID> by <STEP_SIZE>" +
- " increments within the screen applying the optional [DELAY_MS] between\n" +
- " each step.\n" +
- "\n" +
- "am get-config: retrieve the configuration and any recent configurations\n" +
- " of the device.\n" +
- "am suppress-resize-config-changes: suppresses configuration changes due to\n" +
- " user resizing an activity/task.\n" +
- "\n" +
- "am set-inactive: sets the inactive state of an app.\n" +
- "\n" +
- "am get-inactive: returns the inactive state of an app.\n" +
- "\n" +
- "am send-trim-memory: send a memory trim event to a <PROCESS>.\n" +
- "\n" +
- "am get-current-user: returns id of the current foreground user.\n" +
- "\n"
- );
- Intent.printIntentArgsHelp(pw, "");
- pw.flush();
+ try {
+ runAmCmd(new String[] { "help" });
+ } catch (AndroidException e) {
+ e.printStackTrace(System.err);
+ }
}
@Override
@@ -385,9 +122,7 @@
String op = nextArgRequired();
- if (op.equals("broadcast")) {
- sendBroadcast();
- } else if (op.equals("instrument")) {
+ if (op.equals("instrument")) {
runInstrument();
} else {
runAmCmd(getRawArgs());
@@ -458,90 +193,6 @@
}
}
- private Intent makeIntent(int defUser) throws URISyntaxException {
- mStartFlags = 0;
- mWaitOption = false;
- mStopOption = false;
- mRepeat = 0;
- mProfileFile = null;
- mSamplingInterval = 0;
- mAutoStop = false;
- mUserId = defUser;
- mStackId = INVALID_STACK_ID;
-
- return Intent.parseCommandArgs(mArgs, new Intent.CommandOptionHandler() {
- @Override
- public boolean handleOption(String opt, ShellCommand cmd) {
- if (opt.equals("-D")) {
- mStartFlags |= ActivityManager.START_FLAG_DEBUG;
- } else if (opt.equals("-N")) {
- mStartFlags |= ActivityManager.START_FLAG_NATIVE_DEBUGGING;
- } else if (opt.equals("-W")) {
- mWaitOption = true;
- } else if (opt.equals("-P")) {
- mProfileFile = nextArgRequired();
- mAutoStop = true;
- } else if (opt.equals("--start-profiler")) {
- mProfileFile = nextArgRequired();
- mAutoStop = false;
- } else if (opt.equals("--sampling")) {
- mSamplingInterval = Integer.parseInt(nextArgRequired());
- } else if (opt.equals("-R")) {
- mRepeat = Integer.parseInt(nextArgRequired());
- } else if (opt.equals("-S")) {
- mStopOption = true;
- } else if (opt.equals("--track-allocation")) {
- mStartFlags |= ActivityManager.START_FLAG_TRACK_ALLOCATION;
- } else if (opt.equals("--user")) {
- mUserId = UserHandle.parseUserArg(nextArgRequired());
- } else if (opt.equals("--receiver-permission")) {
- mReceiverPermission = nextArgRequired();
- } else if (opt.equals("--stack")) {
- mStackId = Integer.parseInt(nextArgRequired());
- } else {
- return false;
- }
- return true;
- }
- });
- }
-
- private class IntentReceiver extends IIntentReceiver.Stub {
- private boolean mFinished = false;
-
- @Override
- public void performReceive(Intent intent, int resultCode, String data, Bundle extras,
- boolean ordered, boolean sticky, int sendingUser) {
- String line = "Broadcast completed: result=" + resultCode;
- if (data != null) line = line + ", data=\"" + data + "\"";
- if (extras != null) line = line + ", extras: " + extras;
- System.out.println(line);
- synchronized (this) {
- mFinished = true;
- notifyAll();
- }
- }
-
- public synchronized void waitForFinish() {
- try {
- while (!mFinished) wait();
- } catch (InterruptedException e) {
- throw new IllegalStateException(e);
- }
- }
- }
-
- private void sendBroadcast() throws Exception {
- Intent intent = makeIntent(UserHandle.USER_CURRENT);
- IntentReceiver receiver = new IntentReceiver();
- String[] requiredPermissions = mReceiverPermission == null ? null
- : new String[] {mReceiverPermission};
- System.out.println("Broadcasting: " + intent);
- mAm.broadcastIntent(null, intent, null, receiver, 0, null, null, requiredPermissions,
- android.app.AppOpsManager.OP_NONE, null, true, false, mUserId);
- receiver.waitForFinish();
- }
-
public void runInstrument() throws Exception {
Instrument instrument = new Instrument(mAm, mPm);
diff --git a/cmds/appops/appops b/cmds/appops/appops
index 25d2031..5dc85aa 100755
--- a/cmds/appops/appops
+++ b/cmds/appops/appops
@@ -1 +1,2 @@
-cmd appops $@
+#!/system/bin/sh
+cmd appops "$@"
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 3c2efd8..7967e2a 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -74,6 +74,7 @@
static const char LAST_TIME_CHANGED_FILE_PATH[] = "/data/system/time/last_time_change";
static const char ACCURATE_TIME_FLAG_FILE_NAME[] = "time_is_accurate";
static const char ACCURATE_TIME_FLAG_FILE_PATH[] = "/data/system/time/time_is_accurate";
+static const char TIME_FORMAT_12_HOUR_FLAG_FILE_PATH[] = "/data/system/time/time_format_12_hour";
// Java timestamp format. Don't show the clock if the date is before 2000-01-01 00:00:00.
static const long long ACCURATE_TIME_EPOCH = 946684800000;
static constexpr char FONT_BEGIN_CHAR = ' ';
@@ -99,7 +100,7 @@
// ---------------------------------------------------------------------------
BootAnimation::BootAnimation() : Thread(false), mClockEnabled(true), mTimeIsAccurate(false),
- mTimeCheckThread(NULL) {
+ mTimeFormat12Hour(false), mTimeCheckThread(NULL) {
mSession = new SurfaceComposerClient();
// If the system has already booted, the animation is not being used for a boot.
@@ -587,9 +588,10 @@
glBindTexture(GL_TEXTURE_2D, 0);
}
-// We render 24 hour time.
+// We render 12 or 24 hour time.
void BootAnimation::drawClock(const Font& font, const int xPos, const int yPos) {
- static constexpr char TIME_FORMAT[] = "%H:%M";
+ static constexpr char TIME_FORMAT_12[] = "%l:%M";
+ static constexpr char TIME_FORMAT_24[] = "%H:%M";
static constexpr int TIME_LENGTH = 6;
time_t rawtime;
@@ -597,7 +599,8 @@
struct tm* timeInfo = localtime(&rawtime);
char timeBuff[TIME_LENGTH];
- size_t length = strftime(timeBuff, TIME_LENGTH, TIME_FORMAT, timeInfo);
+ const char* timeFormat = mTimeFormat12Hour ? TIME_FORMAT_12 : TIME_FORMAT_24;
+ size_t length = strftime(timeBuff, TIME_LENGTH, timeFormat, timeInfo);
if (length != TIME_LENGTH - 1) {
ALOGE("Couldn't format time; abandoning boot animation clock");
@@ -1059,6 +1062,11 @@
}
struct stat statResult;
+
+ if(stat(TIME_FORMAT_12_HOUR_FLAG_FILE_PATH, &statResult) == 0) {
+ mTimeFormat12Hour = true;
+ }
+
if(stat(ACCURATE_TIME_FLAG_FILE_PATH, &statResult) == 0) {
mTimeIsAccurate = true;
return true;
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 42759f1..7a2e4c2 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -152,6 +152,7 @@
sp<Surface> mFlingerSurface;
bool mClockEnabled;
bool mTimeIsAccurate;
+ bool mTimeFormat12Hour;
bool mSystemBoot;
String8 mZipFileName;
SortedVector<String8> mLoadedFiles;
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 0ba937a..1ee31d8 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -17,6 +17,7 @@
package android.app;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.IIntentSender;
import android.content.Intent;
@@ -179,4 +180,13 @@
* (-1).
*/
public abstract int getUidProcessState(int uid);
+
+ /**
+ * Called when Keyguard flags might have changed.
+ *
+ * @param callback Callback to run after activity visibilities have been reevaluated. This can
+ * be used from window manager so that when the callback is called, it's
+ * guaranteed that all apps have their visibility updated accordingly.
+ */
+ public abstract void notifyKeyguardFlagsChanged(@Nullable Runnable callback);
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 623a11d..15f6361 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1555,8 +1555,7 @@
case SET_LOCK_SCREEN_SHOWN_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
final boolean showing = data.readInt() != 0;
- final boolean occluded = data.readInt() != 0;
- setLockScreenShown(showing, occluded);
+ setLockScreenShown(showing);
reply.writeNoException();
return true;
}
@@ -2337,13 +2336,6 @@
return true;
}
- case KEYGUARD_WAITING_FOR_ACTIVITY_DRAWN_TRANSACTION: {
- data.enforceInterface(IActivityManager.descriptor);
- keyguardWaitingForActivityDrawn();
- reply.writeNoException();
- return true;
- }
-
case KEYGUARD_GOING_AWAY_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
keyguardGoingAway(data.readInt());
@@ -5035,13 +5027,12 @@
reply.recycle();
return pfd;
}
- public void setLockScreenShown(boolean showing, boolean occluded) throws RemoteException
+ public void setLockScreenShown(boolean showing) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(showing ? 1 : 0);
- data.writeInt(occluded ? 1 : 0);
mRemote.transact(SET_LOCK_SCREEN_SHOWN_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
@@ -6060,16 +6051,6 @@
reply.recycle();
}
- public void keyguardWaitingForActivityDrawn() throws RemoteException {
- Parcel data = Parcel.obtain();
- Parcel reply = Parcel.obtain();
- data.writeInterfaceToken(IActivityManager.descriptor);
- mRemote.transact(KEYGUARD_WAITING_FOR_ACTIVITY_DRAWN_TRANSACTION, data, reply, 0);
- reply.readException();
- data.recycle();
- reply.recycle();
- }
-
public void keyguardGoingAway(int flags)
throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 7b25c76..0323651 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -357,8 +357,7 @@
public void killPackageDependents(final String packageName, int userId) throws RemoteException;
public void forceStopPackage(final String packageName, int userId) throws RemoteException;
- // Note: probably don't want to allow applications access to these.
- public void setLockScreenShown(boolean showing, boolean occluded) throws RemoteException;
+ public void setLockScreenShown(boolean showing) throws RemoteException;
public void unhandledBack() throws RemoteException;
public ParcelFileDescriptor openContentUri(Uri uri) throws RemoteException;
@@ -518,8 +517,6 @@
public void showBootMessage(CharSequence msg, boolean always) throws RemoteException;
- public void keyguardWaitingForActivityDrawn() throws RemoteException;
-
/**
* Notify the system that the keyguard is going away.
*
@@ -1017,7 +1014,6 @@
int NOTIFY_LAUNCH_TASK_BEHIND_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+228;
int START_ACTIVITY_FROM_RECENTS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 229;
int NOTIFY_ENTER_ANIMATION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+230;
- int KEYGUARD_WAITING_FOR_ACTIVITY_DRAWN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+231;
int START_ACTIVITY_AS_CALLER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+232;
int ADD_APP_TASK_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+233;
int GET_APP_TASK_THUMBNAIL_SIZE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+234;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index c87eef9..ee81c58 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -59,7 +59,6 @@
int getPackageImportance(String pkg);
void createNotificationChannel(String pkg, in NotificationChannel channel);
- void updateNotificationChannel(String pkg, in NotificationChannel channel);
void updateNotificationChannelForPackage(String pkg, int uid, in NotificationChannel channel);
NotificationChannel getNotificationChannel(String pkg, String channelId);
NotificationChannel getNotificationChannelForPackage(String pkg, int uid, String channelId);
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 4150172..f259c6d 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
package android.app;
import org.json.JSONException;
@@ -33,12 +48,45 @@
private static final String ATT_IMPORTANCE = "importance";
private static final String ATT_LIGHTS = "lights";
private static final String ATT_VIBRATION = "vibration";
- private static final String ATT_DEFAULT_RINGTONE = "ringtone";
+ private static final String ATT_RINGTONE = "ringtone";
+ private static final String ATT_USER_APPROVED = "approved";
+ private static final String ATT_USER_LOCKED = "locked";
+
+ /**
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_LOCKED_PRIORITY = 0x00000001;
+ /**
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_LOCKED_VISIBILITY = 0x00000002;
+ /**
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_LOCKED_IMPORTANCE = 0x00000004;
+ /**
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_LOCKED_LIGHTS = 0x00000008;
+ /**
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_LOCKED_VIBRATION = 0x00000010;
+ /**
+ * @hide
+ */
+ @SystemApi
+ public static final int USER_LOCKED_RINGTONE = 0x00000020;
private static final int DEFAULT_VISIBILITY =
- NotificationListenerService.Ranking.VISIBILITY_NO_OVERRIDE;
+ NotificationManager.VISIBILITY_NO_OVERRIDE;
private static final int DEFAULT_IMPORTANCE =
- NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+ NotificationManager.IMPORTANCE_UNSPECIFIED;
private final String mId;
private CharSequence mName;
@@ -48,16 +96,21 @@
private Uri mRingtone;
private boolean mLights;
private boolean mVibration;
+ private int mUserLockedFields;
/**
* Creates a notification channel.
*
* @param id The id of the channel. Must be unique per package.
* @param name The user visible name of the channel.
+ * @param importance The importance of the channel. This controls how interruptive notifications
+ * posted to this channel are. See e.g.
+ * {@link NotificationManager#IMPORTANCE_DEFAULT}.
*/
- public NotificationChannel(String id, CharSequence name) {
+ public NotificationChannel(String id, CharSequence name, int importance) {
this.mId = id;
this.mName = name;
+ this.mImportance = importance;
}
protected NotificationChannel(Parcel in) {
@@ -77,6 +130,7 @@
}
mLights = in.readByte() != 0;
mVibration = in.readByte() != 0;
+ mUserLockedFields = in.readInt();
}
@Override
@@ -99,54 +153,67 @@
}
dest.writeByte(mLights ? (byte) 1 : (byte) 0);
dest.writeByte(mVibration ? (byte) 1 : (byte) 0);
- }
-
- // Only modifiable by users.
- /**
- * @hide
- */
- @SystemApi
- public void setName(CharSequence name) {
- this.mName = name;
+ dest.writeInt(mUserLockedFields);
}
/**
* @hide
*/
@SystemApi
- public void setImportance(int importance) {
- this.mImportance = importance;
+ public void lockFields(int field) {
+ mUserLockedFields |= field;
}
+ // Modifiable by a notification ranker.
+
/**
- * @hide
+ * Only modifiable by the system and notification ranker.
+ *
+ * Sets whether or not this notification can interrupt the user in
+ * {@link android.app.NotificationManager.Policy#INTERRUPTION_FILTER_PRIORITY} mode.
*/
- @SystemApi
public void setBypassDnd(boolean bypassDnd) {
this.mBypassDnd = bypassDnd;
}
/**
- * @hide
+ * Only modifiable by the system and notification ranker.
+ *
+ * Sets whether this notification appears on the lockscreen or not, and if so, whether it
+ * appears in a redacted form. See e.g. {@link Notification#VISIBILITY_SECRET}.
*/
- @SystemApi
public void setLockscreenVisibility(int lockscreenVisibility) {
this.mLockscreenVisibility = lockscreenVisibility;
}
+ /**
+ * Only modifiable by the system and notification ranker.
+ *
+ * Sets the level of interruption of this notification channel.
+ *
+ * @param importance the amount the user should be interrupted by notifications from this
+ * channel. See e.g.
+ * {@link android.app.NotificationManager#IMPORTANCE_DEFAULT}.
+ */
+ public void setImportance(int importance) {
+ this.mImportance = importance;
+ }
+
// Modifiable by apps on channel creation.
/**
* Sets the ringtone that should be played for notifications posted to this channel if
- * the notifications don't supply a ringtone. Only modifiable on channel creation.
+ * the notifications don't supply a ringtone. Only modifiable before the channel is submitted
+ * to the NotificationManager.
*/
- public void setDefaultRingtone(Uri defaultRingtone) {
- this.mRingtone = defaultRingtone;
+ public void setRingtone(Uri ringtone) {
+ this.mRingtone = ringtone;
}
/**
* Sets whether notifications posted to this channel should display notification lights,
- * on devices that support that feature. Only modifiable on channel creation.
+ * on devices that support that feature. Only modifiable before the channel is submitted to
+ * the NotificationManager.
*/
public void setLights(boolean lights) {
this.mLights = lights;
@@ -154,7 +221,8 @@
/**
* Sets whether notification posted to this channel should vibrate, even if individual
- * notifications are marked as having vibration only modifiable on channel creation.
+ * notifications are marked as having vibration only modifiable before the channel is submitted
+ * to the NotificationManager.
*/
public void setVibration(boolean vibration) {
this.mVibration = vibration;
@@ -193,7 +261,7 @@
/**
* Returns the notification sound for this channel.
*/
- public Uri getDefaultRingtone() {
+ public Uri getRingtone() {
return mRingtone;
}
@@ -212,9 +280,9 @@
}
/**
- * @hide
+ * Returns whether or not notifications posted to this channel are shown on the lockscreen in
+ * full or redacted form.
*/
- @SystemApi
public int getLockscreenVisibility() {
return mLockscreenVisibility;
}
@@ -223,15 +291,23 @@
* @hide
*/
@SystemApi
+ public int getUserLockedFields() {
+ return mUserLockedFields;
+ }
+
+ /**
+ * @hide
+ */
+ @SystemApi
public void populateFromXml(XmlPullParser parser) {
- // Name and id are set in the constructor.
- setImportance(safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE));
+ // Name, id, and importance are set in the constructor.
setBypassDnd(Notification.PRIORITY_DEFAULT
!= safeInt(parser, ATT_PRIORITY, Notification.PRIORITY_DEFAULT));
setLockscreenVisibility(safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY));
- setDefaultRingtone(safeUri(parser, ATT_DEFAULT_RINGTONE));
+ setRingtone(safeUri(parser, ATT_RINGTONE));
setLights(safeBool(parser, ATT_LIGHTS, false));
setVibration(safeBool(parser, ATT_VIBRATION, false));
+ lockFields(safeInt(parser, ATT_USER_LOCKED, 0));
}
/**
@@ -254,8 +330,8 @@
out.attribute(null, ATT_VISIBILITY,
Integer.toString(getLockscreenVisibility()));
}
- if (getDefaultRingtone() != null) {
- out.attribute(null, ATT_DEFAULT_RINGTONE, getDefaultRingtone().toString());
+ if (getRingtone() != null) {
+ out.attribute(null, ATT_RINGTONE, getRingtone().toString());
}
if (shouldShowLights()) {
out.attribute(null, ATT_LIGHTS, Boolean.toString(shouldShowLights()));
@@ -263,6 +339,10 @@
if (shouldVibrate()) {
out.attribute(null, ATT_VIBRATION, Boolean.toString(shouldVibrate()));
}
+ if (getUserLockedFields() != 0) {
+ out.attribute(null, ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
+ }
+
out.endTag(null, TAG_CHANNEL);
}
@@ -284,11 +364,12 @@
if (getLockscreenVisibility() != DEFAULT_VISIBILITY) {
record.put(ATT_VISIBILITY, Notification.visibilityToString(getLockscreenVisibility()));
}
- if (getDefaultRingtone() != null) {
- record.put(ATT_DEFAULT_RINGTONE, getDefaultRingtone().toString());
+ if (getRingtone() != null) {
+ record.put(ATT_RINGTONE, getRingtone().toString());
}
record.put(ATT_LIGHTS, Boolean.toString(shouldShowLights()));
record.put(ATT_VIBRATION, Boolean.toString(shouldVibrate()));
+ record.put(ATT_USER_LOCKED, Integer.toString(getUserLockedFields()));
return record;
}
@@ -342,15 +423,32 @@
NotificationChannel that = (NotificationChannel) o;
- if (mImportance != that.mImportance) return false;
+ if (getImportance() != that.getImportance()) return false;
if (mBypassDnd != that.mBypassDnd) return false;
- if (mLockscreenVisibility != that.mLockscreenVisibility) return false;
+ if (getLockscreenVisibility() != that.getLockscreenVisibility()) return false;
if (mLights != that.mLights) return false;
if (mVibration != that.mVibration) return false;
- if (!mId.equals(that.mId)) return false;
- if (mName != null ? !mName.equals(that.mName) : that.mName != null) return false;
- return mRingtone != null ? mRingtone.equals(
- that.mRingtone) : that.mRingtone == null;
+ if (getUserLockedFields() != that.getUserLockedFields()) return false;
+ if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null) return false;
+ if (getName() != null ? !getName().equals(that.getName()) : that.getName() != null)
+ return false;
+ return getRingtone() != null ? getRingtone().equals(
+ that.getRingtone()) : that.getRingtone() == null;
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = getId() != null ? getId().hashCode() : 0;
+ result = 31 * result + (getName() != null ? getName().hashCode() : 0);
+ result = 31 * result + getImportance();
+ result = 31 * result + (mBypassDnd ? 1 : 0);
+ result = 31 * result + getLockscreenVisibility();
+ result = 31 * result + (getRingtone() != null ? getRingtone().hashCode() : 0);
+ result = 31 * result + (mLights ? 1 : 0);
+ result = 31 * result + (mVibration ? 1 : 0);
+ result = 31 * result + getUserLockedFields();
+ return result;
}
@Override
@@ -361,22 +459,10 @@
", mImportance=" + mImportance +
", mBypassDnd=" + mBypassDnd +
", mLockscreenVisibility=" + mLockscreenVisibility +
- ", mRingtone='" + mRingtone + '\'' +
+ ", mRingtone=" + mRingtone +
", mLights=" + mLights +
", mVibration=" + mVibration +
+ ", mUserLockedFields=" + mUserLockedFields +
'}';
}
-
- @Override
- public int hashCode() {
- int result = mId.hashCode();
- result = 31 * result + (mName != null ? mName.hashCode() : 0);
- result = 31 * result + mImportance;
- result = 31 * result + (mBypassDnd ? 1 : 0);
- result = 31 * result + mLockscreenVisibility;
- result = 31 * result + (mRingtone != null ? mRingtone.hashCode() : 0);
- result = 31 * result + (mLights ? 1 : 0);
- result = 31 * result + (mVibration ? 1 : 0);
- return result;
- }
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 39cd2b5..2234a38 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -181,15 +181,15 @@
public static final int INTERRUPTION_FILTER_UNKNOWN = 0;
/** @hide */
- @IntDef({VISIBILITY_NO_OVERRIDE, IMPORTANCE_UNSPECIFIED, IMPORTANCE_NONE,
- IMPORTANCE_MIN, IMPORTANCE_LOW, IMPORTANCE_DEFAULT, IMPORTANCE_HIGH,
- IMPORTANCE_MAX})
+ @IntDef({IMPORTANCE_UNSPECIFIED, IMPORTANCE_NONE,
+ IMPORTANCE_MIN, IMPORTANCE_LOW, IMPORTANCE_DEFAULT, IMPORTANCE_HIGH})
@Retention(RetentionPolicy.SOURCE)
public @interface Importance {}
/** Value signifying that the user has not expressed a per-app visibility override value.
* @hide */
public static final int VISIBILITY_NO_OVERRIDE = -1000;
+
/**
* Value signifying that the user has not expressed an importance.
*
@@ -214,19 +214,19 @@
public static final int IMPORTANCE_LOW = 2;
/**
- * Default notification importance: shows everywhere, allowed to makes noise,
- * but does not visually intrude.
+ * Default notification importance: shows everywhere, makes noise, but does not visually
+ * intrude.
*/
public static final int IMPORTANCE_DEFAULT = 3;
/**
- * Higher notification importance: shows everywhere, allowed to makes noise and peek.
+ * Higher notification importance: shows everywhere, makes noise and peeks. May use full screen
+ * intents.
*/
public static final int IMPORTANCE_HIGH = 4;
/**
- * Highest notification importance: shows everywhere, allowed to makes noise, peek, and
- * use full screen intents.
+ * Unused.
*/
public static final int IMPORTANCE_MAX = 5;
@@ -402,7 +402,7 @@
}
/**
- * Returns all notification channels created by the calling app.
+ * Returns all notification channels belonging to the calling app.
*/
public List<NotificationChannel> getNotificationChannels() {
INotificationManager service = getService();
@@ -414,18 +414,6 @@
}
/**
- * Updates settings for a given channel.
- */
- public void updateNotificationChannel(NotificationChannel channel) {
- INotificationManager service = getService();
- try {
- service.updateNotificationChannel(mContext.getPackageName(), channel);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
- /**
* Deletes the given notification channel.
*/
public void deleteNotificationChannel(String channelId) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 118e1f3..dcb0d66 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1056,6 +1056,7 @@
* otherwise
*/
public boolean isAdminActive(@NonNull ComponentName admin) {
+ throwIfParentInstance("isAdminActive");
return isAdminActiveAsUser(admin, myUserId());
}
@@ -6145,6 +6146,7 @@
* <li>{@link #getPasswordExpirationTimeout}</li>
* <li>{@link #setPasswordExpirationTimeout}</li>
* <li>{@link #getPasswordExpiration}</li>
+ * <li>{@link #getPasswordMaximumLength}</li>
* <li>{@link #isActivePasswordSufficient}</li>
* <li>{@link #getCurrentFailedPasswordAttempts}</li>
* <li>{@link #getMaximumFailedPasswordsForWipe}</li>
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 542b06b..bb344a6 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1976,6 +1976,9 @@
} else if (profile == BluetoothProfile.PBAP_CLIENT) {
BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
return true;
+ } else if (profile == BluetoothProfile.MAP_CLIENT) {
+ BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
+ return true;
} else {
return false;
}
@@ -2048,6 +2051,10 @@
BluetoothPbapClient pbapClient = (BluetoothPbapClient)proxy;
pbapClient.close();
break;
+ case BluetoothProfile.MAP_CLIENT:
+ BluetoothMapClient mapClient = (BluetoothMapClient)proxy;
+ mapClient.close();
+ break;
}
}
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
new file mode 100644
index 0000000..4252482
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class provides the APIs to control the Bluetooth MAP MCE Profile.
+ *
+ * @hide
+ */
+public final class BluetoothMapClient implements BluetoothProfile {
+
+ private static final String TAG = "BluetoothMapClient";
+ private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean VDBG = Log.isLoggable(TAG, Log.VERBOSE);
+
+ public static final String ACTION_CONNECTION_STATE_CHANGED =
+ "android.bluetooth.mapmce.profile.action.CONNECTION_STATE_CHANGED";
+ public static final String ACTION_MESSAGE_RECEIVED =
+ "android.bluetooth.mapmce.profile.action.MESSAGE_RECEIVED";
+ /* Actions to be used for pending intents */
+ public static final String ACTION_MESSAGE_SENT_SUCCESSFULLY =
+ "android.bluetooth.mapmce.profile.action.MESSAGE_SENT_SUCCESSFULLY";
+ public static final String ACTION_MESSAGE_DELIVERED_SUCCESSFULLY =
+ "android.bluetooth.mapmce.profile.action.MESSAGE_DELIVERED_SUCCESSFULLY";
+
+ private IBluetoothMapClient mService;
+ private final Context mContext;
+ private ServiceListener mServiceListener;
+ private BluetoothAdapter mAdapter;
+
+ /** There was an error trying to obtain the state */
+ public static final int STATE_ERROR = -1;
+
+ public static final int RESULT_FAILURE = 0;
+ public static final int RESULT_SUCCESS = 1;
+ /** Connection canceled before completion. */
+ public static final int RESULT_CANCELED = 2;
+
+ final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
+ new IBluetoothStateChangeCallback.Stub() {
+ public void onBluetoothStateChange(boolean up) {
+ if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
+ if (!up) {
+ if (VDBG) Log.d(TAG, "Unbinding service...");
+ synchronized (mConnection) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG, "", re);
+ }
+ }
+ } else {
+ synchronized (mConnection) {
+ try {
+ if (mService == null) {
+ if (VDBG) Log.d(TAG, "Binding service...");
+ doBind();
+ }
+ } catch (Exception re) {
+ Log.e(TAG, "", re);
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Create a BluetoothMapClient proxy object.
+ */
+ /*package*/ BluetoothMapClient(Context context, ServiceListener l) {
+ if (DBG) Log.d(TAG, "Create BluetoothMapClient proxy object");
+ mContext = context;
+ mServiceListener = l;
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ }
+ doBind();
+ }
+
+ boolean doBind() {
+ Intent intent = new Intent(IBluetoothMapClient.class.getName());
+ ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
+ intent.setComponent(comp);
+ if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
+ android.os.Process.myUserHandle())) {
+ Log.e(TAG, "Could not bind to Bluetooth MAP MCE Service with " + intent);
+ return false;
+ }
+ return true;
+ }
+
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ /**
+ * Close the connection to the backing service.
+ * Other public functions of BluetoothMap will return default error
+ * results once close() has been called. Multiple invocations of close()
+ * are ok.
+ */
+ public void close() {
+ IBluetoothManager mgr = mAdapter.getBluetoothManager();
+ if (mgr != null) {
+ try {
+ mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
+ } catch (Exception e) {
+ Log.e(TAG, "", e);
+ }
+ }
+
+ synchronized (mConnection) {
+ if (mService != null) {
+ try {
+ mService = null;
+ mContext.unbindService(mConnection);
+ } catch (Exception re) {
+ Log.e(TAG, "", re);
+ }
+ }
+ }
+ mServiceListener = null;
+ }
+
+ /**
+ * Returns true if the specified Bluetooth device is connected.
+ * Returns false if not connected, or if this proxy object is not
+ * currently connected to the Map service.
+ */
+ public boolean isConnected(BluetoothDevice device) {
+ if (VDBG) Log.d(TAG, "isConnected(" + device + ")");
+ if (mService != null) {
+ try {
+ return mService.isConnected(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Initiate connection. Initiation of outgoing connections is not
+ * supported for MAP server.
+ */
+ public boolean connect(BluetoothDevice device) {
+ if (DBG) Log.d(TAG, "connect(" + device + ")" + "for MAPS MCE");
+ if (mService != null) {
+ try {
+ return mService.connect(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ } else {
+ Log.w(TAG, "Proxy not attached to service");
+ if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ return false;
+ }
+
+ /**
+ * Initiate disconnect.
+ *
+ * @param device Remote Bluetooth Device
+ * @return false on error, true otherwise
+ */
+ public boolean disconnect(BluetoothDevice device) {
+ if (DBG) Log.d(TAG, "disconnect(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.disconnect(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Get the list of connected devices. Currently at most one.
+ *
+ * @return list of connected devices
+ */
+ @Override
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (DBG) Log.d(TAG, "getConnectedDevices()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getConnectedDevices();
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return new ArrayList<>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<>();
+ }
+
+ /**
+ * Get the list of devices matching specified states. Currently at most one.
+ *
+ * @return list of matching devices
+ */
+ @Override
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+ if (DBG) Log.d(TAG, "getDevicesMatchingStates()");
+ if (mService != null && isEnabled()) {
+ try {
+ return mService.getDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return new ArrayList<>();
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return new ArrayList<>();
+ }
+
+ /**
+ * Get connection state of device
+ *
+ * @return device connection state
+ */
+ @Override
+ public int getConnectionState(BluetoothDevice device) {
+ if (DBG) Log.d(TAG, "getConnectionState(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.getConnectionState(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ /**
+ * Set priority of the profile
+ *
+ * <p> The device should already be paired. Priority can be one of {@link #PRIORITY_ON} or
+ * {@link #PRIORITY_OFF},
+ *
+ * @param device Paired bluetooth device
+ * @return true if priority is set, false on error
+ */
+ public boolean setPriority(BluetoothDevice device, int priority) {
+ if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ if (priority != BluetoothProfile.PRIORITY_OFF &&
+ priority != BluetoothProfile.PRIORITY_ON) {
+ return false;
+ }
+ try {
+ return mService.setPriority(device, priority);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return false;
+ }
+
+ /**
+ * Get the priority of the profile.
+ *
+ * <p> The priority can be any of:
+ * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
+ * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+ *
+ * @param device Bluetooth device
+ * @return priority of the device
+ */
+ public int getPriority(BluetoothDevice device) {
+ if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
+ if (mService != null && isEnabled() &&
+ isValidDevice(device)) {
+ try {
+ return mService.getPriority(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return PRIORITY_OFF;
+ }
+ }
+ if (mService == null) Log.w(TAG, "Proxy not attached to service");
+ return PRIORITY_OFF;
+ }
+
+ /**
+ * Send a message.
+ *
+ * Send an SMS message to either the contacts primary number or the telephone number specified.
+ *
+ * @param device Bluetooth device
+ * @param contacts Uri[] of the contacts
+ * @param message Message to be sent
+ * @param sentIntent intent issued when message is sent
+ * @param deliveredIntent intent issued when message is delivered
+ * @return true if the message is enqueued, false on error
+ */
+ public boolean sendMessage(BluetoothDevice device, Uri[] contacts, String message,
+ PendingIntent sentIntent, PendingIntent deliveredIntent) {
+ if (DBG) Log.d(TAG, "sendMessage(" + device + ", " + contacts + ", " + message);
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ try {
+ return mService.sendMessage(device, contacts, message, sentIntent, deliveredIntent);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get unread messages. Unread messages will be published via {@link #ACTION_MESSAGE_RECEIVED}.
+ *
+ * @param device Bluetooth device
+ * @return true if the message is enqueued, false on error
+ */
+ public boolean getUnreadMessages(BluetoothDevice device) {
+ if (DBG) Log.d(TAG, "getUnreadMessages(" + device + ")");
+ if (mService != null && isEnabled() && isValidDevice(device)) {
+ try {
+ return mService.getUnreadMessages(device);
+ } catch (RemoteException e) {
+ Log.e(TAG, Log.getStackTraceString(new Throwable()));
+ return false;
+ }
+ }
+ return false;
+ }
+
+ private final ServiceConnection mConnection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ if (DBG) Log.d(TAG, "Proxy object connected");
+ mService = IBluetoothMapClient.Stub.asInterface(service);
+ if (mServiceListener != null) {
+ mServiceListener.onServiceConnected(BluetoothProfile.MAP_CLIENT,
+ BluetoothMapClient.this);
+ }
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ if (DBG) Log.d(TAG, "Proxy object disconnected");
+ mService = null;
+ if (mServiceListener != null) {
+ mServiceListener.onServiceDisconnected(BluetoothProfile.MAP_CLIENT);
+ }
+ }
+ };
+
+ private boolean isEnabled() {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (adapter != null && adapter.getState() == BluetoothAdapter.STATE_ON) return true;
+ if (DBG) Log.d(TAG, "Bluetooth is Not enabled");
+ return false;
+ }
+
+ private boolean isValidDevice(BluetoothDevice device) {
+ if (device == null) return false;
+
+ if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+ return false;
+ }
+
+
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 20d95cc..f363607 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Android Open Source Project
+ * Copyright (C) 2010-2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -137,6 +137,12 @@
public static final int PBAP_CLIENT = 17;
/**
+ * MAP Messaging Client Equipment (MCE)
+ * @hide
+ */
+ public static final int MAP_CLIENT = 18;
+
+ /**
* Max profile ID. This value should be updated whenever a new profile is added to match
* the largest value assigned to a profile.
* @hide
diff --git a/core/java/android/bluetooth/IBluetoothMapClient.aidl b/core/java/android/bluetooth/IBluetoothMapClient.aidl
new file mode 100644
index 0000000..df45af9
--- /dev/null
+++ b/core/java/android/bluetooth/IBluetoothMapClient.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+
+import android.app.PendingIntent;
+import android.bluetooth.BluetoothDevice;
+import android.net.Uri;
+
+/**
+ * System private API for Bluetooth MAP MCE service
+ *
+ * {@hide}
+ */
+interface IBluetoothMapClient {
+ boolean connect(in BluetoothDevice device);
+ boolean disconnect(in BluetoothDevice device);
+ boolean isConnected(in BluetoothDevice device);
+ List<BluetoothDevice> getConnectedDevices();
+ List<BluetoothDevice> getDevicesMatchingConnectionStates(in int[] states);
+ int getConnectionState(in BluetoothDevice device);
+ boolean setPriority(in BluetoothDevice device,in int priority);
+ int getPriority(in BluetoothDevice device);
+ boolean sendMessage(in BluetoothDevice device, in Uri[] contacts, in String message,
+ in PendingIntent sentIntent, in PendingIntent deliveryIntent);
+ boolean getUnreadMessages(in BluetoothDevice device);
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 68b7b3a..89c6eb2 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8289,6 +8289,9 @@
BLUETOOTH_MAP_PRIORITY_PREFIX = "bluetooth_map_priority_";
/** {@hide} */
public static final String
+ BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX = "bluetooth_map_client_priority_";
+ /** {@hide} */
+ public static final String
BLUETOOTH_PBAP_CLIENT_PRIORITY_PREFIX = "bluetooth_pbap_client_priority_";
/** {@hide} */
public static final String
@@ -8489,6 +8492,14 @@
}
/**
+ * Get the key that retrieves a bluetooth map client priority.
+ * @hide
+ */
+ public static final String getBluetoothMapClientPriorityKey(String address) {
+ return BLUETOOTH_MAP_CLIENT_PRIORITY_PREFIX + address.toUpperCase(Locale.ROOT);
+ }
+
+ /**
* Get the key that retrieves a bluetooth pbap client priority.
* @hide
*/
@@ -8497,7 +8508,7 @@
}
/**
- * Get the key that retrieves a bluetooth map priority.
+ * Get the key that retrieves a bluetooth sap priority.
* @hide
*/
public static final String getBluetoothSapPriorityKey(String address) {
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index e6f58f5..e606ebf 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -1037,60 +1037,6 @@
* @hide */
public static final int VISIBILITY_NO_OVERRIDE = NotificationManager.VISIBILITY_NO_OVERRIDE;
- /**
- * Value signifying that the user has not expressed an importance.
- *
- * This value is for persisting preferences, and should never be associated with
- * an actual notification.
- *
- * @hide
- */
- public static final int IMPORTANCE_UNSPECIFIED = NotificationManager.IMPORTANCE_UNSPECIFIED;
-
- /**
- * A notification with no importance: shows nowhere, is blocked.
- *
- * @hide
- */
- public static final int IMPORTANCE_NONE = NotificationManager.IMPORTANCE_NONE;
-
- /**
- * Min notification importance: only shows in the shade, below the fold.
- *
- * @hide
- */
- public static final int IMPORTANCE_MIN = NotificationManager.IMPORTANCE_MIN;
-
- /**
- * Low notification importance: shows everywhere, but is not intrusive.
- *
- * @hide
- */
- public static final int IMPORTANCE_LOW = NotificationManager.IMPORTANCE_LOW;
-
- /**
- * Default notification importance: shows everywhere, allowed to makes noise,
- * but does not visually intrude.
- *
- * @hide
- */
- public static final int IMPORTANCE_DEFAULT = NotificationManager.IMPORTANCE_DEFAULT;
-
- /**
- * Higher notification importance: shows everywhere, allowed to makes noise and peek.
- *
- * @hide
- */
- public static final int IMPORTANCE_HIGH = NotificationManager.IMPORTANCE_HIGH;
-
- /**
- * Highest notification importance: shows everywhere, allowed to makes noise, peek, and
- * use full screen intents.
- *
- * @hide
- */
- public static final int IMPORTANCE_MAX = NotificationManager.IMPORTANCE_MAX;
-
private String mKey;
private int mRank = -1;
private boolean mIsAmbient;
@@ -1192,7 +1138,7 @@
CharSequence explanation, String overrideGroupKey) {
mKey = key;
mRank = rank;
- mIsAmbient = importance < IMPORTANCE_LOW;
+ mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW;
mMatchesInterruptionFilter = matchesInterruptionFilter;
mVisibilityOverride = visibilityOverride;
mSuppressedVisualEffects = suppressedVisualEffects;
@@ -1206,20 +1152,19 @@
*/
public static String importanceToString(int importance) {
switch (importance) {
- case IMPORTANCE_UNSPECIFIED:
+ case NotificationManager.IMPORTANCE_UNSPECIFIED:
return "UNSPECIFIED";
- case IMPORTANCE_NONE:
+ case NotificationManager.IMPORTANCE_NONE:
return "NONE";
- case IMPORTANCE_MIN:
+ case NotificationManager.IMPORTANCE_MIN:
return "MIN";
- case IMPORTANCE_LOW:
+ case NotificationManager.IMPORTANCE_LOW:
return "LOW";
- case IMPORTANCE_DEFAULT:
+ case NotificationManager.IMPORTANCE_DEFAULT:
return "DEFAULT";
- case IMPORTANCE_HIGH:
+ case NotificationManager.IMPORTANCE_HIGH:
+ case NotificationManager.IMPORTANCE_MAX:
return "HIGH";
- case IMPORTANCE_MAX:
- return "MAX";
default:
return "UNKNOWN(" + String.valueOf(importance) + ")";
}
@@ -1326,7 +1271,7 @@
}
Integer importance = mImportance.get(key);
if (importance == null) {
- return Ranking.IMPORTANCE_DEFAULT;
+ return NotificationManager.IMPORTANCE_DEFAULT;
}
return importance.intValue();
}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 986ff46..39d7883 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -213,16 +213,6 @@
void dismissKeyguard();
void keyguardGoingAway(int flags);
- /**
- * Called to tell WindowManager whether the keyguard is animating in. While this property
- * is true, WindowManager won't assume that the keyguard is opaque (eg. WindowAnimator won't
- * force-hide windows just because keyguard is visible and WallpaperController won't occlude
- * app windows with the system wallpaper.
- *
- * <p>Requires CONTROL_KEYGUARD permission</p>
- */
- void setKeyguardAnimatingIn(boolean animating);
-
// Requires INTERACT_ACROSS_USERS_FULL permission
void setSwitchingUser(boolean switching);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 20876a9..ba26926 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -7194,7 +7194,6 @@
/**
* Gets the unique identifier of this view on the screen for accessibility purposes.
- * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
*
* @return The view accessibility id.
*
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 87b330d..5a6cf7d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -19,7 +19,6 @@
import static android.view.WindowCallbacks.RESIZE_MODE_DOCKED_DIVIDER;
import static android.view.WindowCallbacks.RESIZE_MODE_FREEFORM;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
@@ -3542,20 +3541,7 @@
mWinFrame.bottom = t + h;
mPendingBackDropFrame.set(mWinFrame);
-
- // Suppress layouts during resizing - a correct layout will happen when resizing
- // is done, and this just increases system load.
- boolean isDockedDivider = mWindowAttributes.type == TYPE_DOCK_DIVIDER;
- boolean suppress = (mDragResizing && mResizeMode == RESIZE_MODE_DOCKED_DIVIDER)
- || isDockedDivider;
- if (!suppress) {
- if (mView != null) {
- forceLayout(mView);
- }
- requestLayout();
- } else {
- maybeHandleWindowMove(mWinFrame);
- }
+ maybeHandleWindowMove(mWinFrame);
}
break;
case MSG_WINDOW_FOCUS_CHANGED: {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index f14acaa..106b211 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -599,13 +599,6 @@
public static final int TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27;
/**
- * Window type: keyguard scrim window. Shows if keyguard needs to be restarted.
- * In multiuser systems shows on all users' windows.
- * @hide
- */
- public static final int TYPE_KEYGUARD_SCRIM = FIRST_SYSTEM_WINDOW+29;
-
- /**
* Window type: Window for Presentation on top of private
* virtual display.
*/
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 653e583..f61a637 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -99,19 +99,30 @@
/**
* Called when a pending app transition gets cancelled.
+ *
+ * @param transit transition type indicating what kind of transition got cancelled
*/
- public void onAppTransitionCancelledLocked() {}
+ public void onAppTransitionCancelledLocked(int transit) {}
/**
* Called when an app transition gets started
*
+ * @param transit transition type indicating what kind of transition gets run, must be one
+ * of AppTransition.TRANSIT_* values
* @param openToken the token for the opening app
* @param closeToken the token for the closing app
* @param openAnimation the animation for the opening app
* @param closeAnimation the animation for the closing app
+ *
+ * @return Return any bit set of {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_LAYOUT},
+ * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_CONFIG},
+ * {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_WALLPAPER},
+ * or {@link WindowManagerPolicy#FINISH_LAYOUT_REDO_ANIM}.
*/
- public void onAppTransitionStartingLocked(IBinder openToken, IBinder closeToken,
- Animation openAnimation, Animation closeAnimation) {}
+ public int onAppTransitionStartingLocked(int transit, IBinder openToken, IBinder closeToken,
+ Animation openAnimation, Animation closeAnimation) {
+ return 0;
+ }
/**
* Called when an app transition is finished running.
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index a6be493..a8d70c4 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -136,10 +136,10 @@
throws RemoteException;
/**
- * @return true if windows with FLAG_DISMISS_KEYGUARD should be allowed to show even if
- * the keyguard is locked.
+ * Called when the Keyguard occluded state changed.
+ * @param occluded Whether Keyguard is currently occluded or not.
*/
- boolean canShowDismissingWindowWhileLockedLw();
+ void onKeyguardOccludedChangedLw(boolean occluded);
/**
* Interface to the Window Manager state associated with a particular
@@ -424,6 +424,10 @@
public boolean isInMultiWindowMode();
public int getRotationAnimationHint();
+
+ public boolean isInputMethodWindow();
+
+ public int getDisplayId();
}
/**
@@ -509,9 +513,9 @@
void getStackBounds(int stackId, Rect outBounds);
/**
- * Overrides all currently playing app animations with {@param a}.
+ * Notifies window manager that {@link #isShowingDreamLw} has changed.
*/
- void overridePlayingAppAnimationsLw(Animation a);
+ void notifyShowingDreamChanged();
}
public interface PointerEventListener {
@@ -699,31 +703,15 @@
int uiMode);
/**
- * Return whether the given window is forcibly hiding all windows except windows with
- * FLAG_SHOW_WHEN_LOCKED set. Typically returns true for the keyguard.
- */
- public boolean isForceHiding(WindowManager.LayoutParams attrs);
-
-
- /**
- * Return whether the given window can become one that passes isForceHiding() test.
- * Typically returns true for the StatusBar.
+ * Return whether the given window can become the Keyguard window. Typically returns true for
+ * the StatusBar.
*/
public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs);
/**
- * Determine if a window that is behind one that is force hiding
- * (as determined by {@link #isForceHiding}) should actually be hidden.
- * For example, typically returns false for the status bar. Be careful
- * to return false for any window that you may hide yourself, since this
- * will conflict with what you set.
+ * @return whether {@param win} can be hidden by Keyguard
*/
- public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs);
-
- /**
- * Return the window that is hiding the keyguard, if such a thing exists.
- */
- public WindowState getWinShowWhenLockedLw();
+ public boolean canBeHiddenByKeyguardLw(WindowState win);
/**
* Called when the system would like to show a UI to indicate that an
@@ -834,16 +822,16 @@
boolean forceDefault);
/**
- * Create and return an animation to re-display a force hidden window.
+ * Create and return an animation to re-display a window that was force hidden by Keyguard.
*/
- public Animation createForceHideEnterAnimation(boolean onWallpaper,
+ public Animation createHiddenByKeyguardExit(boolean onWallpaper,
boolean goingToNotificationShade);
/**
- * Create and return an animation to let the wallpaper disappear after being shown on a force
- * hiding window.
+ * Create and return an animation to let the wallpaper disappear after being shown behind
+ * Keyguard.
*/
- public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade);
+ public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade);
/**
* Called from the input reader thread before a key is enqueued.
@@ -1000,7 +988,7 @@
* @param attached For sub-windows, the window it is attached to. Otherwise null.
*/
public void applyPostLayoutPolicyLw(WindowState win,
- WindowManager.LayoutParams attrs, WindowState attached);
+ WindowManager.LayoutParams attrs, WindowState attached, WindowState imeTarget);
/**
* Called following layout of all windows and after policy has been applied
@@ -1147,11 +1135,11 @@
public boolean isKeyguardSecure(int userId);
/**
- * Return whether the keyguard is on.
+ * Return whether the keyguard is currently occluded.
*
- * @return true if in keyguard is on.
+ * @return true if in keyguard is occluded, false otherwise
*/
- public boolean isKeyguardShowingOrOccluded();
+ public boolean isKeyguardOccluded();
/**
* @return true if in keyguard is on and not occluded.
@@ -1159,6 +1147,11 @@
public boolean isKeyguardShowingAndNotOccluded();
/**
+ * @return whether Keyguard is in trusted state and can be dismissed without credentials
+ */
+ public boolean isKeyguardTrustedLw();
+
+ /**
* inKeyguardRestrictedKeyInputMode
*
* if keyguard screen is showing or in restricted key input mode (i.e. in
@@ -1175,11 +1168,6 @@
public void dismissKeyguardLw();
/**
- * Notifies the keyguard that the activity has drawn it was waiting for.
- */
- public void notifyActivityDrawnForKeyguardLw();
-
- /**
* Ask the policy whether the Keyguard has drawn. If the Keyguard is disabled, this method
* returns true as soon as we know that Keyguard is disabled.
*
@@ -1187,6 +1175,8 @@
*/
public boolean isKeyguardDrawnLw();
+ public boolean isShowingDreamLw();
+
/**
* Given an orientation constant, returns the appropriate surface rotation,
* taking into account sensors, docking mode, rotation lock, and other factors.
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index d5a933c..8cedb17 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2168,7 +2168,6 @@
}
layoutChildren();
- mInLayout = false;
mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
@@ -2176,6 +2175,7 @@
if (mFastScroll != null) {
mFastScroll.onItemCountChanged(getChildCount(), mItemCount);
}
+ mInLayout = false;
}
/**
@@ -2705,6 +2705,9 @@
* fail to relayout them properly to accommodate for new bounds.
*/
void handleBoundsChange() {
+ if (mInLayout) {
+ return;
+ }
final int childCount = getChildCount();
if (childCount > 0) {
mDataChanged = true;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 12d4be3..e1118d8 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -258,7 +258,7 @@
continue;
}
- Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClass " + line);
+ Trace.traceBegin(Trace.TRACE_TAG_DALVIK, line);
try {
if (false) {
Log.v(TAG, "Preloading " + line + "...");
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index 50dd33a..788103d 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -34,7 +34,6 @@
void addStateMonitorCallback(IKeyguardStateCallback callback);
void verifyUnlock(IKeyguardExitCallback callback);
- void keyguardDone(boolean authenticated, boolean wakeup);
void dismiss(boolean allowWhileOccluded);
void onDreamingStarted();
void onDreamingStopped();
@@ -93,10 +92,4 @@
* @param fadeoutDuration the duration of the exit animation, in milliseconds
*/
void startKeyguardExitAnimation(long startTime, long fadeoutDuration);
-
- /**
- * Notifies the Keyguard that the activity that was starting has now been drawn and it's safe
- * to start the keyguard dismiss sequence.
- */
- void onActivityDrawn();
}
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 467ec37..a47062e 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1195,13 +1195,6 @@
return JNI_TRUE;
}
-static jlong Bitmap_refPixelRef(JNIEnv* env, jobject, jlong bitmapHandle) {
- LocalScopedBitmap bitmap(bitmapHandle);
- SkPixelRef& pixelRef = bitmap->bitmap();
- pixelRef.ref();
- return reinterpret_cast<jlong>(&pixelRef);
-}
-
static void Bitmap_prepareToDraw(JNIEnv* env, jobject, jlong bitmapPtr) {
LocalScopedBitmap bitmapHandle(bitmapPtr);
if (!bitmapHandle.valid()) return;
@@ -1269,7 +1262,6 @@
{ "nativeCopyPixelsFromBuffer", "(JLjava/nio/Buffer;)V",
(void*)Bitmap_copyPixelsFromBuffer },
{ "nativeSameAs", "(JJ)Z", (void*)Bitmap_sameAs },
- { "nativeRefPixelRef", "(J)J", (void*)Bitmap_refPixelRef },
{ "nativePrepareToDraw", "(J)V", (void*)Bitmap_prepareToDraw },
{ "nativeGetAllocationByteCount", "(J)I", (void*)Bitmap_getAllocationByteCount },
};
@@ -1283,4 +1275,4 @@
gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
NELEM(gBitmapMethods));
-}
\ No newline at end of file
+}
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index d1fbebb..07f6aa8 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -67,8 +67,8 @@
</plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
- <string name="ClipMmi" msgid="6952821216480289285">"ID de l\'emissor (trucada entrant)"</string>
- <string name="ClirMmi" msgid="7784673673446833091">"ID de l\'emissor (trucada de sortida)"</string>
+ <string name="ClipMmi" msgid="6952821216480289285">"Identificador de trucada (trucada entrant)"</string>
+ <string name="ClirMmi" msgid="7784673673446833091">"Identificador de trucada (trucada de sortida)"</string>
<string name="ColpMmi" msgid="3065121483740183974">"Identificador de la línia connectada"</string>
<string name="ColrMmi" msgid="4996540314421889589">"Restricció de l\'identificador de la línia connectada"</string>
<string name="CfMmi" msgid="5123218989141573515">"Desviació de trucades"</string>
@@ -82,12 +82,12 @@
<string name="RuacMmi" msgid="7827887459138308886">"Rebuig de trucades molestes no desitjades"</string>
<string name="CndMmi" msgid="3116446237081575808">"Lliurament de número que truca"</string>
<string name="DndMmi" msgid="1265478932418334331">"No molesteu"</string>
- <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"El valor predeterminat de l\'identificador de l\'emissor és restringit. Següent trucada: restringit"</string>
- <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"El valor predeterminat de l\'identificador de l\'emissor és restringit. Següent trucada: no restringit"</string>
- <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"El valor predeterminat de l\'identificador de l\'emissor és no restringit. Següent trucada: restringit"</string>
- <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"El valor predeterminat de l\'identificador de l\'emissor és no restringit. Següent trucada: no restringit"</string>
+ <string name="CLIRDefaultOnNextCallOn" msgid="429415409145781923">"El valor predeterminat de l\'identificador de trucada és restringit. Trucada següent: restringit"</string>
+ <string name="CLIRDefaultOnNextCallOff" msgid="3092918006077864624">"El valor predeterminat de l\'identificador de trucada és restringit. Trucada següent: no restringit"</string>
+ <string name="CLIRDefaultOffNextCallOn" msgid="6179425182856418465">"El valor predeterminat de l\'identificador de trucada és no restringit. Trucada següent: restringit"</string>
+ <string name="CLIRDefaultOffNextCallOff" msgid="2567998633124408552">"El valor predeterminat de l\'identificador de trucada és no restringit. Trucada següent: no restringit"</string>
<string name="serviceNotProvisioned" msgid="8614830180508686666">"No s\'ha proveït el servei."</string>
- <string name="CLIRPermanent" msgid="3377371145926835671">"No pots canviar la configuració de l\'identificador de l\'emissor."</string>
+ <string name="CLIRPermanent" msgid="3377371145926835671">"No pots canviar la configuració de l\'identificador de trucada."</string>
<string name="RestrictedOnData" msgid="8653794784690065540">"El servei de dades està bloquejat."</string>
<string name="RestrictedOnEmergency" msgid="6581163779072833665">"El servei d\'emergència està bloquejat."</string>
<string name="RestrictedOnNormal" msgid="4953867011389750673">"El servei de veu està bloquejat."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index ac74164..340010f 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -671,7 +671,7 @@
<string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"Nödsamtalsnummer"</string>
<string name="lockscreen_carrier_default" msgid="6169005837238288522">"Ingen tjänst"</string>
<string name="lockscreen_screen_locked" msgid="7288443074806832904">"Skärmen har låsts."</string>
- <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Tryck på Menu om du vill låsa upp eller ringa nödsamtal."</string>
+ <string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"Tryck på Menu för att låsa upp eller ringa nödsamtal."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"Tryck på Menu för att låsa upp."</string>
<string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"Rita grafiskt lösenord för att låsa upp"</string>
<string name="lockscreen_emergency_call" msgid="5298642613417801888">"Nödsamtal"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 567e920..0678dfd 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2635,4 +2635,11 @@
<!-- An array of packages for which notifications cannot be blocked. -->
<string-array translatable="false" name="config_nonBlockableNotificationPackages" />
+
+ <!-- The default value for transition animation scale found in developer settings.
+ 1.0 corresponds to 1x animator scale, 0 means that there will be no transition
+ animations. Note that this is only a default and will be overridden by a
+ user-set value if toggled by settings so the "Transition animation scale" setting
+ should also be hidden if intended to be permanent. -->
+ <item name="config_appTransitionAnimationDurationScaleDefault" format="float" type="dimen">1.0</item>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e946136..0073f53 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2731,4 +2731,6 @@
<!-- Screen-size-dependent modes for picker dialogs. -->
<java-symbol type="integer" name="time_picker_mode" />
<java-symbol type="integer" name="date_picker_mode" />
+
+ <java-symbol type="dimen" name="config_appTransitionAnimationDurationScaleDefault" />
</resources>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index fd2f705..79c63ee 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1655,16 +1655,6 @@
nativePrepareToDraw(mNativePtr);
}
- /**
- * Refs the underlying SkPixelRef and returns a pointer to it.
- *
- * @hide
- * */
- public final long refSkPixelRef() {
- checkRecycled("Can't refSkPixelRef on a recycled bitmap!");
- return nativeRefPixelRef(mNativePtr);
- }
-
//////////// native methods
private static native Bitmap nativeCreate(int[] colors, int offset,
@@ -1721,7 +1711,6 @@
private static native boolean nativeHasMipMap(long nativeBitmap);
private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap);
private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1);
- private static native long nativeRefPixelRef(long nativeBitmap);
private static native void nativePrepareToDraw(long nativeBitmap);
private static native int nativeGetAllocationByteCount(long nativeBitmap);
}
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index c4a65f6..0a60a8e 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -82,6 +82,12 @@
void Texture::deleteTexture() {
mCaches.textureState().deleteTexture(mId);
mId = 0;
+ mTarget = GL_NONE;
+ if (mEglImageHandle != EGL_NO_IMAGE_KHR) {
+ EGLDisplay eglDisplayHandle = eglGetCurrentDisplay();
+ eglDestroyImageKHR(eglDisplayHandle, mEglImageHandle);
+ mEglImageHandle = EGL_NO_IMAGE_KHR;
+ }
}
bool Texture::updateSize(uint32_t width, uint32_t height, GLint internalFormat,
@@ -129,6 +135,17 @@
GL_CHECKPOINT(MODERATE);
}
+void Texture::uploadHardwareBitmapToTexture(GraphicBuffer* buffer) {
+ EGLDisplay eglDisplayHandle = eglGetCurrentDisplay();
+ if (mEglImageHandle != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(eglDisplayHandle, mEglImageHandle);
+ mEglImageHandle = EGL_NO_IMAGE_KHR;
+ }
+ mEglImageHandle = eglCreateImageKHR(eglDisplayHandle, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+ buffer->getNativeBuffer(), 0);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, mEglImageHandle);
+}
+
static void uploadToTexture(bool resize, GLint internalFormat, GLenum format, GLenum type,
GLsizei stride, GLsizei bpp, GLsizei width, GLsizei height, const GLvoid * data) {
@@ -173,7 +190,7 @@
}
}
-static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
+void Texture::colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType) {
switch (colorType) {
case kAlpha_8_SkColorType:
@@ -214,6 +231,24 @@
}
}
+SkBitmap Texture::uploadToN32(const SkBitmap& bitmap, bool hasSRGB, sk_sp<SkColorSpace> sRGB) {
+ SkBitmap rgbaBitmap;
+ rgbaBitmap.allocPixels(SkImageInfo::MakeN32(bitmap.width(), bitmap.height(),
+ bitmap.info().alphaType(), hasSRGB ? sRGB : nullptr));
+ rgbaBitmap.eraseColor(0);
+ SkCanvas canvas(rgbaBitmap);
+ canvas.drawBitmap(bitmap, 0.0f, 0.0f, nullptr);
+ return rgbaBitmap;
+}
+
+bool Texture::hasUnsupportedColorType(const SkImageInfo& info, bool hasSRGB, SkColorSpace* sRGB) {
+ bool needSRGB = info.colorSpace() == sRGB;
+ return info.colorType() == kARGB_4444_SkColorType
+ || info.colorType() == kIndex_8_SkColorType
+ || (info.colorType() == kRGB_565_SkColorType && hasSRGB && needSRGB);
+}
+
+
void Texture::upload(Bitmap& bitmap) {
if (!bitmap.readyToDraw()) {
ALOGE("Cannot generate texture from bitmap");
@@ -243,33 +278,23 @@
GLint internalFormat, format, type;
colorTypeToGlFormatAndType(mCaches, bitmap.colorType(), needSRGB, &internalFormat, &format, &type);
- if (updateSize(bitmap.width(), bitmap.height(), internalFormat, format, GL_TEXTURE_2D)) {
- needsAlloc = true;
- }
+ GLenum target = bitmap.isHardware() ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
+ needsAlloc |= updateSize(bitmap.width(), bitmap.height(), internalFormat, format, target);
blend = !bitmap.isOpaque();
- mCaches.textureState().bindTexture(mId);
+ mCaches.textureState().bindTexture(mTarget, mId);
// TODO: Handle sRGB gray bitmaps
bool hasSRGB = mCaches.extensions().hasSRGB();
- if (CC_UNLIKELY(bitmap.colorType() == kARGB_4444_SkColorType
- || bitmap.colorType() == kIndex_8_SkColorType
- || (bitmap.colorType() == kRGB_565_SkColorType && hasSRGB && needSRGB))) {
-
- SkBitmap rgbaBitmap;
- rgbaBitmap.allocPixels(SkImageInfo::MakeN32(
- mWidth, mHeight, bitmap.info().alphaType(), hasSRGB ? sRGB : nullptr));
- rgbaBitmap.eraseColor(0);
-
- SkCanvas canvas(rgbaBitmap);
+ if (CC_UNLIKELY(hasUnsupportedColorType(bitmap.info(), hasSRGB, sRGB.get()))) {
SkBitmap skBitmap;
bitmap.getSkBitmap(&skBitmap);
- canvas.drawBitmap(skBitmap, 0.0f, 0.0f, nullptr);
-
+ SkBitmap rgbaBitmap = uploadToN32(skBitmap, hasSRGB, std::move(sRGB));
uploadToTexture(needsAlloc, internalFormat, format, type, rgbaBitmap.rowBytesAsPixels(),
rgbaBitmap.bytesPerPixel(), rgbaBitmap.width(),
rgbaBitmap.height(), rgbaBitmap.getPixels());
-
+ } else if (bitmap.isHardware()) {
+ uploadHardwareBitmapToTexture(bitmap.graphicBuffer());
} else {
uploadToTexture(needsAlloc, internalFormat, format, type, bitmap.rowBytesAsPixels(),
bitmap.info().bytesPerPixel(), bitmap.width(), bitmap.height(), bitmap.pixels());
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index d73789a..c75e88f 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -21,8 +21,14 @@
#include "hwui/Bitmap.h"
#include <GLES2/gl2.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <SkBitmap.h>
namespace android {
+
+class GraphicBuffer;
+
namespace uirenderer {
class Caches;
@@ -34,6 +40,11 @@
*/
class Texture : public GpuMemoryTracker {
public:
+ static SkBitmap uploadToN32(const SkBitmap& bitmap, bool hasSRGB, sk_sp<SkColorSpace> sRGB);
+ static bool hasUnsupportedColorType(const SkImageInfo& info, bool hasSRGB, SkColorSpace* sRGB);
+ static void colorTypeToGlFormatAndType(const Caches& caches, SkColorType colorType,
+ bool needSRGB, GLint* outInternalFormat, GLint* outFormat, GLint* outType);
+
explicit Texture(Caches& caches)
: GpuMemoryTracker(GpuObjectType::Texture)
, mCaches(caches)
@@ -147,7 +158,6 @@
* the current frame. This is reset at the start of a new frame.
*/
void* isInUse = nullptr;
-
private:
// TODO: Temporarily grant private access to Layer, remove once
// Layer can be de-tangled from being a dual-purpose render target
@@ -157,6 +167,7 @@
// Returns true if the size changed, false if it was the same
bool updateSize(uint32_t width, uint32_t height, GLint internalFormat,
GLint format, GLenum target);
+ void uploadHardwareBitmapToTexture(GraphicBuffer* buffer);
void resetCachedParams();
GLuint mId = 0;
@@ -165,6 +176,7 @@
GLint mFormat = 0;
GLint mInternalFormat = 0;
GLenum mTarget = GL_NONE;
+ EGLImageKHR mEglImageHandle = EGL_NO_IMAGE_KHR;
/* See GLES spec section 3.8.14
* "In the initial state, the value assigned to TEXTURE_MIN_FILTER is
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 31fbe68..be0b22e 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -16,11 +16,27 @@
#include "Bitmap.h"
#include "Caches.h"
+#include "renderthread/RenderThread.h"
+#include "renderthread/RenderProxy.h"
#include <cutils/log.h>
#include <sys/mman.h>
#include <cutils/ashmem.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+
+#include <gui/IGraphicBufferAlloc.h>
+#include <gui/ISurfaceComposer.h>
+#include <private/gui/ComposerService.h>
+#include <binder/IServiceManager.h>
+#include <ui/PixelFormat.h>
+
+#include <SkCanvas.h>
+
namespace android {
static bool computeAllocationSize(size_t rowBytes, int height, size_t* size) {
@@ -76,6 +92,167 @@
return sk_sp<Bitmap>(new Bitmap(addr, size, info, rowBytes, ctable));
}
+#define FENCE_TIMEOUT 2000000000
+
+// TODO: handle SRGB sanely
+static PixelFormat internalFormatToPixelFormat(GLint internalFormat) {
+ switch (internalFormat) {
+ case GL_ALPHA:
+ return PIXEL_FORMAT_TRANSPARENT;
+ case GL_LUMINANCE:
+ return PIXEL_FORMAT_RGBA_8888;
+ case GL_SRGB8_ALPHA8:
+ return PIXEL_FORMAT_RGBA_8888;
+ case GL_RGBA:
+ return PIXEL_FORMAT_RGBA_8888;
+ default:
+ LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", internalFormat);
+ return PIXEL_FORMAT_UNKNOWN;
+ }
+}
+
+class AutoEglFence {
+public:
+ AutoEglFence(EGLDisplay display)
+ : mDisplay(display) {
+ fence = eglCreateSyncKHR(mDisplay, EGL_SYNC_FENCE_KHR, NULL);
+ }
+
+ ~AutoEglFence() {
+ if (fence != EGL_NO_SYNC_KHR) {
+ eglDestroySyncKHR(mDisplay, fence);
+ }
+ }
+
+ EGLSyncKHR fence = EGL_NO_SYNC_KHR;
+private:
+ EGLDisplay mDisplay = EGL_NO_DISPLAY;
+};
+
+class AutoEglImage {
+public:
+ AutoEglImage(EGLDisplay display, EGLClientBuffer clientBuffer)
+ : mDisplay(display) {
+ EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE };
+ image = eglCreateImageKHR(display, EGL_NO_CONTEXT,
+ EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
+ }
+
+ ~AutoEglImage() {
+ if (image != EGL_NO_IMAGE_KHR) {
+ eglDestroyImageKHR(mDisplay, image);
+ }
+ }
+
+ EGLImageKHR image = EGL_NO_IMAGE_KHR;
+private:
+ EGLDisplay mDisplay = EGL_NO_DISPLAY;
+};
+
+static bool uploadBitmapToGraphicBuffer(uirenderer::Caches& caches, SkBitmap& bitmap,
+ GraphicBuffer& buffer, GLint format, GLint type) {
+ SkAutoLockPixels alp(bitmap);
+ EGLDisplay display = eglGetCurrentDisplay();
+ LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY,
+ "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
+ uirenderer::renderthread::EglManager::eglErrorString());
+ // These objects are initialized below but the default "null"
+ // values are used to cleanup properly at any point in the
+ // initialization sequenc
+ GLuint texture = 0;
+ // We use an EGLImage to access the content of the GraphicBuffer
+ // The EGL image is later bound to a 2D texture
+ EGLClientBuffer clientBuffer = (EGLClientBuffer) buffer.getNativeBuffer();
+ AutoEglImage autoImage(display, clientBuffer);
+ if (autoImage.image == EGL_NO_IMAGE_KHR) {
+ ALOGW("Could not create EGL image, err =%s",
+ uirenderer::renderthread::EglManager::eglErrorString());
+ return false;
+ }
+ glGenTextures(1, &texture);
+ caches.textureState().bindTexture(texture);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, autoImage.image);
+
+ GL_CHECKPOINT(MODERATE);
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bitmap.width(), bitmap.height(),
+ format, type, bitmap.getPixels());
+
+ GL_CHECKPOINT(MODERATE);
+
+ // The fence is used to wait for the texture upload to finish
+ // properly. We cannot rely on glFlush() and glFinish() as
+ // some drivers completely ignore these API calls
+ AutoEglFence autoFence(display);
+ if (autoFence.fence == EGL_NO_SYNC_KHR) {
+ LOG_ALWAYS_FATAL("Could not create sync fence %#x", eglGetError());
+ return false;
+ }
+ // The flag EGL_SYNC_FLUSH_COMMANDS_BIT_KHR will trigger a
+ // pipeline flush (similar to what a glFlush() would do.)
+ EGLint waitStatus = eglClientWaitSyncKHR(display, autoFence.fence,
+ EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, FENCE_TIMEOUT);
+ if (waitStatus != EGL_CONDITION_SATISFIED_KHR) {
+ LOG_ALWAYS_FATAL("Failed to wait for the fence %#x", eglGetError());
+ return false;
+ }
+ return true;
+}
+
+sk_sp<Bitmap> Bitmap::allocateHardwareBitmap(uirenderer::renderthread::RenderThread& renderThread,
+ SkBitmap& skBitmap) {
+ renderThread.eglManager().initialize();
+ uirenderer::Caches& caches = uirenderer::Caches::getInstance();
+
+ sp<ISurfaceComposer> composer(ComposerService::getComposerService());
+ sp<IGraphicBufferAlloc> alloc(composer->createGraphicBufferAlloc());
+ if (alloc == NULL) {
+ ALOGW("createGraphicBufferAlloc() failed in GraphicBuffer.create()");
+ return nullptr;
+ }
+
+ const SkImageInfo& info = skBitmap.info();
+ if (info.colorType() == kUnknown_SkColorType) {
+ ALOGW("unable to create hardware bitmap of configuration");
+ return nullptr;
+ }
+
+ sk_sp<SkColorSpace> sRGB = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named);
+ bool needSRGB = skBitmap.info().colorSpace() == sRGB.get();
+ bool hasSRGB = caches.extensions().hasSRGB();
+ GLint format, type, internalFormat;
+ uirenderer::Texture::colorTypeToGlFormatAndType(caches, skBitmap.colorType(),
+ needSRGB, &internalFormat, &format, &type);
+
+ PixelFormat pixelFormat = internalFormatToPixelFormat(internalFormat);
+ status_t error;
+ sp<GraphicBuffer> buffer = alloc->createGraphicBuffer(info.width(), info.height(), pixelFormat,
+ GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER
+ | GraphicBuffer::USAGE_SW_READ_NEVER , &error);
+
+ if (!buffer.get()) {
+ ALOGW("createGraphicBuffer() failed in GraphicBuffer.create()");
+ return nullptr;
+ }
+
+ SkBitmap bitmap;
+ if (CC_UNLIKELY(uirenderer::Texture::hasUnsupportedColorType(skBitmap.info(),
+ hasSRGB, sRGB.get()))) {
+ bitmap = uirenderer::Texture::uploadToN32(skBitmap, hasSRGB, std::move(sRGB));
+ } else {
+ bitmap = skBitmap;
+ }
+
+ if (!uploadBitmapToGraphicBuffer(caches, bitmap, *buffer, format, type)) {
+ return nullptr;
+ }
+ return sk_sp<Bitmap>(new Bitmap(std::move(buffer), info));
+}
+
+sk_sp<Bitmap> Bitmap::allocateHardwareBitmap(SkBitmap& bitmap) {
+ return uirenderer::renderthread::RenderProxy::allocateHardwareBitmap(bitmap);
+}
+
sk_sp<Bitmap> Bitmap::allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable) {
return allocateBitmap(bitmap, ctable, &android::allocateHeapBitmap);
}
@@ -183,6 +360,16 @@
reconfigure(info, rowBytes, ctable);
}
+Bitmap::Bitmap(sp<GraphicBuffer>&& buffer, const SkImageInfo& info)
+ : SkPixelRef(info)
+ , mPixelStorageType(PixelStorageType::Hardware) {
+ auto rawBuffer = buffer.get();
+ mPixelStorage.hardware.buffer = rawBuffer;
+ if (rawBuffer) {
+ rawBuffer->incStrong(rawBuffer);
+ }
+ mRowBytes = bytesPerPixel(buffer->getPixelFormat()) * buffer->getStride();
+}
Bitmap::~Bitmap() {
switch (mPixelStorageType) {
case PixelStorageType::External:
@@ -196,6 +383,12 @@
case PixelStorageType::Heap:
free(mPixelStorage.heap.address);
break;
+ case PixelStorageType::Hardware:
+ auto buffer = mPixelStorage.hardware.buffer;
+ buffer->decStrong(buffer);
+ mPixelStorage.hardware.buffer = nullptr;
+ break;
+
}
if (android::uirenderer::Caches::hasInstance()) {
@@ -219,6 +412,9 @@
return mPixelStorage.ashmem.address;
case PixelStorageType::Heap:
return mPixelStorage.heap.address;
+ case PixelStorageType::Hardware:
+ LOG_ALWAYS_FATAL_IF("Can't get address for hardware bitmap");
+ return nullptr;
}
}
@@ -264,6 +460,11 @@
}
void Bitmap::getSkBitmap(SkBitmap* outBitmap) {
+ if (isHardware()) {
+ //TODO: use readback to get pixels
+ LOG_ALWAYS_FATAL("Not implemented");
+ return;
+ }
outBitmap->setInfo(info(), rowBytes());
outBitmap->setPixelRef(this);
outBitmap->setHasHardwareMipMap(mHasHardwareMipMap);
@@ -274,4 +475,11 @@
bounds->set(0, 0, SkIntToScalar(info().width()), SkIntToScalar(info().height()));
}
+GraphicBuffer* Bitmap::graphicBuffer() {
+ if (isHardware()) {
+ return mPixelStorage.hardware.buffer;
+ }
+ return nullptr;
+}
+
} // namespace android
\ No newline at end of file
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index c175690..3940381 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -20,6 +20,7 @@
#include <SkImageInfo.h>
#include <SkPixelRef.h>
#include <cutils/compiler.h>
+#include <ui/GraphicBuffer.h>
namespace android {
@@ -27,8 +28,17 @@
External,
Heap,
Ashmem,
+ Hardware,
};
+namespace uirenderer {
+namespace renderthread {
+ class RenderThread;
+}
+}
+
+class PixelStorage;
+
typedef void (*FreeFunc)(void* addr, void* context);
class ANDROID_API Bitmap : public SkPixelRef {
@@ -36,17 +46,24 @@
static sk_sp<Bitmap> allocateHeapBitmap(SkBitmap* bitmap, SkColorTable* ctable);
static sk_sp<Bitmap> allocateHeapBitmap(const SkImageInfo& info);
+ static sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& bitmap);
+
static sk_sp<Bitmap> allocateAshmemBitmap(SkBitmap* bitmap, SkColorTable* ctable);
static sk_sp<Bitmap> allocateAshmemBitmap(size_t allocSize, const SkImageInfo& info,
size_t rowBytes, SkColorTable* ctable);
static sk_sp<Bitmap> createFrom(const SkImageInfo&, SkPixelRef&);
+
+ static sk_sp<Bitmap> allocateHardwareBitmap(uirenderer::renderthread::RenderThread&,
+ SkBitmap& bitmap);
+
Bitmap(void* address, size_t allocSize, const SkImageInfo& info, size_t rowBytes,
SkColorTable* ctable);
Bitmap(void* address, void* context, FreeFunc freeFunc,
const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
Bitmap(void* address, int fd, size_t mappedSize, const SkImageInfo& info,
size_t rowBytes, SkColorTable* ctable);
+ Bitmap(sp<GraphicBuffer>&& buffer, const SkImageInfo& info);
int width() const { return info().width(); }
int height() const { return info().height(); }
@@ -81,13 +98,18 @@
bool readyToDraw() const {
return this->colorType() != kIndex_8_SkColorType || mColorTable;
}
+
+ bool isHardware() const {
+ return mPixelStorageType == PixelStorageType::Hardware;
+ }
+
+ GraphicBuffer* graphicBuffer();
protected:
virtual bool onNewLockPixels(LockRec* rec) override;
virtual void onUnlockPixels() override { };
virtual size_t getAllocatedSizeInBytes() const override;
private:
virtual ~Bitmap();
- void doFreePixels();
void* getStorage() const;
PixelStorageType mPixelStorageType;
@@ -111,6 +133,9 @@
void* address;
size_t size;
} heap;
+ struct {
+ GraphicBuffer* buffer;
+ } hardware;
} mPixelStorage;
};
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index ce48bc0..beaa85e 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -16,6 +16,7 @@
#include "EglManager.h"
+#include "Texture.h"
#include "Caches.h"
#include "DeviceInfo.h"
#include "Properties.h"
@@ -60,7 +61,7 @@
return "Unknown error";
}
}
-static const char* egl_error_str() {
+const char* EglManager::eglErrorString() {
return egl_error_str(eglGetError());
}
@@ -103,11 +104,11 @@
mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
- "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str());
+ "Failed to get EGL_DEFAULT_DISPLAY! err=%s", eglErrorString());
EGLint major, minor;
LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE,
- "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str());
+ "Failed to initialize display %p! err=%s", mEglDisplay, eglErrorString());
ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);
@@ -186,7 +187,7 @@
loadConfig();
} else {
// Failed to get a valid config
- LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str());
+ LOG_ALWAYS_FATAL("Failed to choose config, error = %s", eglErrorString());
}
}
}
@@ -198,7 +199,7 @@
};
mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs);
LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
- "Failed to create context, error = %s", egl_error_str());
+ "Failed to create context, error = %s", eglErrorString());
}
void EglManager::createPBufferSurface() {
@@ -225,12 +226,12 @@
EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, attribs);
LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
"Failed to create EGLSurface for window %p, eglErr = %s",
- (void*) window, egl_error_str());
+ (void*) window, eglErrorString());
if (mSwapBehavior != SwapBehavior::Preserved) {
LOG_ALWAYS_FATAL_IF(eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED) == EGL_FALSE,
"Failed to set swap behavior to destroyed for window %p, eglErr = %s",
- (void*) window, egl_error_str());
+ (void*) window, eglErrorString());
}
return surface;
@@ -241,7 +242,7 @@
makeCurrent(EGL_NO_SURFACE);
}
if (!eglDestroySurface(mEglDisplay, surface)) {
- ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str());
+ ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, eglErrorString());
}
}
@@ -276,7 +277,7 @@
(void*)surface, egl_error_str(*errOut));
} else {
LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
- (void*)surface, egl_error_str());
+ (void*)surface, eglErrorString());
}
}
mCurrentSurface = surface;
@@ -317,7 +318,7 @@
frame.map(dirty, rects);
if (!eglSetDamageRegionKHR(mEglDisplay, frame.mSurface, rects, 1)) {
LOG_ALWAYS_FATAL("Failed to set damage region on surface %p, error=%s",
- (void*)frame.mSurface, egl_error_str());
+ (void*)frame.mSurface, eglErrorString());
}
}
#endif
@@ -371,14 +372,14 @@
preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED);
if (!preserved) {
ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
- (void*) surface, egl_error_str());
+ (void*) surface, eglErrorString());
// Maybe it's already set?
EGLint swapBehavior;
if (eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &swapBehavior)) {
preserved = (swapBehavior == EGL_BUFFER_PRESERVED);
} else {
ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
- (void*) surface, egl_error_str());
+ (void*) surface, eglErrorString());
}
}
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index ba4a3e1..7349dcc 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -55,6 +55,7 @@
// and EGLConfig, which are re-used by CanvasContext
class EglManager {
public:
+ static const char* eglErrorString();
// Returns true on success, false on failure
void initialize();
@@ -83,7 +84,6 @@
private:
friend class RenderThread;
-
explicit EglManager(RenderThread& thread);
// EglContext is never destroyed, method is purposely not implemented
~EglManager();
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 6cb2b9c..39e5931 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -650,6 +650,19 @@
}
}
+CREATE_BRIDGE2(allocateHardwareBitmap, RenderThread* thread, SkBitmap* bitmap) {
+ sk_sp<Bitmap> hardwareBitmap = Bitmap::allocateHardwareBitmap(*args->thread, *args->bitmap);
+ return hardwareBitmap.release();
+}
+
+sk_sp<Bitmap> RenderProxy::allocateHardwareBitmap(SkBitmap& bitmap) {
+ SETUP_TASK(allocateHardwareBitmap);
+ args->bitmap = &bitmap;
+ args->thread = &RenderThread::getInstance();
+ sk_sp<Bitmap> hardwareBitmap(reinterpret_cast<Bitmap*>(staticPostAndWait(task)));
+ return hardwareBitmap;
+}
+
void RenderProxy::post(RenderTask* task) {
mRenderThread.queue(task);
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index ae9330d..e559142 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -130,6 +130,7 @@
int left, int top, int right, int bottom, SkBitmap* bitmap);
ANDROID_API static void prepareToDraw(Bitmap& bitmap);
+ static sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& bitmap);
private:
RenderThread& mRenderThread;
CanvasContext* mContext;
diff --git a/libs/hwui/tests/common/BitmapAllocationTestUtils.h b/libs/hwui/tests/common/BitmapAllocationTestUtils.h
new file mode 100644
index 0000000..6dadd3e3
--- /dev/null
+++ b/libs/hwui/tests/common/BitmapAllocationTestUtils.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "TestScene.h"
+
+#include <SkBitmap.h>
+#include <string>
+
+namespace android {
+namespace uirenderer {
+namespace test {
+
+class BitmapAllocationTestUtils {
+public:
+ static sk_sp<Bitmap> allocateHeapBitmap(int width, int height,
+ SkColorType colorType, std::function<void(SkBitmap& bitmap)> setup) {
+ sk_sp<Bitmap> bitmap = TestUtils::createBitmap(width, height, colorType);
+ SkBitmap skBitmap;
+ bitmap->getSkBitmap(&skBitmap);
+ setup(skBitmap);
+ return bitmap;
+ }
+
+ static sk_sp<Bitmap> allocateHardwareBitmap(int width, int height,
+ SkColorType colorType, std::function<void(SkBitmap& bitmap)> setup) {
+ SkBitmap skBitmap;
+ sk_sp<Bitmap> heapBitmap(TestUtils::createBitmap(width, height, &skBitmap));
+ setup(skBitmap);
+ return Bitmap::allocateHardwareBitmap(skBitmap);
+ }
+
+ typedef sk_sp<Bitmap> (*BitmapAllocator) (int, int, SkColorType,
+ std::function<void(SkBitmap& bitmap)> setup);
+
+ template <class T, BitmapAllocator allocator>
+ static test::TestScene* createBitmapAllocationScene(const TestScene::Options&) {
+ return new T(allocator);
+ }
+
+ template <class BaseScene>
+ static bool registerBitmapAllocationScene(std::string name, std::string description) {
+ TestScene::registerScene({
+ name + "GlTex",
+ description + " (GlTex version).",
+ createBitmapAllocationScene<BaseScene, &allocateHeapBitmap>
+ });
+
+ TestScene::registerScene({
+ name + "EglImage",
+ description + " (EglImage version).",
+ createBitmapAllocationScene<BaseScene, &allocateHardwareBitmap>
+ });
+ return true;
+ }
+};
+
+} // namespace test
+} // namespace uirenderer
+} // namespace android
\ No newline at end of file
diff --git a/libs/hwui/tests/common/scenes/BitmapFillrate.cpp b/libs/hwui/tests/common/scenes/BitmapFillrate.cpp
new file mode 100644
index 0000000..be58d09
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/BitmapFillrate.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestSceneBase.h"
+#include "tests/common/BitmapAllocationTestUtils.h"
+#include "utils/Color.h"
+
+#include <SkBitmap.h>
+
+using namespace android;
+using namespace android::uirenderer;
+
+class BitmapFillrate;
+
+static bool _BitmapFillrate(
+ BitmapAllocationTestUtils::registerBitmapAllocationScene<BitmapFillrate>(
+ "bitmapFillrate", "Draws multiple large half transparent bitmaps."));
+
+class BitmapFillrate : public TestScene {
+public:
+ BitmapFillrate(BitmapAllocationTestUtils::BitmapAllocator allocator)
+ : TestScene()
+ , mAllocator(allocator) { }
+
+ void createContent(int width, int height, Canvas& canvas) override {
+ canvas.drawColor(Color::White, SkBlendMode::kSrcOver);
+ createNode(canvas, 0x909C27B0, 0, 0, width, height);
+ createNode(canvas, 0xA0CDDC39, width / 3, height / 3, width, height);
+ createNode(canvas, 0x90009688, width / 3, 0, width, height);
+ createNode(canvas, 0xA0FF5722, 0, height / 3, width, height);
+ createNode(canvas, 0x9000796B, width / 6, height/6, width, height);
+ createNode(canvas, 0xA0FFC107, width / 6, 0, width, height);
+ }
+
+ void doFrame(int frameNr) override {
+ for (size_t ci = 0; ci < mNodes.size(); ci++) {
+ mNodes[ci]->mutateStagingProperties().setTranslationX(frameNr % 200);
+ mNodes[ci]->mutateStagingProperties().setTranslationY(frameNr % 200);
+ mNodes[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
+ }
+ }
+private:
+ void createNode(Canvas& canvas, SkColor color, int left, int top,
+ int width, int height) {
+ int itemWidth = 2 * width / 3;
+ int itemHeight = 2 * height / 3;
+ auto card = TestUtils::createNode(left, top, left + itemWidth , top + itemHeight,
+ [this, itemWidth, itemHeight, color](RenderProperties& props, Canvas& canvas) {
+ sk_sp<Bitmap> bitmap = mAllocator(itemWidth, itemHeight, kRGBA_8888_SkColorType,
+ [color](SkBitmap& skBitmap) {
+ skBitmap.eraseColor(color);
+ });
+ canvas.drawBitmap(*bitmap, 0, 0, nullptr);
+ });
+ canvas.drawRenderNode(card.get());
+ mNodes.push_back(card);
+ }
+
+ BitmapAllocationTestUtils::BitmapAllocator mAllocator;
+ std::vector< sp<RenderNode> > mNodes;
+};
\ No newline at end of file
diff --git a/libs/hwui/utils/GLUtils.h b/libs/hwui/utils/GLUtils.h
index b49c1eb..94818b2 100644
--- a/libs/hwui/utils/GLUtils.h
+++ b/libs/hwui/utils/GLUtils.h
@@ -27,7 +27,7 @@
#if DEBUG_OPENGL
#define GL_CHECKPOINT(LEVEL) \
do { if (DEBUG_OPENGL >= DEBUG_LEVEL_##LEVEL) {\
- LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(),\
+ LOG_ALWAYS_FATAL_IF(android::uirenderer::GLUtils::dumpGLErrors(),\
"GL errors! %s:%d", __FILE__, __LINE__);\
} } while (0)
#else
diff --git a/packages/ExtServices/src/android/ext/services/notification/Ranker.java b/packages/ExtServices/src/android/ext/services/notification/Ranker.java
index 63fc157..2feb51f 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Ranker.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Ranker.java
@@ -16,8 +16,6 @@
package android.ext.services.notification;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
-
import android.os.Bundle;
import android.os.UserHandle;
import android.service.notification.Adjustment;
@@ -36,6 +34,7 @@
/**
* Class that provides an updatable ranker module for the notification manager.
+ * TODO: delete
*/
public final class Ranker extends NotificationRankerService {
private static final String TAG = "RocketRanker";
diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
index 474ffea..327d218 100644
--- a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
@@ -76,12 +76,6 @@
void playTrustedSound();
/**
- * @return true if and only if Keyguard is showing or if Keyguard is disabled by an external app
- * (legacy API)
- */
- boolean isInputRestricted();
-
- /**
* @return true if the screen is on
*/
boolean isScreenOn();
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index caad889..58aab1d 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -91,7 +91,7 @@
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"Point d\'accès Wi-Fi mobile"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"Via Bluetooth"</string>
<string name="tether_settings_title_usb_bluetooth" msgid="5355828977109785001">"Partage de connexion"</string>
- <string name="tether_settings_title_all" msgid="8356136101061143841">"Partage de connexion et point d\'accès mobile"</string>
+ <string name="tether_settings_title_all" msgid="8356136101061143841">"Partage de connexion"</string>
<string name="managed_user_title" msgid="8109605045406748842">"Toutes les applis profess."</string>
<string name="user_guest" msgid="8475274842845401871">"Invité"</string>
<string name="unknown" msgid="1592123443519355854">"Inconnu"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 78e1ee1..5dcad7a 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -132,10 +132,10 @@
<item msgid="8903157781070679765">"Normaal"</item>
<item msgid="164347302621392996">"Snel"</item>
<item msgid="5794028588101562009">"Sneller"</item>
- <item msgid="7163942783888652942">"Zeer snel"</item>
- <item msgid="7831712693748700507">"Vlug"</item>
- <item msgid="5194774745031751806">"Zeer vlug"</item>
- <item msgid="9085102246155045744">"Snelst"</item>
+ <item msgid="7163942783888652942">"Nog sneller"</item>
+ <item msgid="7831712693748700507">"Heel erg snel"</item>
+ <item msgid="5194774745031751806">"Snelst"</item>
+ <item msgid="9085102246155045744">"Allerallersnelst"</item>
</string-array>
<string name="choose_profile" msgid="8229363046053568878">"Profiel kiezen"</string>
<string name="category_personal" msgid="1299663247844969448">"Persoonlijk"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
index 7f0e27a..1ea592d 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -22,6 +22,7 @@
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothHeadsetClient;
import android.bluetooth.BluetoothMap;
+import android.bluetooth.BluetoothMapClient;
import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothPbapClient;
@@ -81,12 +82,14 @@
private HeadsetProfile mHeadsetProfile;
private HfpClientProfile mHfpClientProfile;
private MapProfile mMapProfile;
+ private MapClientProfile mMapClientProfile;
private final HidProfile mHidProfile;
private OppProfile mOppProfile;
private final PanProfile mPanProfile;
private PbapClientProfile mPbapClientProfile;
private final PbapServerProfile mPbapProfile;
private final boolean mUsePbapPce;
+ private final boolean mUseMapClient;
/**
* Mapping from profile name, e.g. "HEADSET" to profile object.
@@ -104,6 +107,8 @@
mDeviceManager = deviceManager;
mEventManager = eventManager;
mUsePbapPce = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
+ // MAP Client is typically used in the same situations as PBAP Client
+ mUseMapClient = mContext.getResources().getBoolean(R.bool.enable_pbap_pce_profile);
// pass this reference to adapter and event manager (circular dependency)
mLocalAdapter.setProfileManager(this);
mEventManager.setProfileManager(this);
@@ -125,10 +130,15 @@
BluetoothPan.ACTION_CONNECTION_STATE_CHANGED);
if(DEBUG) Log.d(TAG, "Adding local MAP profile");
- mMapProfile = new MapProfile(mContext, mLocalAdapter,
- mDeviceManager, this);
- addProfile(mMapProfile, MapProfile.NAME,
- BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
+ if (mUseMapClient) {
+ mMapClientProfile = new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
+ addProfile(mMapClientProfile, MapClientProfile.NAME,
+ BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
+ } else {
+ mMapProfile = new MapProfile(mContext, mLocalAdapter, mDeviceManager, this);
+ addProfile(mMapProfile, MapProfile.NAME,
+ BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
+ }
//Create PBAP server profile, but do not add it to list of profiles
// as we do not need to monitor the profile as part of profile list
@@ -199,6 +209,22 @@
Log.d(TAG, "Handsfree Uuid not found.");
}
+ // Message Access Profile Client
+ if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.MNS)) {
+ if (mMapClientProfile == null) {
+ if(DEBUG) Log.d(TAG, "Adding local Map Client profile");
+ mMapClientProfile =
+ new MapClientProfile(mContext, mLocalAdapter, mDeviceManager, this);
+ addProfile(mMapClientProfile, MapClientProfile.NAME,
+ BluetoothMapClient.ACTION_CONNECTION_STATE_CHANGED);
+ }
+ } else if (mMapClientProfile != null) {
+ Log.w(TAG,
+ "Warning: MAP Client profile was previously added but the UUID is now missing.");
+ } else {
+ Log.d(TAG, "MAP Client Uuid not found.");
+ }
+
// OPP
if (BluetoothUuid.isUuidPresent(uuids, BluetoothUuid.ObexObjectPush)) {
if (mOppProfile == null) {
@@ -383,6 +409,10 @@
return mMapProfile;
}
+ public MapClientProfile getMapClientProfile() {
+ return mMapClientProfile;
+ }
+
/**
* Fill in a list of LocalBluetoothProfile objects that are supported by
* the local device and the remote device.
@@ -465,6 +495,11 @@
mMapProfile.setPreferred(device, true);
}
+ if (mMapClientProfile != null) {
+ profiles.add(mMapClientProfile);
+ removedProfiles.remove(mMapClientProfile);
+ }
+
if (mUsePbapPce) {
profiles.add(mPbapClientProfile);
removedProfiles.remove(mPbapClientProfile);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
new file mode 100644
index 0000000..a7621fc
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/MapClientProfile.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothMapClient;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * MapClientProfile handles Bluetooth MAP profile.
+ */
+public final class MapClientProfile implements LocalBluetoothProfile {
+ private static final String TAG = "MapClientProfile";
+ private static boolean V = false;
+
+ private BluetoothMapClient mService;
+ private boolean mIsProfileReady;
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+ private final LocalBluetoothProfileManager mProfileManager;
+
+ static final ParcelUuid[] UUIDS = {
+ BluetoothUuid.MAP,
+ BluetoothUuid.MNS,
+ BluetoothUuid.MAS,
+ };
+
+ static final String NAME = "MAP Client";
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 0;
+
+ // These callbacks run on the main thread.
+ private final class MapClientServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (V) Log.d(TAG,"Bluetooth service connected");
+ mService = (BluetoothMapClient) proxy;
+ // We just bound to the service, so refresh the UI for any connected MAP devices.
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ while (!deviceList.isEmpty()) {
+ BluetoothDevice nextDevice = deviceList.remove(0);
+ CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+ // we may add a new device here, but generally this should not happen
+ if (device == null) {
+ Log.w(TAG, "MapProfile found new device: " + nextDevice);
+ device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+ }
+ device.onProfileStateChanged(MapClientProfile.this,
+ BluetoothProfile.STATE_CONNECTED);
+ device.refresh();
+ }
+
+ mProfileManager.callServiceConnectedListeners();
+ mIsProfileReady=true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (V) Log.d(TAG,"Bluetooth service disconnected");
+ mProfileManager.callServiceDisconnectedListeners();
+ mIsProfileReady=false;
+ }
+ }
+
+ public boolean isProfileReady() {
+ if(V) Log.d(TAG,"isProfileReady(): "+ mIsProfileReady);
+ return mIsProfileReady;
+ }
+
+ MapClientProfile(Context context, LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager,
+ LocalBluetoothProfileManager profileManager) {
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mProfileManager = profileManager;
+ mLocalAdapter.getProfileProxy(context, new MapClientServiceListener(),
+ BluetoothProfile.MAP_CLIENT);
+ }
+
+ public boolean isConnectable() {
+ return true;
+ }
+
+ public boolean isAutoConnectable() {
+ return true;
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ if (mService == null) return false;
+ List<BluetoothDevice> connectedDevices = getConnectedDevices();
+ if (connectedDevices != null) {
+ for (BluetoothDevice connectedDevice : connectedDevices) {
+ mService.disconnect(connectedDevice);
+ }
+ }
+ return mService.connect(device);
+ }
+
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) return false;
+ // Downgrade priority as user is disconnecting.
+ if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ return mService.disconnect(device);
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
+
+ return mService.getConnectionState(device);
+ }
+
+ public boolean isPreferred(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ }
+
+ public int getPreferred(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+ return mService.getPriority(device);
+ }
+
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ if (mService == null) return;
+ if (preferred) {
+ if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ } else {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ }
+ }
+
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (mService == null) return new ArrayList<BluetoothDevice>(0);
+ return mService.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_map;
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_map_profile_summary_use_for;
+
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_map_profile_summary_connected;
+
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_cellphone;
+ }
+
+ protected void finalize() {
+ if (V) Log.d(TAG, "finalize()");
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.MAP_CLIENT,
+ mService);
+ mService = null;
+ }catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up MAP Client proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
index d7c9eab..72a3b3a 100755
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/PbapClientProfile.java
@@ -145,7 +145,7 @@
}
}
for (BluetoothDevice src : srcs) {
- mService.disconnect(device);
+ mService.disconnect(src);
}
}
Log.d(TAG,"PBAPClientProfile attempting to connect to " + device.getAddress());
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/ProfileSelectDialog.java b/packages/SettingsLib/src/com/android/settingslib/drawer/ProfileSelectDialog.java
index 4e85f2e..512049f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/ProfileSelectDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/ProfileSelectDialog.java
@@ -26,10 +26,15 @@
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
+import android.util.Log;
+
+import java.util.List;
public class ProfileSelectDialog extends DialogFragment implements OnClickListener {
+ private static final String TAG = "ProfileSelectDialog";
private static final String ARG_SELECTED_TILE = "selectedTile";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private Tile mSelectedTile;
@@ -68,4 +73,20 @@
getActivity().startActivityAsUser(mSelectedTile.intent, user);
((SettingsDrawerActivity) getActivity()).onProfileTileOpen();
}
+
+ public static void updateUserHandlesIfNeeded(Context context, Tile tile) {
+ List<UserHandle> userHandles = tile.userHandle;
+ if (tile.userHandle == null || tile.userHandle.size() <= 1) {
+ return;
+ }
+ final UserManager userManager = UserManager.get(context);
+ for (int i = userHandles.size() - 1; i >= 0; i--) {
+ if (userManager.getUserInfo(userHandles.get(i).getIdentifier()) == null) {
+ if (DEBUG) {
+ Log.d(TAG, "Delete the user: " + userHandles.get(i).getIdentifier());
+ }
+ userHandles.remove(i);
+ }
+ }
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
index bad7ba4..86514dc 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java
@@ -28,10 +28,8 @@
import android.content.res.TypedArray;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.support.annotation.VisibleForTesting;
import android.support.v4.widget.DrawerLayout;
import android.util.ArraySet;
import android.util.Log;
@@ -312,7 +310,7 @@
return true;
}
try {
- updateUserHandlesIfNeeded(tile);
+ ProfileSelectDialog.updateUserHandlesIfNeeded(this /* context */, tile);
int numUserHandles = tile.userHandle.size();
if (numUserHandles > 1) {
ProfileSelectDialog.show(getFragmentManager(), tile);
@@ -334,24 +332,6 @@
return true;
}
- private void updateUserHandlesIfNeeded(Tile tile) {
- List<UserHandle> userHandles = tile.userHandle;
-
- for (int i = userHandles.size() - 1; i >= 0; i--) {
- if (mUserManager.getUserInfo(userHandles.get(i).getIdentifier()) == null) {
- if (DEBUG) {
- Log.d(TAG, "Delete the user: " + userHandles.get(i).getIdentifier());
- }
- userHandles.remove(i);
- }
- }
- }
-
- @VisibleForTesting
- public void setUserManager(UserManager userManager) {
- mUserManager = userManager;
- }
-
protected void onTileClicked(Tile tile) {
if (openTile(tile)) {
finish();
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java b/packages/SettingsLib/tests/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java
new file mode 100644
index 0000000..ac2d759
--- /dev/null
+++ b/packages/SettingsLib/tests/src/com/android/settingslib/drawer/ProfileSelectDialogTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.drawer;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import static junit.framework.Assert.assertEquals;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ProfileSelectDialogTest {
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private UserManager mUserManager;
+ private static final UserHandle NORMAL_USER = UserHandle.of(1111);
+ private static final UserHandle REMOVED_USER = UserHandle.of(2222);
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
+ final UserInfo userInfo = new UserInfo(
+ NORMAL_USER.getIdentifier(), "test_user", UserInfo.FLAG_RESTRICTED);
+ when(mUserManager.getUserInfo(NORMAL_USER.getIdentifier())).thenReturn(userInfo);
+ }
+
+ @Test
+ public void testUpdateUserHandlesIfNeeded_Normal() {
+ final Tile tile = new Tile();
+ tile.intent = new Intent();
+ tile.userHandle.add(NORMAL_USER);
+
+ ProfileSelectDialog.updateUserHandlesIfNeeded(mContext, tile);
+
+ assertEquals(tile.userHandle.size(), 1);
+ assertEquals(tile.userHandle.get(0).getIdentifier(), NORMAL_USER.getIdentifier());
+ verify(mUserManager, never()).getUserInfo(NORMAL_USER.getIdentifier());
+ }
+
+ @Test
+ public void testUpdateUserHandlesIfNeeded_Remove() {
+ final Tile tile = new Tile();
+ tile.intent = new Intent();
+ tile.userHandle.add(REMOVED_USER);
+ tile.userHandle.add(NORMAL_USER);
+ tile.userHandle.add(REMOVED_USER);
+
+ ProfileSelectDialog.updateUserHandlesIfNeeded(mContext, tile);
+
+ assertEquals(tile.userHandle.size(), 1);
+ assertEquals(tile.userHandle.get(0).getIdentifier(), NORMAL_USER.getIdentifier());
+ verify(mUserManager, times(1)).getUserInfo(NORMAL_USER.getIdentifier());
+ verify(mUserManager, times(2)).getUserInfo(REMOVED_USER.getIdentifier());
+ }
+}
diff --git a/packages/SettingsLib/tests/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java b/packages/SettingsLib/tests/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
index 4d7d4cf..1e87ea0f 100644
--- a/packages/SettingsLib/tests/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
+++ b/packages/SettingsLib/tests/src/com/android/settingslib/drawer/SettingsDrawerActivityTest.java
@@ -19,25 +19,16 @@
import android.app.Instrumentation;
import android.content.Intent;
import android.support.test.InstrumentationRegistry;
-import android.annotation.Nullable;
-import android.content.Intent;
-import android.content.pm.UserInfo;
-import android.os.Bundle;
-import android.os.UserHandle;
-import android.os.UserManager;
import android.support.test.filters.SmallTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
-import com.android.settingslib.drawer.SettingsDrawerActivity;
-import com.android.settingslib.drawer.Tile;
import com.android.settingslib.R;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static android.support.test.espresso.Espresso.onView;
@@ -45,66 +36,19 @@
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withContentDescription;
-import static junit.framework.Assert.assertEquals;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.verify;
@RunWith(AndroidJUnit4.class)
@SmallTest
public class SettingsDrawerActivityTest {
- @Mock
- private UserManager mUserManager;
+
@Rule
public ActivityTestRule<TestActivity> mActivityRule =
new ActivityTestRule<>(TestActivity.class, true, true);
- private static final UserHandle NORMAL_USER = UserHandle.of(1111);
- private static final UserHandle REMOVED_USER = UserHandle.of(2222);
-
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
-
- final UserInfo userInfo = new UserInfo(
- NORMAL_USER.getIdentifier(), "test_user", UserInfo.FLAG_RESTRICTED);
- when(mUserManager.getUserInfo(NORMAL_USER.getIdentifier())).thenReturn(userInfo);
- }
-
- @Test
- public void testUpdateUserHandlesIfNeeded_Normal() {
- TestActivity activity = mActivityRule.getActivity();
- activity.setUserManager(mUserManager);
-
- Tile tile = new Tile();
- tile.intent = new Intent();
- tile.userHandle.add(NORMAL_USER);
-
- activity.openTile(tile);
-
- assertEquals(tile.userHandle.size(), 1);
- assertEquals(tile.userHandle.get(0).getIdentifier(), NORMAL_USER.getIdentifier());
- verify(mUserManager, times(1)).getUserInfo(NORMAL_USER.getIdentifier());
- }
-
- @Test
- public void testUpdateUserHandlesIfNeeded_Remove() {
- TestActivity activity = mActivityRule.getActivity();
- activity.setUserManager(mUserManager);
-
- Tile tile = new Tile();
- tile.intent = new Intent();
- tile.userHandle.add(REMOVED_USER);
- tile.userHandle.add(NORMAL_USER);
- tile.userHandle.add(REMOVED_USER);
-
- activity.openTile(tile);
-
- assertEquals(tile.userHandle.size(), 1);
- assertEquals(tile.userHandle.get(0).getIdentifier(), NORMAL_USER.getIdentifier());
- verify(mUserManager, times(1)).getUserInfo(NORMAL_USER.getIdentifier());
- verify(mUserManager, times(2)).getUserInfo(REMOVED_USER.getIdentifier());
}
@Test
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainer.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainer.java
index a616369..4947863 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainer.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainer.java
@@ -31,7 +31,7 @@
// This should be incremented any time this class or ActivityStarter or BaseStatusBarHeader
// change in incompatible ways.
- public static final int VERSION = 2;
+ public static final int VERSION = 3;
public QSContainer(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -116,7 +116,6 @@
void startPendingIntentDismissingKeyguard(PendingIntent intent);
void startActivity(Intent intent, boolean dismissShade);
void startActivity(Intent intent, boolean dismissShade, Callback callback);
- void preventNextAnimation();
interface Callback {
void onActivityStarted(int resultCode);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index fd1ac8e..81dfafc 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -30,13 +30,10 @@
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
-import android.media.AudioAttributes;
import android.net.Uri;
import android.os.Handler;
import android.os.PowerManager;
-import android.os.SystemClock;
import android.os.UserHandle;
-import android.os.Vibrator;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -104,7 +101,7 @@
return null;
}
- public void setListen(boolean listen) {
+ public void setListening(boolean listen) {
for (TriggerSensor s : mSensors) {
s.setListening(listen);
if (listen) {
@@ -209,8 +206,7 @@
@AnyThread
public void onTrigger(TriggerEvent event) {
mHandler.post(mWakeLock.wrap(() -> {
- if (DEBUG)
- Log.d(TAG, "onTrigger: " + triggerEventToString(event));
+ if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
boolean sensorPerformsProxCheck = false;
if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
int subType = (int) event.values[0];
@@ -250,6 +246,12 @@
}
public interface Callback {
+
+ /**
+ * Called when a sensor requests a pulse
+ * @param pulseReason Requesting sensor, e.g. {@link DozeLog#PULSE_REASON_SENSOR_PICKUP}
+ * @param sensorPerformedProxCheck true if the sensor already checked for FAR proximity.
+ */
void onSensorPulse(int pulseReason, boolean sensorPerformedProxCheck);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index cbaf232..2bb1d6a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -36,8 +36,6 @@
import android.view.Display;
import com.android.internal.hardware.AmbientDisplayConfiguration;
-import com.android.internal.util.Preconditions;
-import com.android.systemui.DejankUtils;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.Assert;
@@ -298,7 +296,7 @@
private void listenForPulseSignals(boolean listen) {
if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen);
- mDozeSensors.setListen(listen);
+ mDozeSensors.setListening(listen);
listenForBroadcasts(listen);
listenForNotifications(listen);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index e05e507..816d70d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -81,15 +81,6 @@
}
@Override // Binder interface
- public void keyguardDone(boolean authenticated, boolean wakeup) {
- Trace.beginSection("KeyguardService.mBinder#keyguardDone");
- checkPermission();
- // TODO: Remove wakeup
- mKeyguardViewMediator.keyguardDone(authenticated);
- Trace.endSection();
- }
-
- @Override // Binder interface
public void setOccluded(boolean isOccluded, boolean animate) {
Trace.beginSection("KeyguardService.mBinder#setOccluded");
checkPermission();
@@ -202,12 +193,6 @@
mKeyguardViewMediator.startKeyguardExitAnimation(startTime, fadeoutDuration);
Trace.endSection();
}
-
- @Override
- public void onActivityDrawn() {
- checkPermission();
- mKeyguardViewMediator.onActivityDrawn();
- }
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 24247e4..9ae341a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -135,7 +135,6 @@
private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
- private final static boolean DBG_WAKE = false;
private final static String TAG = "KeyguardViewMediator";
@@ -145,25 +144,23 @@
"com.android.internal.policy.impl.PhoneWindowManager.DELAYED_LOCK";
// used for handler messages
- private static final int SHOW = 2;
- private static final int HIDE = 3;
- private static final int RESET = 4;
- private static final int VERIFY_UNLOCK = 5;
- private static final int NOTIFY_FINISHED_GOING_TO_SLEEP = 6;
- private static final int NOTIFY_SCREEN_TURNING_ON = 7;
- private static final int KEYGUARD_DONE = 9;
- private static final int KEYGUARD_DONE_DRAWING = 10;
- private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
- private static final int SET_OCCLUDED = 12;
- private static final int KEYGUARD_TIMEOUT = 13;
- private static final int DISMISS = 17;
- private static final int START_KEYGUARD_EXIT_ANIM = 18;
- private static final int ON_ACTIVITY_DRAWN = 19;
- private static final int KEYGUARD_DONE_PENDING_TIMEOUT = 20;
- private static final int NOTIFY_STARTED_WAKING_UP = 21;
- private static final int NOTIFY_SCREEN_TURNED_ON = 22;
- private static final int NOTIFY_SCREEN_TURNED_OFF = 23;
- private static final int NOTIFY_STARTED_GOING_TO_SLEEP = 24;
+ private static final int SHOW = 1;
+ private static final int HIDE = 2;
+ private static final int RESET = 3;
+ private static final int VERIFY_UNLOCK = 4;
+ private static final int NOTIFY_FINISHED_GOING_TO_SLEEP = 5;
+ private static final int NOTIFY_SCREEN_TURNING_ON = 6;
+ private static final int KEYGUARD_DONE = 7;
+ private static final int KEYGUARD_DONE_DRAWING = 8;
+ private static final int SET_OCCLUDED = 9;
+ private static final int KEYGUARD_TIMEOUT = 10;
+ private static final int DISMISS = 11;
+ private static final int START_KEYGUARD_EXIT_ANIM = 12;
+ private static final int KEYGUARD_DONE_PENDING_TIMEOUT = 13;
+ private static final int NOTIFY_STARTED_WAKING_UP = 14;
+ private static final int NOTIFY_SCREEN_TURNED_ON = 15;
+ private static final int NOTIFY_SCREEN_TURNED_OFF = 16;
+ private static final int NOTIFY_STARTED_GOING_TO_SLEEP = 17;
/**
* The default amount of time we stay awake (used for all key input)
@@ -185,11 +182,6 @@
private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
/**
- * Secure setting whether analytics are collected on the keyguard.
- */
- private static final String KEYGUARD_ANALYTICS_SETTING = "keyguard_analytics";
-
- /**
* Boolean option for doKeyguardLocked/doKeyguardTimeout which, when set to true, forces the
* keyguard to show even if it is disabled for the current user.
*/
@@ -209,16 +201,9 @@
/** High level access to the power manager for WakeLocks */
private PowerManager mPM;
- /** High level access to the window manager for dismissing keyguard animation */
- private IWindowManager mWM;
-
-
/** TrustManager for letting it know when we change visibility */
private TrustManager mTrustManager;
- /** SearchManager for determining whether or not search assistant is available */
- private SearchManager mSearchManager;
-
/**
* Used to keep the device awake while to ensure the keyguard finishes opening before
* we sleep.
@@ -342,8 +327,6 @@
private boolean mWakeAndUnlocking;
private IKeyguardDrawnCallback mDrawnCallback;
- private boolean mIsPerUserLock;
-
KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
@Override
@@ -533,7 +516,7 @@
}
if (!mKeyguardDonePending) {
- KeyguardViewMediator.this.keyguardDone(true /* authenticated */);
+ KeyguardViewMediator.this.handleKeyguardDone(true /* authenticated */);
}
if (strongAuth) {
mUpdateMonitor.reportSuccessfulStrongAuthUnlockAttempt();
@@ -584,7 +567,7 @@
if (mKeyguardDonePending) {
// Somebody has called keyguardDonePending before, which means that we are
// authenticated
- KeyguardViewMediator.this.keyguardDone(true /* authenticated */);
+ KeyguardViewMediator.this.handleKeyguardDone(true /* authenticated */);
}
Trace.endSection();
}
@@ -600,11 +583,6 @@
}
@Override
- public boolean isInputRestricted() {
- return KeyguardViewMediator.this.isInputRestricted();
- }
-
- @Override
public boolean isScreenOn() {
return mDeviceInteractive;
}
@@ -645,7 +623,6 @@
private void setupLocked() {
mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mWM = WindowManagerGlobal.getWindowManagerService();
mTrustManager = (TrustManager) mContext.getSystemService(Context.TRUST_SERVICE);
mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
@@ -720,14 +697,12 @@
* Let us know that the system is ready after startup.
*/
public void onSystemReady() {
- mSearchManager = (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
synchronized (this) {
if (DEBUG) Log.d(TAG, "onSystemReady");
mSystemReady = true;
doKeyguardLocked(null);
mUpdateMonitor.registerCallback(mUpdateCallback);
}
- mIsPerUserLock = StorageManager.isFileEncryptedNativeOrEmulated();
// Most services aren't available until the system reaches the ready state, so we
// send it here when the device first boots.
maybeSendUserPresentBroadcast();
@@ -1153,7 +1128,6 @@
if (mOccluded != isOccluded) {
mOccluded = isOccluded;
mStatusBarKeyguardViewManager.setOccluded(isOccluded, animate);
- updateActivityLockScreenState();
adjustStatusBarLocked();
}
}
@@ -1514,9 +1488,6 @@
Trace.beginSection("KeyguardViewMediator#handleMessage KEYGUARD_DONE_PENDING_TIMEOUT");
Log.w(TAG, "Timeout while waiting for activity drawn!");
Trace.endSection();
- // Fall through.
- case ON_ACTIVITY_DRAWN:
- handleOnActivityDrawn();
break;
}
}
@@ -1638,7 +1609,7 @@
private void updateActivityLockScreenState() {
Trace.beginSection("KeyguardViewMediator#updateActivityLockScreenState");
try {
- ActivityManagerNative.getDefault().setLockScreenShown(mShowing, mOccluded);
+ ActivityManagerNative.getDefault().setLockScreenShown(mShowing);
} catch (RemoteException e) {
}
Trace.endSection();
@@ -1668,7 +1639,6 @@
mWakeAndUnlocking = false;
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
- updateActivityLockScreenState();
adjustStatusBarLocked();
userActivity();
@@ -1745,13 +1715,6 @@
Trace.endSection();
}
- private void handleOnActivityDrawn() {
- if (DEBUG) Log.d(TAG, "handleOnActivityDrawn: mKeyguardDonePending=" + mKeyguardDonePending);
- if (mKeyguardDonePending) {
- mStatusBarKeyguardViewManager.onActivityDrawn();
- }
- }
-
private void handleStartKeyguardExitAnimation(long startTime, long fadeoutDuration) {
Trace.beginSection("KeyguardViewMediator#handleStartKeyguardExitAnimation");
if (DEBUG) Log.d(TAG, "handleStartKeyguardExitAnimation startTime=" + startTime
@@ -1784,7 +1747,6 @@
mStatusBarKeyguardViewManager.hide(startTime, fadeoutDuration);
resetKeyguardDonePendingLocked();
mHideAnimationRun = false;
- updateActivityLockScreenState();
adjustStatusBarLocked();
sendUserPresentBroadcast();
}
@@ -1831,7 +1793,7 @@
private void handleReset() {
synchronized (KeyguardViewMediator.this) {
if (DEBUG) Log.d(TAG, "handleReset");
- mStatusBarKeyguardViewManager.reset();
+ mStatusBarKeyguardViewManager.reset(true /* hideBouncerWhenShowing */);
}
}
@@ -1845,7 +1807,6 @@
if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
setShowingLocked(true);
mStatusBarKeyguardViewManager.verifyUnlock();
- updateActivityLockScreenState();
}
Trace.endSection();
}
@@ -1964,10 +1925,6 @@
Trace.endSection();
}
- public void onActivityDrawn() {
- mHandler.sendEmptyMessage(ON_ACTIVITY_DRAWN);
- }
-
public ViewMediatorCallback getViewMediatorCallback() {
return mViewMediatorCallback;
}
@@ -2027,6 +1984,7 @@
}
updateInputRestrictedLocked();
mTrustManager.reportKeyguardShowingChanged();
+ updateActivityLockScreenState();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 64ef997..abde44e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -181,10 +181,7 @@
ssp.registerTaskStackListener(mTaskStackListener);
// Initialize the static configuration resources
- LayoutInflater inflater = LayoutInflater.from(mContext);
mDummyStackView = new TaskStackView(mContext);
- mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
- null, false);
reloadResources();
}
@@ -205,14 +202,6 @@
Resources res = mContext.getResources();
reloadResources();
mDummyStackView.reloadOnConfigurationChange();
- // Update the header bar direction directly as it is not attached to anything and does not
- // layout except in updateHeaderBarLayout()
- mHeaderBar.setLayoutDirection(res.getConfiguration().getLayoutDirection());
- mHeaderBar.onConfigurationChanged();
- mHeaderBar.forceLayout();
- mHeaderBar.measure(
- MeasureSpec.makeMeasureSpec(mHeaderBar.getMeasuredWidth(), MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(mHeaderBar.getMeasuredHeight(), MeasureSpec.EXACTLY));
}
/**
@@ -586,6 +575,11 @@
R.dimen.recents_task_view_header_height_tablet_land,
R.dimen.recents_task_view_header_height,
R.dimen.recents_task_view_header_height_tablet_land);
+
+ LayoutInflater inflater = LayoutInflater.from(mContext);
+ mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
+ null, false);
+ mHeaderBar.setLayoutDirection(res.getConfiguration().getLayoutDirection());
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index fce7f9d..571c0f6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -344,19 +344,6 @@
mContext = context;
mCb = cb;
mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
- mMinMargin = res.getDimensionPixelSize(R.dimen.recents_layout_min_margin);
- mBaseTopMargin = getDimensionForDevice(context,
- R.dimen.recents_layout_top_margin_phone,
- R.dimen.recents_layout_top_margin_tablet,
- R.dimen.recents_layout_top_margin_tablet_xlarge);
- mBaseSideMargin = getDimensionForDevice(context,
- R.dimen.recents_layout_side_margin_phone,
- R.dimen.recents_layout_side_margin_tablet,
- R.dimen.recents_layout_side_margin_tablet_xlarge);
- mBaseBottomMargin = res.getDimensionPixelSize(R.dimen.recents_layout_bottom_margin);
- mFreeformStackGap =
- res.getDimensionPixelSize(R.dimen.recents_freeform_layout_bottom_margin);
-
reloadOnConfigurationChange(context);
}
@@ -390,6 +377,18 @@
R.dimen.recents_layout_initial_bottom_offset_tablet,
R.dimen.recents_layout_initial_bottom_offset_tablet);
mFreeformLayoutAlgorithm.reloadOnConfigurationChange(context);
+ mMinMargin = res.getDimensionPixelSize(R.dimen.recents_layout_min_margin);
+ mBaseTopMargin = getDimensionForDevice(context,
+ R.dimen.recents_layout_top_margin_phone,
+ R.dimen.recents_layout_top_margin_tablet,
+ R.dimen.recents_layout_top_margin_tablet_xlarge);
+ mBaseSideMargin = getDimensionForDevice(context,
+ R.dimen.recents_layout_side_margin_phone,
+ R.dimen.recents_layout_side_margin_tablet,
+ R.dimen.recents_layout_side_margin_tablet_xlarge);
+ mBaseBottomMargin = res.getDimensionPixelSize(R.dimen.recents_layout_bottom_margin);
+ mFreeformStackGap =
+ res.getDimensionPixelSize(R.dimen.recents_freeform_layout_bottom_margin);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 4cc7a16..70e21d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -119,8 +119,6 @@
import java.util.Locale;
import java.util.Set;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
-
public abstract class BaseStatusBar extends SystemUI implements
CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener,
ExpandableNotificationRow.ExpansionLogger, NotificationData.Environment,
@@ -347,17 +345,12 @@
dismissKeyguardThenExecute(new OnDismissAction() {
@Override
public boolean onDismiss() {
- if (keyguardShowing && !afterKeyguardGone) {
- try {
- ActivityManagerNative.getDefault()
- .keyguardWaitingForActivityDrawn();
- ActivityManagerNative.getDefault().resumeAppSwitches();
- } catch (RemoteException e) {
- }
+ try {
+ ActivityManagerNative.getDefault().resumeAppSwitches();
+ } catch (RemoteException e) {
}
boolean handled = superOnClickHandler(view, pendingIntent, fillInIntent);
- overrideActivityPendingAppTransition(keyguardShowing && !afterKeyguardGone);
// close the shade if it was open
if (handled) {
@@ -1054,24 +1047,15 @@
}
private void startNotificationGutsIntent(final Intent intent, final int appUid) {
- final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
dismissKeyguardThenExecute(new OnDismissAction() {
@Override
public boolean onDismiss() {
AsyncTask.execute(new Runnable() {
public void run() {
- try {
- if (keyguardShowing) {
- ActivityManagerNative.getDefault()
- .keyguardWaitingForActivityDrawn();
- }
- TaskStackBuilder.create(mContext)
- .addNextIntentWithParentStack(intent)
- .startActivities(getActivityOptions(),
- new UserHandle(UserHandle.getUserId(appUid)));
- overrideActivityPendingAppTransition(keyguardShowing);
- } catch (RemoteException e) {
- }
+ TaskStackBuilder.create(mContext)
+ .addNextIntentWithParentStack(intent)
+ .startActivities(getActivityOptions(),
+ new UserHandle(UserHandle.getUserId(appUid)));
}
});
animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */);
@@ -1834,11 +1818,6 @@
@Override
public void run() {
try {
- if (keyguardShowing && !afterKeyguardGone) {
- ActivityManagerNative.getDefault()
- .keyguardWaitingForActivityDrawn();
- }
-
// The intent we are sending is for the application, which
// won't have permission to immediately start an activity after
// the user switches to home. We know it is safe to do at this
@@ -1857,8 +1836,6 @@
}
if (intent.isActivity()) {
mAssistManager.hideAssist();
- overrideActivityPendingAppTransition(keyguardShowing
- && !afterKeyguardGone);
}
}
}.start();
@@ -1945,11 +1922,6 @@
@Override
public void run() {
try {
- if (keyguardShowing && !afterKeyguardGone) {
- ActivityManagerNative.getDefault()
- .keyguardWaitingForActivityDrawn();
- }
-
// The intent we are sending is for the application, which
// won't have permission to immediately start an activity after
// the user switches to home. We know it is safe to do at this
@@ -1995,8 +1967,6 @@
}
if (intent.isActivity()) {
mAssistManager.hideAssist();
- overrideActivityPendingAppTransition(keyguardShowing
- && !afterKeyguardGone);
}
}
@@ -2067,16 +2037,6 @@
public void animateCollapsePanels(int flags, boolean force, boolean delayed) {
}
- public void overrideActivityPendingAppTransition(boolean keyguardShowing) {
- if (keyguardShowing) {
- try {
- mWindowManagerService.overridePendingAppTransition(null, 0, 0, null);
- } catch (RemoteException e) {
- Log.w(TAG, "Error overriding app transition: " + e);
- }
- }
- }
-
protected boolean startWorkChallengeIfNecessary(int userId, IntentSender intendSender,
String notificationKey) {
final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null,
@@ -2578,7 +2538,7 @@
return false;
}
- if (mNotificationData.getImportance(sbn.getKey()) < IMPORTANCE_HIGH) {
+ if (mNotificationData.getImportance(sbn.getKey()) < NotificationManager.IMPORTANCE_HIGH) {
if (DEBUG) Log.d(TAG, "No peeking: unimportant notification: " + sbn.getKey());
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index bae16f3..7019880 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar;
import android.app.Notification;
+import android.app.NotificationManager;
import android.content.Context;
import android.os.SystemClock;
import android.service.notification.NotificationListenerService;
@@ -186,8 +187,8 @@
public int compare(Entry a, Entry b) {
final StatusBarNotification na = a.notification;
final StatusBarNotification nb = b.notification;
- int aImportance = Ranking.IMPORTANCE_DEFAULT;
- int bImportance = Ranking.IMPORTANCE_DEFAULT;
+ int aImportance = NotificationManager.IMPORTANCE_DEFAULT;
+ int bImportance = NotificationManager.IMPORTANCE_DEFAULT;
int aRank = 0;
int bRank = 0;
@@ -205,13 +206,13 @@
// IMPORTANCE_MIN media streams are allowed to drift to the bottom
final boolean aMedia = a.key.equals(mediaNotification)
- && aImportance > Ranking.IMPORTANCE_MIN;
+ && aImportance > NotificationManager.IMPORTANCE_MIN;
final boolean bMedia = b.key.equals(mediaNotification)
- && bImportance > Ranking.IMPORTANCE_MIN;
+ && bImportance > NotificationManager.IMPORTANCE_MIN;
- boolean aSystemMax = aImportance >= Ranking.IMPORTANCE_MAX &&
+ boolean aSystemMax = aImportance >= NotificationManager.IMPORTANCE_HIGH &&
isSystemNotification(na);
- boolean bSystemMax = bImportance >= Ranking.IMPORTANCE_MAX &&
+ boolean bSystemMax = bImportance >= NotificationManager.IMPORTANCE_HIGH &&
isSystemNotification(nb);
boolean isHeadsUp = a.row.isHeadsUp();
@@ -318,7 +319,7 @@
mRankingMap.getRanking(key, mTmpRanking);
return mTmpRanking.getImportance();
}
- return Ranking.IMPORTANCE_UNSPECIFIED;
+ return NotificationManager.IMPORTANCE_UNSPECIFIED;
}
public String getOverrideGroupKey(String key) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 62d730a..b10fb31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -19,6 +19,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.INotificationManager;
+import android.app.NotificationManager;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -30,7 +31,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.service.notification.NotificationListenerService;
-import android.service.notification.NotificationListenerService.Ranking;
import android.service.notification.StatusBarNotification;
import android.util.AttributeSet;
import android.view.View;
@@ -178,7 +178,7 @@
final Set<String> nonBlockablePkgs, final int importance) {
mINotificationManager = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
- mStartingUserImportance = NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
+ mStartingUserImportance = NotificationManager.IMPORTANCE_UNSPECIFIED;
try {
mStartingUserImportance =
mINotificationManager.getImportance(sbn.getPackageName(), sbn.getUid());
@@ -229,15 +229,15 @@
if (mSeekBar.isEnabled()) {
return mSeekBar.getProgress();
} else {
- return Ranking.IMPORTANCE_UNSPECIFIED;
+ return NotificationManager.IMPORTANCE_UNSPECIFIED;
}
} else {
if (mBlock.isChecked()) {
- return Ranking.IMPORTANCE_NONE;
+ return NotificationManager.IMPORTANCE_NONE;
} else if (mSilent.isChecked()) {
- return Ranking.IMPORTANCE_LOW;
+ return NotificationManager.IMPORTANCE_LOW;
} else {
- return Ranking.IMPORTANCE_UNSPECIFIED;
+ return NotificationManager.IMPORTANCE_UNSPECIFIED;
}
}
}
@@ -262,7 +262,7 @@
}
mBlock.setText(mContext.getString(R.string.block));
mSilent.setText(mContext.getString(R.string.show_silently));
- if (importance == NotificationListenerService.Ranking.IMPORTANCE_LOW) {
+ if (importance == NotificationManager.IMPORTANCE_LOW) {
mSilent.setChecked(true);
} else {
mReset.setChecked(true);
@@ -278,9 +278,9 @@
mSeekBar = (SeekBar) importanceSlider.findViewById(R.id.seekbar);
final int minProgress = nonBlockable ?
- NotificationListenerService.Ranking.IMPORTANCE_MIN
- : NotificationListenerService.Ranking.IMPORTANCE_NONE;
- mSeekBar.setMax(NotificationListenerService.Ranking.IMPORTANCE_MAX);
+ NotificationManager.IMPORTANCE_MIN
+ : NotificationManager.IMPORTANCE_NONE;
+ mSeekBar.setMax(NotificationManager.IMPORTANCE_HIGH);
mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
@@ -317,7 +317,7 @@
applyAuto();
}
});
- mAuto = mStartingUserImportance == Ranking.IMPORTANCE_UNSPECIFIED;
+ mAuto = mStartingUserImportance == NotificationManager.IMPORTANCE_UNSPECIFIED;
applyAuto();
}
@@ -344,36 +344,32 @@
private void updateTitleAndSummary(int progress) {
switch (progress) {
- case Ranking.IMPORTANCE_NONE:
+ case NotificationManager.IMPORTANCE_NONE:
mImportanceSummary.setText(mContext.getString(
R.string.notification_importance_blocked));
mImportanceTitle.setText(mContext.getString(R.string.blocked_importance));
break;
- case Ranking.IMPORTANCE_MIN:
+ case NotificationManager.IMPORTANCE_MIN:
mImportanceSummary.setText(mContext.getString(
R.string.notification_importance_min));
mImportanceTitle.setText(mContext.getString(R.string.min_importance));
break;
- case Ranking.IMPORTANCE_LOW:
+ case NotificationManager.IMPORTANCE_LOW:
mImportanceSummary.setText(mContext.getString(
R.string.notification_importance_low));
mImportanceTitle.setText(mContext.getString(R.string.low_importance));
break;
- case Ranking.IMPORTANCE_DEFAULT:
+ case NotificationManager.IMPORTANCE_DEFAULT:
mImportanceSummary.setText(mContext.getString(
R.string.notification_importance_default));
mImportanceTitle.setText(mContext.getString(R.string.default_importance));
break;
- case Ranking.IMPORTANCE_HIGH:
+ case NotificationManager.IMPORTANCE_HIGH:
+ case NotificationManager.IMPORTANCE_MAX:
mImportanceSummary.setText(mContext.getString(
R.string.notification_importance_high));
mImportanceTitle.setText(mContext.getString(R.string.high_importance));
break;
- case Ranking.IMPORTANCE_MAX:
- mImportanceSummary.setText(mContext.getString(
- R.string.notification_importance_max));
- mImportanceTitle.setText(mContext.getString(R.string.max_importance));
- break;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index f9b7bb5..dfb06d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -496,7 +496,6 @@
} catch (RemoteException e) {
Log.w(TAG, "Unable to start camera activity", e);
}
- mActivityStarter.preventNextAnimation();
final boolean launched = isSuccessfulLaunch(result);
post(new Runnable() {
@Override
@@ -539,7 +538,6 @@
@Override
public void run() {
mAssistManager.launchVoiceAssistFromKeyguard();
- mActivityStarter.preventNextAnimation();
}
};
if (mPhoneStatusBar.isKeyguardCurrentlySecure()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 798d9df..df167e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -105,7 +105,7 @@
private boolean mInCarMode = false;
private boolean mDockedStackExists;
- private final SparseArray<ButtonDispatcher> mButtonDisatchers = new SparseArray<>();
+ private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
private Configuration mConfiguration;
private NavigationBarInflaterView mNavigationInflaterView;
@@ -206,11 +206,11 @@
mBarTransitions = new NavigationBarTransitions(this);
- mButtonDisatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
- mButtonDisatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
- mButtonDisatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
- mButtonDisatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
- mButtonDisatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
+ mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
+ mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
+ mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
+ mButtonDispatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
+ mButtonDispatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
}
public BarTransitions getBarTransitions() {
@@ -262,23 +262,23 @@
}
public ButtonDispatcher getRecentsButton() {
- return mButtonDisatchers.get(R.id.recent_apps);
+ return mButtonDispatchers.get(R.id.recent_apps);
}
public ButtonDispatcher getMenuButton() {
- return mButtonDisatchers.get(R.id.menu);
+ return mButtonDispatchers.get(R.id.menu);
}
public ButtonDispatcher getBackButton() {
- return mButtonDisatchers.get(R.id.back);
+ return mButtonDispatchers.get(R.id.back);
}
public ButtonDispatcher getHomeButton() {
- return mButtonDisatchers.get(R.id.home);
+ return mButtonDispatchers.get(R.id.home);
}
public ButtonDispatcher getImeSwitchButton() {
- return mButtonDisatchers.get(R.id.ime_switcher);
+ return mButtonDispatchers.get(R.id.ime_switcher);
}
private void updateCarModeIcons(Context ctx) {
@@ -495,7 +495,7 @@
mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
R.id.navigation_inflater);
updateRotatedViews();
- mNavigationInflaterView.setButtonDispatchers(mButtonDisatchers);
+ mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
@@ -556,8 +556,8 @@
mCurrentView = mRotatedViews[rot];
mCurrentView.setVisibility(View.VISIBLE);
mNavigationInflaterView.setAlternativeOrder(rot == Surface.ROTATION_90);
- for (int i = 0; i < mButtonDisatchers.size(); i++) {
- mButtonDisatchers.valueAt(i).setCurrentView(mCurrentView);
+ for (int i = 0; i < mButtonDispatchers.size(); i++) {
+ mButtonDispatchers.valueAt(i).setCurrentView(mCurrentView);
}
updateLayoutTransitionsEnabled();
mCurrentRotation = rot;
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 7b35cbd..cda0bfe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1858,6 +1858,7 @@
mLaunchAnimationEndRunnable.run();
mLaunchAnimationEndRunnable = null;
}
+ mStatusBar.readyForKeyguardDone();
}
@Override
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 0ef2687..669a512 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -37,8 +37,8 @@
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
import android.app.IActivityManager;
-import android.app.KeyguardManager;
import android.app.Notification;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
@@ -50,7 +50,6 @@
import android.content.IntentSender;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
-import android.content.pm.UserInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -1562,7 +1561,7 @@
Log.d(TAG, "No Fullscreen intent: suppressed by DND: " + notification.getKey());
}
} else if (mNotificationData.getImportance(notification.getKey())
- < NotificationListenerService.Ranking.IMPORTANCE_MAX) {
+ < NotificationManager.IMPORTANCE_HIGH) {
if (DEBUG) {
Log.d(TAG, "No Fullscreen intent: not important enough: "
+ notification.getKey());
@@ -2514,11 +2513,6 @@
startActivityDismissingKeyguard(intent, false, dismissShade, callback);
}
- @Override
- public void preventNextAnimation() {
- overrideActivityPendingAppTransition(true /* keyguardShowing */);
- }
-
public void setQsExpanded(boolean expanded) {
mStatusBarWindowManager.setQsExpanded(expanded);
mKeyguardStatusView.setImportantForAccessibility(expanded
@@ -2870,7 +2864,7 @@
for (int i = 0; i < size; i++) {
clonedList.get(i).run();
}
-
+ mStatusBarKeyguardViewManager.readyForKeyguardDone();
}
@Override
@@ -3497,7 +3491,6 @@
final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
mContext, intent, mCurrentUserId);
- final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Runnable runnable = new Runnable() {
@Override
public void run() {
@@ -3528,8 +3521,6 @@
} catch (RemoteException e) {
Log.w(TAG, "Unable to start activity", e);
}
- overrideActivityPendingAppTransition(
- keyguardShowing && !afterKeyguardGone);
if (callback != null) {
callback.onActivityStarted(result);
}
@@ -3547,36 +3538,24 @@
afterKeyguardGone, true /* deferred */);
}
+ public void readyForKeyguardDone() {
+ mStatusBarKeyguardViewManager.readyForKeyguardDone();
+ }
+
public void executeRunnableDismissingKeyguard(final Runnable runnable,
final Runnable cancelAction,
final boolean dismissShade,
final boolean afterKeyguardGone,
final boolean deferred) {
- final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
- dismissKeyguardThenExecute(new OnDismissAction() {
- @Override
- public boolean onDismiss() {
- AsyncTask.execute(new Runnable() {
- @Override
- public void run() {
- try {
- if (keyguardShowing && !afterKeyguardGone) {
- ActivityManagerNative.getDefault()
- .keyguardWaitingForActivityDrawn();
- }
- if (runnable != null) {
- runnable.run();
- }
- } catch (RemoteException e) {
- }
- }
- });
- if (dismissShade) {
- animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */,
- true /* delayed*/);
- }
- return deferred;
+ dismissKeyguardThenExecute(() -> {
+ if (runnable != null) {
+ AsyncTask.execute(runnable);
}
+ if (dismissShade) {
+ animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */,
+ true /* delayed*/);
+ }
+ return deferred;
}, cancelAction, afterKeyguardGone);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 77c60fb..d296498 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -120,14 +120,14 @@
mShowing = true;
mStatusBarWindowManager.setKeyguardShowing(true);
mScrimController.abortKeyguardFadingOut();
- reset();
+ reset(true /* hideBouncerWhenShowing */);
}
/**
* Shows the notification keyguard or the bouncer depending on
* {@link KeyguardBouncer#needsFullscreenBouncer()}.
*/
- protected void showBouncerOrKeyguard() {
+ protected void showBouncerOrKeyguard(boolean hideBouncerWhenShowing) {
if (mBouncer.needsFullscreenBouncer()) {
// The keyguard might be showing (already). So we need to hide it.
@@ -135,8 +135,10 @@
mBouncer.show(true /* resetSecuritySelection */);
} else {
mPhoneStatusBar.showKeyguard();
- mBouncer.hide(false /* destroyView */);
- mBouncer.prepare();
+ if (hideBouncerWhenShowing) {
+ mBouncer.hide(false /* destroyView */);
+ mBouncer.prepare();
+ }
}
}
@@ -163,14 +165,14 @@
/**
* Reset the state of the view.
*/
- public void reset() {
+ public void reset(boolean hideBouncerWhenShowing) {
if (mShowing) {
if (mOccluded) {
mPhoneStatusBar.hideKeyguard();
mPhoneStatusBar.stopWaitingForKeyguardExit();
mBouncer.hide(false /* destroyView */);
} else {
- showBouncerOrKeyguard();
+ showBouncerOrKeyguard(hideBouncerWhenShowing);
}
KeyguardUpdateMonitor.getInstance(mContext).sendKeyguardReset();
updateStates();
@@ -257,7 +259,7 @@
@Override
public void run() {
mStatusBarWindowManager.setKeyguardOccluded(mOccluded);
- reset();
+ reset(true /* hideBouncerWhenShowing */);
}
});
return;
@@ -268,7 +270,10 @@
mPhoneStatusBar.updateMediaMetaData(false, animate && !occluded);
}
mStatusBarWindowManager.setKeyguardOccluded(occluded);
- reset();
+
+ // If Keyguard is reshown, don't hide the bouncer as it might just have been requested by
+ // a FLAG_DISMISS_KEYGUARD_ACTIVITY.
+ reset(false /* hideBouncerWhenShowing*/);
if (animate && !occluded && mShowing) {
mPhoneStatusBar.animateKeyguardUnoccluding();
}
@@ -418,9 +423,7 @@
* Dismisses the keyguard by going to the next screen or making it gone.
*/
public void dismiss() {
- if (mDeviceInteractive || mDeviceWillWakeUp) {
- showBouncer();
- }
+ showBouncer();
}
/**
@@ -445,7 +448,7 @@
public boolean onBackPressed() {
if (mBouncer.isShowing()) {
mPhoneStatusBar.endAffordanceLaunch();
- reset();
+ reset(true /* hideBouncerWhenShowing */);
return true;
}
return false;
@@ -556,17 +559,8 @@
return mBouncer.interceptMediaKey(event);
}
- public void onActivityDrawn() {
- if (mPhoneStatusBar.isCollapsing()) {
- mPhoneStatusBar.addPostCollapseAction(new Runnable() {
- @Override
- public void run() {
- mViewMediatorCallback.readyForKeyguardDone();
- }
- });
- } else {
- mViewMediatorCallback.readyForKeyguardDone();
- }
+ public void readyForKeyguardDone() {
+ mViewMediatorCallback.readyForKeyguardDone();
}
public boolean shouldDisableWindowAnimationsForUnlock() {
@@ -581,10 +575,6 @@
return mBouncer.isSecure() || mLockPatternUtils.isSecure(userId);
}
- public boolean isInputRestricted() {
- return mViewMediatorCallback.isInputRestricted();
- }
-
public void keyguardGoingAway() {
mPhoneStatusBar.keyguardGoingAway();
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 40f0aae..5d41d36 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.am;
import android.app.ApplicationThreadConstants;
+import android.annotation.Nullable;
import android.os.IDeviceIdentifiersPolicyService;
import android.util.Size;
import android.util.TypedValue;
@@ -312,7 +313,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_IMMERSIVE;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKSCREEN;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LRU;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
@@ -374,13 +374,14 @@
import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_RELAUNCH;
+import static com.android.server.wm.AppTransition.TRANSIT_NONE;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_TO_FRONT;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
-public final class ActivityManagerService extends ActivityManagerNative
+public class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityManagerService" : TAG_AM;
@@ -549,6 +550,7 @@
/** Run all ActivityStacks through this */
final ActivityStackSupervisor mStackSupervisor;
+ private final KeyguardController mKeyguardController;
final ActivityStarter mActivityStarter;
@@ -632,7 +634,7 @@
public boolean canShowErrorDialogs() {
return mShowDialogs && !mSleeping && !mShuttingDown
- && mLockScreenShown != LOCK_SCREEN_SHOWN;
+ && !mKeyguardController.isKeyguardShowing();
}
private static final class PriorityState {
@@ -1251,14 +1253,6 @@
*/
final ArrayList<SleepToken> mSleepTokens = new ArrayList<SleepToken>();
- static final int LOCK_SCREEN_HIDDEN = 0;
- static final int LOCK_SCREEN_LEAVING = 1;
- static final int LOCK_SCREEN_SHOWN = 2;
- /**
- * State of external call telling us if the lock screen is shown.
- */
- int mLockScreenShown = LOCK_SCREEN_HIDDEN;
-
/**
* Set if we are shutting down the system, similar to sleeping.
*/
@@ -2621,6 +2615,7 @@
mStackSupervisor = new ActivityStackSupervisor(this);
mStackSupervisor.onConfigurationChanged(mTempConfig);
+ mKeyguardController = mStackSupervisor.mKeyguardController;
mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
mTaskChangeNotificationController =
@@ -3037,7 +3032,7 @@
mHandler.obtainMessage(VR_MODE_CHANGE_MSG, 0, 0, r));
}
- private void applyVrModeIfNeededLocked(ActivityRecord r, boolean enable) {
+ void applyVrModeIfNeededLocked(ActivityRecord r, boolean enable) {
mHandler.sendMessage(
mHandler.obtainMessage(VR_MODE_APPLY_IF_NEEDED_MSG, enable ? 1 : 0, 0, r));
}
@@ -4967,12 +4962,17 @@
finishInstrumentationLocked(app, Activity.RESULT_CANCELED, info);
}
- if (!restarting && hasVisibleActivities
- && !mStackSupervisor.resumeFocusedStackTopActivityLocked()) {
- // If there was nothing to resume, and we are not already restarting this process, but
- // there is a visible activity that is hosted by the process... then make sure all
- // visible activities are running, taking care of restarting this process.
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mWindowManager.deferSurfaceLayout();
+ try {
+ if (!restarting && hasVisibleActivities
+ && !mStackSupervisor.resumeFocusedStackTopActivityLocked()) {
+ // If there was nothing to resume, and we are not already restarting this process, but
+ // there is a visible activity that is hosted by the process... then make sure all
+ // visible activities are running, taking care of restarting this process.
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ }
+ } finally {
+ mWindowManager.continueSurfaceLayout();
}
}
@@ -6602,39 +6602,12 @@
}
@Override
- public void keyguardWaitingForActivityDrawn() {
- enforceNotIsolatedCaller("keyguardWaitingForActivityDrawn");
- final long token = Binder.clearCallingIdentity();
- try {
- synchronized (this) {
- if (DEBUG_LOCKSCREEN) logLockScreen("");
- mWindowManager.keyguardWaitingForActivityDrawn();
- if (mLockScreenShown == LOCK_SCREEN_SHOWN) {
- mLockScreenShown = LOCK_SCREEN_LEAVING;
- updateSleepIfNeededLocked();
- }
- }
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override
public void keyguardGoingAway(int flags) {
enforceNotIsolatedCaller("keyguardGoingAway");
final long token = Binder.clearCallingIdentity();
try {
synchronized (this) {
- if (DEBUG_LOCKSCREEN) logLockScreen("");
- mWindowManager.keyguardGoingAway(flags);
- if (mLockScreenShown == LOCK_SCREEN_SHOWN) {
- mLockScreenShown = LOCK_SCREEN_HIDDEN;
- updateSleepIfNeededLocked();
-
- // Some stack visibility might change (e.g. docked stack)
- mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
- applyVrModeIfNeededLocked(mStackSupervisor.getResumedActivityLocked(), true);
- }
+ mKeyguardController.keyguardGoingAway(flags);
}
} finally {
Binder.restoreCallingIdentity(token);
@@ -6785,6 +6758,7 @@
final long origId = Binder.clearCallingIdentity();
synchronized(this) {
ActivityRecord.activityResumedLocked(token);
+ mWindowManager.notifyAppResumedFinished(token);
}
Binder.restoreCallingIdentity(origId);
}
@@ -11524,7 +11498,7 @@
case PowerManagerInternal.WAKEFULNESS_DOZING:
// Pause applications whenever the lock screen is shown or any sleep
// tokens have been acquired.
- return (mLockScreenShown != LOCK_SCREEN_HIDDEN || !mSleepTokens.isEmpty());
+ return mKeyguardController.isKeyguardShowing() || !mSleepTokens.isEmpty();
case PowerManagerInternal.WAKEFULNESS_ASLEEP:
default:
// If we're asleep then pause applications unconditionally.
@@ -11592,22 +11566,6 @@
Binder.restoreCallingIdentity(origId);
}
- private String lockScreenShownToString() {
- switch (mLockScreenShown) {
- case LOCK_SCREEN_HIDDEN: return "LOCK_SCREEN_HIDDEN";
- case LOCK_SCREEN_LEAVING: return "LOCK_SCREEN_LEAVING";
- case LOCK_SCREEN_SHOWN: return "LOCK_SCREEN_SHOWN";
- default: return "Unknown=" + mLockScreenShown;
- }
- }
-
- void logLockScreen(String msg) {
- if (DEBUG_LOCKSCREEN) Slog.d(TAG_LOCKSCREEN, Debug.getCallers(2) + ":" + msg
- + " mLockScreenShown=" + lockScreenShownToString() + " mWakefulness="
- + PowerManagerInternal.wakefulnessToString(mWakefulness)
- + " mSleeping=" + mSleeping);
- }
-
void startRunningVoiceLocked(IVoiceInteractionSession session, int targetUid) {
Slog.d(TAG, "<<< startRunningVoiceLocked()");
mVoiceWakeLock.setWorkSource(new WorkSource(targetUid));
@@ -11625,7 +11583,8 @@
mWindowManager.setEventDispatching(mBooted && !mShuttingDown);
}
- public void setLockScreenShown(boolean showing, boolean occluded) {
+ @Override
+ public void setLockScreenShown(boolean showing) {
if (checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
@@ -11635,18 +11594,7 @@
synchronized(this) {
long ident = Binder.clearCallingIdentity();
try {
- if (DEBUG_LOCKSCREEN) logLockScreen(" showing=" + showing + " occluded=" + occluded);
- mLockScreenShown = (showing && !occluded) ? LOCK_SCREEN_SHOWN : LOCK_SCREEN_HIDDEN;
- if (showing && occluded) {
- // The lock screen is currently showing, but is occluded by a window that can
- // show on top of the lock screen. In this can we want to dismiss the docked
- // stack since it will be complicated/risky to try to put the activity on top
- // of the lock screen in the right fullscreen configuration.
- mStackSupervisor.moveTasksToFullscreenStackLocked(DOCKED_STACK_ID,
- mStackSupervisor.mFocusedStack.getStackId() == DOCKED_STACK_ID);
- }
-
- updateSleepIfNeededLocked();
+ mKeyguardController.setKeyguardShown(showing);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -14652,8 +14600,7 @@
pw.println(" mWakefulness="
+ PowerManagerInternal.wakefulnessToString(mWakefulness));
pw.println(" mSleepTokens=" + mSleepTokens);
- pw.println(" mSleeping=" + mSleeping + " mLockScreenShown="
- + lockScreenShownToString());
+ pw.println(" mSleeping=" + mSleeping);
pw.println(" mShuttingDown=" + mShuttingDown + " mTestPssMode=" + mTestPssMode);
if (mRunningVoice != null) {
pw.println(" mRunningVoice=" + mRunningVoice);
@@ -22091,6 +22038,21 @@
public int getUidProcessState(int uid) {
return getUidState(uid);
}
+
+ @Override
+ public void notifyKeyguardFlagsChanged(@Nullable Runnable callback) {
+ synchronized (ActivityManagerService.this) {
+
+ // We might change the visibilities here, so prepare an empty app transition which
+ // might be overridden later if we actually change visibilities.
+ mWindowManager.prepareAppTransition(TRANSIT_NONE, false /* alwaysKeepCurrent */);
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mWindowManager.executeAppTransition();
+ }
+ if (callback != null) {
+ callback.run();
+ }
+ }
}
private final class SleepTokenImpl extends SleepToken {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 1484420..8234f35 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -141,7 +141,8 @@
case "broadcast":
return runSendBroadcast(pw);
case "instrument":
- return runInstrument(pw);
+ getOutPrintWriter().println("Error: must be invoked through 'am instrument'.");
+ return -1;
case "trace-ipc":
return runTraceIpc(pw);
case "profile":
@@ -561,224 +562,6 @@
return 0;
}
- final static class InstrumentationWatcher extends IInstrumentationWatcher.Stub {
- private final IActivityManager mInterface;
- private final PrintWriter mPw;
- private boolean mFinished = false;
- private boolean mRawMode = false;
-
- InstrumentationWatcher(IActivityManager iam, PrintWriter pw) {
- mInterface = iam;
- mPw = pw;
- }
-
- /**
- * Set or reset "raw mode". In "raw mode", all bundles are dumped. In "pretty mode",
- * if a bundle includes Instrumentation.REPORT_KEY_STREAMRESULT, just print that.
- * @param rawMode true for raw mode, false for pretty mode.
- */
- public void setRawOutput(boolean rawMode) {
- mRawMode = rawMode;
- }
-
- @Override
- public void instrumentationStatus(ComponentName name, int resultCode, Bundle results) {
- synchronized (this) {
- // pretty printer mode?
- String pretty = null;
- if (!mRawMode && results != null) {
- pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
- }
- if (pretty != null) {
- mPw.print(pretty);
- } else {
- if (results != null) {
- for (String key : results.keySet()) {
- mPw.println(
- "INSTRUMENTATION_STATUS: " + key + "=" + results.get(key));
- }
- }
- mPw.println("INSTRUMENTATION_STATUS_CODE: " + resultCode);
- }
- mPw.flush();
- notifyAll();
- }
- }
-
- @Override
- public void instrumentationFinished(ComponentName name, int resultCode,
- Bundle results) {
- synchronized (this) {
- // pretty printer mode?
- String pretty = null;
- if (!mRawMode && results != null) {
- pretty = results.getString(Instrumentation.REPORT_KEY_STREAMRESULT);
- }
- if (pretty != null) {
- mPw.println(pretty);
- } else {
- if (results != null) {
- for (String key : results.keySet()) {
- mPw.println(
- "INSTRUMENTATION_RESULT: " + key + "=" + results.get(key));
- }
- }
- mPw.println("INSTRUMENTATION_CODE: " + resultCode);
- }
- mPw.flush();
- mFinished = true;
- notifyAll();
- }
- }
-
- public boolean waitForFinish() {
- synchronized (this) {
- while (!mFinished) {
- try {
- if (!mInterface.asBinder().pingBinder()) {
- return false;
- }
- wait(1000);
- } catch (InterruptedException e) {
- throw new IllegalStateException(e);
- }
- }
- }
- return true;
- }
- }
-
- int runInstrument(PrintWriter pw) throws RemoteException {
- final PrintWriter err = getErrPrintWriter();
- String profileFile = null;
- boolean wait = false;
- boolean rawMode = false;
- boolean no_window_animation = false;
- int userId = UserHandle.USER_CURRENT;
- Bundle args = new Bundle();
- String argKey = null, argValue = null;
- IWindowManager wm = IWindowManager.Stub.asInterface(ServiceManager.getService("window"));
- String abi = null;
-
- String opt;
- while ((opt=getNextOption()) != null) {
- if (opt.equals("-p")) {
- profileFile = getNextArgRequired();
- } else if (opt.equals("-w")) {
- wait = true;
- } else if (opt.equals("-r")) {
- rawMode = true;
- } else if (opt.equals("-e")) {
- argKey = getNextArgRequired();
- argValue = getNextArgRequired();
- args.putString(argKey, argValue);
- } else if (opt.equals("--no_window_animation")
- || opt.equals("--no-window-animation")) {
- no_window_animation = true;
- } else if (opt.equals("--user")) {
- userId = UserHandle.parseUserArg(getNextArgRequired());
- } else if (opt.equals("--abi")) {
- abi = getNextArgRequired();
- } else {
- err.println("Error: Unknown option: " + opt);
- return -1;
- }
- }
-
- if (userId == UserHandle.USER_ALL) {
- err.println("Error: Can't start instrumentation with user 'all'");
- return -1;
- }
-
- String cnArg = getNextArgRequired();
-
- ComponentName cn;
- if (cnArg.contains("/")) {
- cn = ComponentName.unflattenFromString(cnArg);
- if (cn == null) throw new IllegalArgumentException("Bad component name: " + cnArg);
- } else {
- List<InstrumentationInfo> infos = mPm.queryInstrumentation(null, 0).getList();
-
- final int numInfos = infos == null ? 0: infos.size();
- List<ComponentName> cns = new ArrayList<>();
- for (int i = 0; i < numInfos; i++) {
- InstrumentationInfo info = infos.get(i);
-
- ComponentName c = new ComponentName(info.packageName, info.name);
- if (cnArg.equals(info.packageName)) {
- cns.add(c);
- }
- }
-
- if (cns.size() == 0) {
- throw new IllegalArgumentException("No instrumentation found for: " + cnArg);
- } else if (cns.size() == 1) {
- cn = cns.get(0);
- } else {
- StringBuilder cnsStr = new StringBuilder();
- final int numCns = cns.size();
- for (int i = 0; i < numCns; i++) {
- cnsStr.append(cns.get(i).flattenToString());
- cnsStr.append(", ");
- }
-
- // Remove last ", "
- cnsStr.setLength(cnsStr.length() - 2);
-
- throw new IllegalArgumentException("Found multiple instrumentations: "
- + cnsStr.toString());
- }
- }
-
- InstrumentationWatcher watcher = null;
- UiAutomationConnection connection = null;
- if (wait) {
- watcher = new InstrumentationWatcher(mInterface, pw);
- watcher.setRawOutput(rawMode);
- // Don't yet know how to support this.
- connection = null; //new UiAutomationConnection();
- }
-
- float[] oldAnims = null;
- if (no_window_animation) {
- oldAnims = wm.getAnimationScales();
- wm.setAnimationScale(0, 0.0f);
- wm.setAnimationScale(1, 0.0f);
- }
-
- if (abi != null) {
- final String[] supportedAbis = Build.SUPPORTED_ABIS;
- boolean matched = false;
- for (String supportedAbi : supportedAbis) {
- if (supportedAbi.equals(abi)) {
- matched = true;
- break;
- }
- }
-
- if (!matched) {
- throw new RuntimeException(
- "INSTRUMENTATION_FAILED: Unsupported instruction set " + abi);
- }
- }
-
- if (!mInterface.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId,
- abi)) {
- throw new RuntimeException("INSTRUMENTATION_FAILED: " + cn.flattenToString());
- }
-
- if (watcher != null) {
- if (!watcher.waitForFinish()) {
- pw.println("INSTRUMENTATION_ABORTED: System has crashed.");
- }
- }
-
- if (oldAnims != null) {
- wm.setAnimationScales(oldAnims);
- }
- return 0;
- }
-
int runTraceIpc(PrintWriter pw) throws RemoteException {
String op = getNextArgRequired();
if (op.equals("start")) {
@@ -2550,6 +2333,25 @@
pw.println(" --user <USER_ID> | all | current: Specify which user to send to; if not");
pw.println(" specified then send to all users.");
pw.println(" --receiver-permission <PERMISSION>: Require receiver to hold permission.");
+ pw.println(" instrument [-r] [-e <NAME> <VALUE>] [-p <FILE>] [-w]");
+ pw.println(" [--user <USER_ID> | current]");
+ pw.println(" [--no-window-animation] [--abi <ABI>] <COMPONENT>");
+ pw.println(" Start an Instrumentation. Typically this target <COMPONENT> is in the");
+ pw.println(" form <TEST_PACKAGE>/<RUNNER_CLASS> or only <TEST_PACKAGE> if there");
+ pw.println(" is only one instrumentation. Options are:");
+ pw.println(" -r: print raw results (otherwise decode REPORT_KEY_STREAMRESULT). Use with");
+ pw.println(" [-e perf true] to generate raw output for performance measurements.");
+ pw.println(" -e <NAME> <VALUE>: set argument <NAME> to <VALUE>. For test runners a");
+ pw.println(" common form is [-e <testrunner_flag> <value>[,<value>...]].");
+ pw.println(" -p <FILE>: write profiling data to <FILE>");
+ pw.println(" -m: Write output as protobuf (machine readable)");
+ pw.println(" -w: wait for instrumentation to finish before returning. Required for");
+ pw.println(" test runners.");
+ pw.println(" --user <USER_ID> | current: Specify user instrumentation runs in;");
+ pw.println(" current user if not specified.");
+ pw.println(" --no-window-animation: turn off window animations while running.");
+ pw.println(" --abi <ABI>: Launch the instrumented process with the selected ABI.");
+ pw.println(" This assumes that the process supports the selected ABI.");
pw.println(" trace-ipc [start|stop] [--dump-file <FILE>]");
pw.println(" Trace IPC transactions.");
pw.println(" start: start tracing IPC transactions.");
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index df03af2..90b46ed 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -83,6 +83,7 @@
import android.view.AppTransitionAnimationSpec;
import android.view.IApplicationToken;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.ReferrerIntent;
@@ -721,7 +722,7 @@
: android.R.style.Theme_Holo;
}
if ((aInfo.flags&ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
- windowFlags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
}
if ((aInfo.flags&ActivityInfo.FLAG_MULTIPROCESS) != 0
&& _caller != null
@@ -929,6 +930,22 @@
return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
}
+ /**
+ * @return true if the activity contains windows that have
+ * {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set
+ */
+ boolean hasShowWhenLockedWindows() {
+ return service.mWindowManager.containsShowWhenLockedWindow(appToken);
+ }
+
+ /**
+ * @return true if the activity contains windows that have
+ * {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set
+ */
+ boolean hasDismissKeyguardWindows() {
+ return service.mWindowManager.containsDismissKeyguardWindow(appToken);
+ }
+
void makeFinishingLocked() {
if (!finishing) {
final ActivityStack stack = getStack();
@@ -1334,7 +1351,6 @@
if (nowVisible) {
// We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now.
mStackSupervisor.reportActivityVisibleLocked(this);
- mStackSupervisor.notifyActivityDrawnForKeyguard();
}
// Schedule an idle timeout in case the app doesn't do it for us.
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index fc41fd3..ffe2185 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -31,7 +31,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_APP;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKSCREEN;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE;
import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RESULTS;
@@ -60,7 +59,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityManagerService.LOCK_SCREEN_SHOWN;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.STARTING_WINDOW_REMOVED;
@@ -332,6 +330,9 @@
private final LaunchingTaskPositioner mTaskPositioner;
+ private boolean mTopActivityOccludesKeyguard;
+ private ActivityRecord mTopDismissingKeyguardActivity;
+
static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
@@ -1169,7 +1170,12 @@
if (mPausingActivity == r) {
if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
+ (timeout ? " (due to timeout)" : " (pause complete)"));
- completePauseLocked(true, null);
+ mService.mWindowManager.deferSurfaceLayout();
+ try {
+ completePauseLocked(true, null);
+ } finally {
+ mService.mWindowManager.continueSurfaceLayout();
+ }
return;
} else {
EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
@@ -1581,153 +1587,218 @@
*/
final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
boolean preserveWindows) {
- ActivityRecord top = topRunningActivityLocked();
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + top
- + " configChanges=0x" + Integer.toHexString(configChanges));
- if (top != null) {
- checkTranslucentActivityWaiting(top);
- }
+ mTopActivityOccludesKeyguard = false;
+ mTopDismissingKeyguardActivity = null;
+ mStackSupervisor.mKeyguardController.beginActivityVisibilityUpdate();
+ try {
+ ActivityRecord top = topRunningActivityLocked();
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + top
+ + " configChanges=0x" + Integer.toHexString(configChanges));
+ if (top != null) {
+ checkTranslucentActivityWaiting(top);
+ }
- // If the top activity is not fullscreen, then we need to
- // make sure any activities under it are now visible.
- boolean aboveTop = top != null;
- final int stackVisibility = getStackVisibilityLocked(starting);
- final boolean stackInvisible = stackVisibility != STACK_VISIBLE;
- final boolean stackVisibleBehind = stackVisibility == STACK_VISIBLE_ACTIVITY_BEHIND;
- boolean behindFullscreenActivity = stackInvisible;
- boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this)
- && (isInStackLocked(starting) == null);
- boolean behindTranslucentActivity = false;
- final ActivityRecord visibleBehind = getVisibleBehindActivity();
- for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
- final TaskRecord task = mTaskHistory.get(taskNdx);
- final ArrayList<ActivityRecord> activities = task.mActivities;
- for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
- final ActivityRecord r = activities.get(activityNdx);
- if (r.finishing) {
- // Normally the screenshot will be taken in makeInvisible(). When an activity
- // is finishing, we no longer change its visibility, but we still need to take
- // the screenshots if startPausingLocked decided it should be taken.
- if (r.mUpdateTaskThumbnailWhenHidden) {
- r.updateThumbnailLocked(r.screenshotActivityLocked(),
- null /* description */);
- r.mUpdateTaskThumbnailWhenHidden = false;
+ // If the top activity is not fullscreen, then we need to
+ // make sure any activities under it are now visible.
+ boolean aboveTop = top != null;
+ final int stackVisibility = getStackVisibilityLocked(starting);
+ final boolean stackInvisible = stackVisibility != STACK_VISIBLE;
+ final boolean stackVisibleBehind = stackVisibility == STACK_VISIBLE_ACTIVITY_BEHIND;
+ boolean behindFullscreenActivity = stackInvisible;
+ boolean resumeNextActivity = mStackSupervisor.isFocusedStack(this)
+ && (isInStackLocked(starting) == null);
+ boolean behindTranslucentActivity = false;
+ final ActivityRecord visibleBehind = getVisibleBehindActivity();
+ for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+ final TaskRecord task = mTaskHistory.get(taskNdx);
+ final ArrayList<ActivityRecord> activities = task.mActivities;
+ for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+ final ActivityRecord r = activities.get(activityNdx);
+ if (r.finishing) {
+ // Normally the screenshot will be taken in makeInvisible(). When an activity
+ // is finishing, we no longer change its visibility, but we still need to take
+ // the screenshots if startPausingLocked decided it should be taken.
+ if (r.mUpdateTaskThumbnailWhenHidden) {
+ r.updateThumbnailLocked(r.screenshotActivityLocked(),
+ null /* description */);
+ r.mUpdateTaskThumbnailWhenHidden = false;
+ }
+ continue;
}
- continue;
- }
- final boolean isTop = r == top;
- if (aboveTop && !isTop) {
- continue;
- }
- aboveTop = false;
-
- if (r.shouldBeVisible(behindTranslucentActivity, stackVisibleBehind,
- visibleBehind, behindFullscreenActivity)) {
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
- + " finishing=" + r.finishing + " state=" + r.state);
- // First: if this is not the current activity being started, make
- // sure it matches the current configuration.
- if (r != starting) {
- r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindows);
+ final boolean isTop = r == top;
+ if (aboveTop && !isTop) {
+ continue;
}
+ aboveTop = false;
- if (r.app == null || r.app.thread == null) {
- if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop,
- resumeNextActivity, r)) {
- if (activityNdx >= activities.size()) {
- // Record may be removed if its process needs to restart.
- activityNdx = activities.size() - 1;
- } else {
+ // Check whether activity should be visible without Keyguard influence
+ final boolean shouldBeVisible = r.shouldBeVisible(behindTranslucentActivity,
+ stackVisibleBehind, visibleBehind, behindFullscreenActivity);
+
+ // Now check whether it's really visible depending on Keyguard state.
+ final boolean reallyVisible = checkKeyguardVisibility(r, shouldBeVisible,
+ isTop);
+ if (shouldBeVisible) {
+ behindFullscreenActivity = updateBehindFullscreen(stackInvisible,
+ behindFullscreenActivity, task, r);
+ if (behindFullscreenActivity && !r.fullscreen) {
+ behindTranslucentActivity = true;
+ }
+ }
+ if (reallyVisible) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r
+ + " finishing=" + r.finishing + " state=" + r.state);
+ // First: if this is not the current activity being started, make
+ // sure it matches the current configuration.
+ if (r != starting) {
+ r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindows);
+ }
+
+ if (r.app == null || r.app.thread == null) {
+ if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop,
+ resumeNextActivity, r)) {
+ if (activityNdx >= activities.size()) {
+ // Record may be removed if its process needs to restart.
+ activityNdx = activities.size() - 1;
+ } else {
+ resumeNextActivity = false;
+ }
+ }
+ } else if (r.visible) {
+ // If this activity is already visible, then there is nothing to do here.
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+ "Skipping: already visible at " + r);
+
+ if (r.handleAlreadyVisible()) {
resumeNextActivity = false;
}
+ } else {
+ r.makeVisibleIfNeeded(starting);
}
- } else if (r.visible) {
- // If this activity is already visible, then there is nothing to do here.
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
- "Skipping: already visible at " + r);
-
- if (r.handleAlreadyVisible()) {
- resumeNextActivity = false;
- }
+ // Aggregate current change flags.
+ configChanges |= r.configChangeFlags;
} else {
- r.makeVisibleIfNeeded(starting);
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
+ + " finishing=" + r.finishing + " state=" + r.state + " stackInvisible="
+ + stackInvisible + " behindFullscreenActivity="
+ + behindFullscreenActivity + " mLaunchTaskBehind="
+ + r.mLaunchTaskBehind);
+ makeInvisible(r, visibleBehind);
}
- // Aggregate current change flags.
- configChanges |= r.configChangeFlags;
- behindFullscreenActivity = updateBehindFullscreen(stackInvisible,
- behindFullscreenActivity, task, r);
- if (behindFullscreenActivity && !r.fullscreen) {
- behindTranslucentActivity = true;
+ }
+ if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
+ // The visibility of tasks and the activities they contain in freeform stack are
+ // determined individually unlike other stacks where the visibility or fullscreen
+ // status of an activity in a previous task affects other.
+ behindFullscreenActivity = stackVisibility == STACK_INVISIBLE;
+ } else if (mStackId == HOME_STACK_ID) {
+ if (task.isOnTopLauncher()) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "On-top launcher: at " + task
+ + " stackInvisible=" + stackInvisible
+ + " behindFullscreenActivity=" + behindFullscreenActivity);
+ // When an on-top launcher is visible, (e.g. it's on the top of the home stack),
+ // other tasks in the home stack could be visible if and only if:
+ // - some app is running in the docked stack;
+ // - no app is running in either the fullscreen stack or the freefrom stack.
+ final ActivityStack dockedStack = mStackSupervisor.getStack(DOCKED_STACK_ID);
+ final ActivityStack fullscreenStack = mStackSupervisor.getStack(
+ FULLSCREEN_WORKSPACE_STACK_ID);
+ final ActivityStack freeformStack = mStackSupervisor.getStack(
+ FREEFORM_WORKSPACE_STACK_ID);
+ final boolean dockedStackEmpty = dockedStack == null ||
+ dockedStack.topRunningActivityLocked() == null;
+ final boolean fullscreenStackEmpty = fullscreenStack == null ||
+ fullscreenStack.topRunningActivityLocked() == null;
+ final boolean freeformStackEmpty = freeformStack == null ||
+ freeformStack.topRunningActivityLocked() == null;
+ behindFullscreenActivity = dockedStackEmpty || !fullscreenStackEmpty ||
+ !freeformStackEmpty;
+ } else if (task.isHomeTask()) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task
+ + " stackInvisible=" + stackInvisible
+ + " behindFullscreenActivity=" + behindFullscreenActivity);
+ // No other task in the home stack should be visible behind the home activity.
+ // Home activities is usually a translucent activity with the wallpaper behind
+ // them. However, when they don't have the wallpaper behind them, we want to
+ // show activities in the next application stack behind them vs. another
+ // task in the home stack like recents.
+ behindFullscreenActivity = true;
+ } else if (task.isRecentsTask()
+ && task.getTaskToReturnTo() == APPLICATION_ACTIVITY_TYPE) {
+ if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
+ "Recents task returning to app: at " + task
+ + " stackInvisible=" + stackInvisible
+ + " behindFullscreenActivity=" + behindFullscreenActivity);
+ // We don't want any other tasks in the home stack visible if the recents
+ // activity is going to be returning to an application activity type.
+ // We do this to preserve the visible order the user used to get into the
+ // recents activity. The recents activity is normally translucent and if it
+ // doesn't have the wallpaper behind it the next activity in the home stack
+ // shouldn't be visible when the home stack is brought to the front to display
+ // the recents activity from an app.
+ behindFullscreenActivity = true;
}
- } else {
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r
- + " finishing=" + r.finishing + " state=" + r.state + " stackInvisible="
- + stackInvisible + " behindFullscreenActivity="
- + behindFullscreenActivity + " mLaunchTaskBehind="
- + r.mLaunchTaskBehind);
- makeInvisible(r, visibleBehind);
+
}
}
- if (mStackId == FREEFORM_WORKSPACE_STACK_ID) {
- // The visibility of tasks and the activities they contain in freeform stack are
- // determined individually unlike other stacks where the visibility or fullscreen
- // status of an activity in a previous task affects other.
- behindFullscreenActivity = stackVisibility == STACK_INVISIBLE;
- } else if (mStackId == HOME_STACK_ID) {
- if (task.isOnTopLauncher()) {
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "On-top launcher: at " + task
- + " stackInvisible=" + stackInvisible
- + " behindFullscreenActivity=" + behindFullscreenActivity);
- // When an on-top launcher is visible, (e.g. it's on the top of the home stack),
- // other tasks in the home stack could be visible if and only if:
- // - some app is running in the docked stack;
- // - no app is running in either the fullscreen stack or the freefrom stack.
- final ActivityStack dockedStack = mStackSupervisor.getStack(DOCKED_STACK_ID);
- final ActivityStack fullscreenStack = mStackSupervisor.getStack(
- FULLSCREEN_WORKSPACE_STACK_ID);
- final ActivityStack freeformStack = mStackSupervisor.getStack(
- FREEFORM_WORKSPACE_STACK_ID);
- final boolean dockedStackEmpty = dockedStack == null ||
- dockedStack.topRunningActivityLocked() == null;
- final boolean fullscreenStackEmpty = fullscreenStack == null ||
- fullscreenStack.topRunningActivityLocked() == null;
- final boolean freeformStackEmpty = freeformStack == null ||
- freeformStack.topRunningActivityLocked() == null;
- behindFullscreenActivity = dockedStackEmpty || !fullscreenStackEmpty ||
- !freeformStackEmpty;
- } else if (task.isHomeTask()) {
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task
- + " stackInvisible=" + stackInvisible
- + " behindFullscreenActivity=" + behindFullscreenActivity);
- // No other task in the home stack should be visible behind the home activity.
- // Home activities is usually a translucent activity with the wallpaper behind
- // them. However, when they don't have the wallpaper behind them, we want to
- // show activities in the next application stack behind them vs. another
- // task in the home stack like recents.
- behindFullscreenActivity = true;
- } else if (task.isRecentsTask()
- && task.getTaskToReturnTo() == APPLICATION_ACTIVITY_TYPE) {
- if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
- "Recents task returning to app: at " + task
- + " stackInvisible=" + stackInvisible
- + " behindFullscreenActivity=" + behindFullscreenActivity);
- // We don't want any other tasks in the home stack visible if the recents
- // activity is going to be returning to an application activity type.
- // We do this to preserve the visible order the user used to get into the
- // recents activity. The recents activity is normally translucent and if it
- // doesn't have the wallpaper behind it the next activity in the home stack
- // shouldn't be visible when the home stack is brought to the front to display
- // the recents activity from an app.
- behindFullscreenActivity = true;
- }
+ if (mTranslucentActivityWaiting != null &&
+ mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
+ // Nothing is getting drawn or everything was already visible, don't wait for timeout.
+ notifyActivityDrawnLocked(null);
+ }
+ } finally {
+ mStackSupervisor.mKeyguardController.endActivityVisibilityUpdate();
+ }
+ }
+
+ /**
+ * @return true if the top visible activity wants to occlude the Keyguard, false otherwise
+ */
+ boolean topActivityOccludesKeyguard() {
+ return mTopActivityOccludesKeyguard;
+ }
+
+ /**
+ * @return the top most visible activity that wants to dismiss Keyguard
+ */
+ ActivityRecord getTopDismissingKeyguardActivity() {
+ return mTopDismissingKeyguardActivity;
+ }
+
+ /**
+ * Checks whether {@param r} should be visible depending on Keyguard state and updates
+ * {@link #mTopActivityOccludesKeyguard} and {@link #mTopDismissingKeyguardActivity} if
+ * necessary.
+ *
+ * @return true if {@param r} is visible taken Keyguard state into account, false otherwise
+ */
+ private boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible,
+ boolean isTop) {
+ final boolean keyguardShowing = mStackSupervisor.mKeyguardController.isKeyguardShowing();
+ final boolean keyguardLocked = mStackSupervisor.mKeyguardController.isKeyguardLocked();
+ final boolean showWhenLocked = r.hasShowWhenLockedWindows();
+ if (shouldBeVisible) {
+ if (r.hasDismissKeyguardWindows() && mTopDismissingKeyguardActivity == null) {
+ mTopDismissingKeyguardActivity = r;
+ }
+
+ // Only the top activity may control occluded, as we can't occlude the Keyguard if the
+ // top app doesn't want to occlude it.
+ if (isTop) {
+ mTopActivityOccludesKeyguard |= showWhenLocked;
}
}
+ if (keyguardShowing) {
- if (mTranslucentActivityWaiting != null &&
- mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
- // Nothing is getting drawn or everything was already visible, don't wait for timeout.
- notifyActivityDrawnLocked(null);
+ // If keyguard is showing, nothing is visible.
+ return false;
+ } else if (keyguardLocked) {
+
+ // Show when locked windows above keyguard.
+ return shouldBeVisible && showWhenLocked;
+ } else {
+ return shouldBeVisible;
}
}
@@ -1947,10 +2018,6 @@
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
- if (mService.mLockScreenShown == ActivityManagerService.LOCK_SCREEN_LEAVING) {
- mService.mLockScreenShown = ActivityManagerService.LOCK_SCREEN_HIDDEN;
- mService.updateSleepIfNeededLocked();
- }
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
@@ -1969,8 +2036,6 @@
}
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
- if (DEBUG_LOCKSCREEN) mService.logLockScreen("");
-
if (!mService.mBooting && !mService.mBooted) {
// Not ready yet!
return false;
@@ -3287,72 +3352,77 @@
return false;
}
- r.makeFinishingLocked();
- final TaskRecord task = r.task;
- EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
- r.userId, System.identityHashCode(r),
- task.taskId, r.shortComponentName, reason);
- final ArrayList<ActivityRecord> activities = task.mActivities;
- final int index = activities.indexOf(r);
- if (index < (activities.size() - 1)) {
- task.setFrontOfTask();
- if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
- // If the caller asked that this activity (and all above it)
- // be cleared when the task is reset, don't lose that information,
- // but propagate it up to the next activity.
- ActivityRecord next = activities.get(index+1);
- next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ mWindowManager.deferSurfaceLayout();
+ try {
+ r.makeFinishingLocked();
+ final TaskRecord task = r.task;
+ EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
+ r.userId, System.identityHashCode(r),
+ task.taskId, r.shortComponentName, reason);
+ final ArrayList<ActivityRecord> activities = task.mActivities;
+ final int index = activities.indexOf(r);
+ if (index < (activities.size() - 1)) {
+ task.setFrontOfTask();
+ if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
+ // If the caller asked that this activity (and all above it)
+ // be cleared when the task is reset, don't lose that information,
+ // but propagate it up to the next activity.
+ ActivityRecord next = activities.get(index+1);
+ next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ }
}
- }
- r.pauseKeyDispatchingLocked();
+ r.pauseKeyDispatchingLocked();
- adjustFocusedActivityStackLocked(r, "finishActivity");
+ adjustFocusedActivityStackLocked(r, "finishActivity");
- finishActivityResultsLocked(r, resultCode, resultData);
+ finishActivityResultsLocked(r, resultCode, resultData);
- final boolean endTask = index <= 0;
- final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
- if (mResumedActivity == r) {
- if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
- "Prepare close transition: finishing " + r);
+ final boolean endTask = index <= 0;
+ final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
+ if (mResumedActivity == r) {
+ if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
+ "Prepare close transition: finishing " + r);
if (endTask) {
mService.mTaskChangeNotificationController.notifyTaskRemovalStarted(task.taskId);
}
- mWindowManager.prepareAppTransition(transit, false);
-
- // Tell window manager to prepare for this one to be removed.
- mWindowManager.setAppVisibility(r.appToken, false);
-
- if (mPausingActivity == null) {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
- if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
- "finish() => pause with userLeaving=false");
- startPausingLocked(false, false, null, false);
- }
-
- if (endTask) {
- mStackSupervisor.removeLockedTaskLocked(task);
- }
- } else if (r.state != ActivityState.PAUSING) {
- // If the activity is PAUSING, we will complete the finish once
- // it is done pausing; else we can just directly finish it here.
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
- if (r.visible) {
mWindowManager.prepareAppTransition(transit, false);
- mWindowManager.setAppVisibility(r.appToken, false);
- mWindowManager.executeAppTransition();
- if (!mStackSupervisor.mWaitingVisibleActivities.contains(r)) {
- mStackSupervisor.mWaitingVisibleActivities.add(r);
- }
- }
- return finishCurrentActivityLocked(r, (r.visible || r.nowVisible) ?
- FINISH_AFTER_VISIBLE : FINISH_AFTER_PAUSE, oomAdj) == null;
- } else {
- if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
- }
- return false;
+ // Tell window manager to prepare for this one to be removed.
+ mWindowManager.setAppVisibility(r.appToken, false);
+
+ if (mPausingActivity == null) {
+ if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r);
+ if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
+ "finish() => pause with userLeaving=false");
+ startPausingLocked(false, false, null, false);
+ }
+
+ if (endTask) {
+ mStackSupervisor.removeLockedTaskLocked(task);
+ }
+ } else if (r.state != ActivityState.PAUSING) {
+ // If the activity is PAUSING, we will complete the finish once
+ // it is done pausing; else we can just directly finish it here.
+ if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r);
+ if (r.visible) {
+ mWindowManager.prepareAppTransition(transit, false);
+ mWindowManager.setAppVisibility(r.appToken, false);
+ mWindowManager.executeAppTransition();
+ if (!mStackSupervisor.mWaitingVisibleActivities.contains(r)) {
+ mStackSupervisor.mWaitingVisibleActivities.add(r);
+ }
+ }
+ return finishCurrentActivityLocked(r, (r.visible || r.nowVisible) ?
+ FINISH_AFTER_VISIBLE : FINISH_AFTER_PAUSE, oomAdj) == null;
+ } else {
+ if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r);
+ }
+
+ return false;
+ } finally {
+ mWindowManager.continueSurfaceLayout();
+ }
}
static final int FINISH_IMMEDIATELY = 0;
@@ -4762,7 +4832,8 @@
voiceInteractor);
// add the task to stack first, mTaskPositioner might need the stack association
addTask(task, toTop, "createTaskRecord");
- final boolean isLockscreenShown = mService.mLockScreenShown == LOCK_SCREEN_SHOWN;
+ final boolean isLockscreenShown =
+ mService.mStackSupervisor.mKeyguardController.isKeyguardShowing();
if (!layoutTaskInStack(task, info.windowLayout) && mBounds != null && task.isResizeable()
&& !isLockscreenShown) {
task.updateOverrideConfiguration(mBounds);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index f0427e4..eed8dd7 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -16,6 +16,79 @@
package com.android.server.am;
+import static android.Manifest.permission.START_ANY_ACTIVITY;
+import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
+import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
+import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
+import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
+import static android.app.ActivityManager.RESIZE_MODE_FORCED;
+import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
+import static android.app.ActivityManager.START_TASK_TO_FRONT;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
+import static android.app.ActivityManager.StackId.FIRST_STATIC_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_IDLE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBLE_BEHIND;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONTAINERS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_IDLE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBLE_BEHIND;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.ActivityManagerService.ANIMATE;
+import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
+import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
+import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
+import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
+import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
+import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
+import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
+import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
+import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
+import static com.android.server.am.ActivityStack.STACK_VISIBLE;
+import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
+import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
+import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
+import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
+import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
+import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
+
import android.Manifest;
import android.annotation.UserIdInt;
import android.app.Activity;
@@ -26,7 +99,6 @@
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.AppOpsManager;
-import android.app.IActivityContainer;
import android.app.IActivityContainerCallback;
import android.app.IActivityManager;
import android.app.IActivityManager.WaitResult;
@@ -83,7 +155,6 @@
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.Display;
-import android.view.DisplayInfo;
import android.view.InputEvent;
import android.view.Surface;
@@ -106,79 +177,7 @@
import java.util.Objects;
import java.util.Set;
-import static android.Manifest.permission.START_ANY_ACTIVITY;
-import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
-import static android.app.ActivityManager.LOCK_TASK_MODE_LOCKED;
-import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
-import static android.app.ActivityManager.LOCK_TASK_MODE_PINNED;
-import static android.app.ActivityManager.RESIZE_MODE_FORCED;
-import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
-import static android.app.ActivityManager.START_TASK_TO_FRONT;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FIRST_DYNAMIC_STACK_ID;
-import static android.app.ActivityManager.StackId.FIRST_STATIC_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.HOME_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-import static android.app.ActivityManager.StackId.LAST_STATIC_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONTAINERS;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_IDLE;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKSCREEN;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PAUSE;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RELEASE;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
-import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBLE_BEHIND;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONTAINERS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_IDLE;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_PAUSE;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RELEASE;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
-import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBLE_BEHIND;
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
-import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityManagerService.ANIMATE;
-import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
-import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
-import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
-import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
-import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
-import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
-import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
-import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
-import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
-import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
-import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
-import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
-import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
-import static com.android.server.am.ActivityStack.STACK_VISIBLE;
-import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
-import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE;
-import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
-import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_PINNABLE;
-import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_WHITELISTED;
-import static com.android.server.wm.AppTransition.TRANSIT_DOCK_TASK_FROM_RECENTS;
-
-public final class ActivityStackSupervisor extends ConfigurationContainer
+public class ActivityStackSupervisor extends ConfigurationContainer
implements DisplayListener {
private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM;
private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
@@ -477,6 +476,8 @@
*/
boolean mIsDockMinimized;
+ final KeyguardController mKeyguardController;
+
/**
* Description of a request to start a new activity, which has been held
* due to app switches being disabled.
@@ -514,6 +515,7 @@
mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
mActivityMetricsLogger = new ActivityMetricsLogger(this, mService.mContext);
mResizeDockedStackTimeout = new ResizeDockedStackTimeout(service, this, mHandler);
+ mKeyguardController = new KeyguardController(service, this);
}
void setRecentTasks(RecentTasks recentTasks) {
@@ -562,6 +564,7 @@
void setWindowManager(WindowManagerService wm) {
synchronized (mService) {
mWindowManager = wm;
+ mKeyguardController.setWindowManager(wm);
mDisplayManager =
(DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
@@ -585,11 +588,6 @@
}
}
- void notifyActivityDrawnForKeyguard() {
- if (DEBUG_LOCKSCREEN) mService.logLockScreen("");
- mWindowManager.notifyActivityDrawnForKeyguard();
- }
-
ActivityStack getFocusedStack() {
return mFocusedStack;
}
@@ -1224,6 +1222,10 @@
displayId);
}
+ if (mKeyguardController.isKeyguardLocked()) {
+ mWindowManager.notifyUnknownAppVisibilityLaunched(r.appToken);
+ }
+
r.app = app;
app.waitingToKill = null;
r.launchCount++;
@@ -1944,7 +1946,7 @@
return null;
}
// TODO(multi-display): Allow creating stacks on secondary displays.
- return createStackOnDisplay(stackId, Display.DEFAULT_DISPLAY, createOnTop);
+ return createStackOnDisplay(stackId, DEFAULT_DISPLAY, createOnTop);
}
ArrayList<ActivityStack> getStacks() {
@@ -1955,6 +1957,10 @@
return allStacks;
}
+ ArrayList<ActivityStack> getStacksOnDefaultDisplay() {
+ return mActivityDisplays.valueAt(DEFAULT_DISPLAY).mStacks;
+ }
+
ActivityRecord getHomeActivity() {
return getHomeActivityForUser(mCurrentUser);
}
@@ -2919,14 +2925,19 @@
void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges,
boolean preserveWindows) {
- // First the front stacks. In case any are not fullscreen and are in front of home.
- for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
- final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
- final int topStackNdx = stacks.size() - 1;
- for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
- final ActivityStack stack = stacks.get(stackNdx);
- stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows);
+ mKeyguardController.beginActivityVisibilityUpdate();
+ try {
+ // First the front stacks. In case any are not fullscreen and are in front of home.
+ for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
+ final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
+ final int topStackNdx = stacks.size() - 1;
+ for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+ stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows);
+ }
}
+ } finally {
+ mKeyguardController.endActivityVisibilityUpdate();
}
}
@@ -3157,15 +3168,16 @@
pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
pw.print(prefix); pw.println("mActivityContainers=" + mActivityContainers);
pw.print(prefix); pw.print("mLockTaskModeState=" + lockTaskModeToString());
- final SparseArray<String[]> packages = mService.mLockTaskPackages;
- if (packages.size() > 0) {
- pw.println(" mLockTaskPackages (userId:packages)=");
- for (int i = 0; i < packages.size(); ++i) {
- pw.print(prefix); pw.print(prefix); pw.print(packages.keyAt(i));
- pw.print(":"); pw.println(Arrays.toString(packages.valueAt(i)));
- }
- }
- pw.println(" mLockTaskModeTasks" + mLockTaskModeTasks);
+ final SparseArray<String[]> packages = mService.mLockTaskPackages;
+ if (packages.size() > 0) {
+ pw.print(prefix); pw.println("mLockTaskPackages (userId:packages)=");
+ for (int i = 0; i < packages.size(); ++i) {
+ pw.print(prefix); pw.print(prefix); pw.print(packages.keyAt(i));
+ pw.print(":"); pw.println(Arrays.toString(packages.valueAt(i)));
+ }
+ }
+ pw.println(" mLockTaskModeTasks" + mLockTaskModeTasks);
+ mKeyguardController.dump(pw, prefix);
}
/**
@@ -3470,10 +3482,10 @@
}
private StackInfo getStackInfoLocked(ActivityStack stack) {
- final ActivityDisplay display = mActivityDisplays.get(Display.DEFAULT_DISPLAY);
+ final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY);
StackInfo info = new StackInfo();
mWindowManager.getStackBounds(stack.mStackId, info.bounds);
- info.displayId = Display.DEFAULT_DISPLAY;
+ info.displayId = DEFAULT_DISPLAY;
info.stackId = stack.mStackId;
info.userId = stack.mCurrentUser;
info.visible = stack.getStackVisibilityLocked(null) == STACK_VISIBLE;
@@ -4390,7 +4402,7 @@
ActivityStack findStackBehind(ActivityStack stack) {
// TODO(multi-display): We are only looking for stacks on the default display.
- final ActivityDisplay display = mActivityDisplays.get(Display.DEFAULT_DISPLAY);
+ final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY);
if (display == null) {
return null;
}
@@ -4505,7 +4517,7 @@
public List<IBinder> getTopVisibleActivities() {
// TODO(multi-display): Get rid of DEFAULT_DISPLAY here. Used in
// VoiceInteractionManagerServiceImpl#showSessionLocked.
- final ActivityDisplay display = mActivityDisplays.get(Display.DEFAULT_DISPLAY);
+ final ActivityDisplay display = mActivityDisplays.get(DEFAULT_DISPLAY);
if (display == null) {
return Collections.EMPTY_LIST;
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 006c13d..db73048 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -577,10 +577,6 @@
ActivityStack targetStack) {
if (result < START_SUCCESS) {
- // If someone asked to have the keyguard dismissed on the next activity start,
- // but we are not actually doing an activity switch... just dismiss the keyguard now,
- // because we probably want to see whatever is behind it.
- mSupervisor.notifyActivityDrawnForKeyguard();
return;
}
@@ -1661,11 +1657,6 @@
private void resumeTargetStackIfNeeded() {
if (mDoResume) {
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, null, mOptions);
- if (!mMovedToFront) {
- // Make sure to notify Keyguard as well if we are not running an app transition
- // later.
- mSupervisor.notifyActivityDrawnForKeyguard();
- }
} else {
ActivityOptions.abort(mOptions);
}
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
new file mode 100644
index 0000000..98acc9c
--- /dev/null
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.am;
+
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
+import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
+import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
+import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
+import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
+import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_GOING_AWAY;
+import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_OCCLUDE;
+import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
+
+import com.android.server.wm.WindowManagerService;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+
+/**
+ * Controls Keyguard occluding, dismissing and transitions depending on what kind of activities are
+ * currently visible.
+ * <p>
+ * Note that everything in this class should only be accessed with the AM lock being held.
+ */
+class KeyguardController {
+
+ private final ActivityManagerService mService;
+ private final ActivityStackSupervisor mStackSupervisor;
+ private WindowManagerService mWindowManager;
+ private boolean mKeyguardShowing;
+ private boolean mKeyguardGoingAway;
+ private boolean mOccluded;
+ private ActivityRecord mDismissingKeyguardActivity;
+ private int mBeforeUnoccludeTransit;
+ private int mVisibilityTransactionDepth;
+
+ KeyguardController(ActivityManagerService service,
+ ActivityStackSupervisor stackSupervisor) {
+ mService = service;
+ mStackSupervisor = stackSupervisor;
+ }
+
+ void setWindowManager(WindowManagerService windowManager) {
+ mWindowManager = windowManager;
+ }
+
+ /**
+ * @return true if Keyguard is showing, not going away, and not being occluded, false otherwise
+ */
+ boolean isKeyguardShowing() {
+ return mKeyguardShowing && !mKeyguardGoingAway && !mOccluded;
+ }
+
+ /**
+ * @return true if Keyguard is either showing or occluded, but not going away
+ */
+ boolean isKeyguardLocked() {
+ return mKeyguardShowing && !mKeyguardGoingAway;
+ }
+
+ /**
+ * Update the Keyguard showing state.
+ */
+ void setKeyguardShown(boolean showing) {
+ if (showing == mKeyguardShowing) {
+ return;
+ }
+ mKeyguardShowing = showing;
+ if (showing) {
+ mKeyguardGoingAway = false;
+
+ // Allow an activity to redismiss Keyguard.
+ mDismissingKeyguardActivity = null;
+ }
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mService.updateSleepIfNeededLocked();
+ }
+
+ /**
+ * Called when Keyguard is going away.
+ *
+ * @param flags See {@link android.view.WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
+ * etc.
+ */
+ void keyguardGoingAway(int flags) {
+ if (mKeyguardShowing) {
+ mWindowManager.deferSurfaceLayout();
+ try {
+ mKeyguardGoingAway = true;
+ mWindowManager.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
+ false /* alwaysKeepCurrent */, convertTransitFlags(flags),
+ false /* forceOverride */);
+ mWindowManager.keyguardGoingAway(flags);
+ mService.updateSleepIfNeededLocked();
+
+ // Some stack visibility might change (e.g. docked stack)
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mWindowManager.executeAppTransition();
+ mService.applyVrModeIfNeededLocked(mStackSupervisor.getResumedActivityLocked(),
+ true /* enable */);
+ } finally {
+ mWindowManager.continueSurfaceLayout();
+ }
+ }
+ }
+
+ private int convertTransitFlags(int keyguardGoingAwayFlags) {
+ int result = 0;
+ if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0) {
+ result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
+ }
+ if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0) {
+ result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
+ }
+ if ((keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0) {
+ result |= TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
+ }
+ return result;
+ }
+
+ /**
+ * Starts a batch of visibility updates.
+ */
+ void beginActivityVisibilityUpdate() {
+ mVisibilityTransactionDepth++;
+ }
+
+ /**
+ * Ends a batch of visibility updates. After all batches are done, this method makes sure to
+ * update lockscreen occluded/dismiss state if needed.
+ */
+ void endActivityVisibilityUpdate() {
+ mVisibilityTransactionDepth--;
+ if (mVisibilityTransactionDepth == 0) {
+ visibilitiesUpdated();
+ }
+ }
+
+ private void visibilitiesUpdated() {
+ final boolean lastOccluded = mOccluded;
+ final ActivityRecord lastDismissingKeyguardActivity = mDismissingKeyguardActivity;
+ mOccluded = false;
+ mDismissingKeyguardActivity = null;
+ final ArrayList<ActivityStack> stacks = mStackSupervisor.getStacksOnDefaultDisplay();
+ final int topStackNdx = stacks.size() - 1;
+ for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
+ final ActivityStack stack = stacks.get(stackNdx);
+
+ // Only the very top activity may control occluded state
+ if (stackNdx == topStackNdx) {
+ mOccluded = stack.topActivityOccludesKeyguard();
+ }
+ if (mDismissingKeyguardActivity == null
+ && stack.getTopDismissingKeyguardActivity() != null) {
+ mDismissingKeyguardActivity = stack.getTopDismissingKeyguardActivity();
+ }
+ }
+ mOccluded |= mWindowManager.isShowingDream();
+ if (mOccluded != lastOccluded) {
+ handleOccludedChanged();
+ }
+ if (mDismissingKeyguardActivity != lastDismissingKeyguardActivity) {
+ handleDismissKeyguard();
+ }
+ }
+
+ /**
+ * Called when occluded state changed.
+ */
+ private void handleOccludedChanged() {
+ mWindowManager.onKeyguardOccludedChanged(mOccluded);
+ if (isKeyguardLocked()) {
+ mWindowManager.deferSurfaceLayout();
+ try {
+ mWindowManager.prepareAppTransition(resolveOccludeTransit(),
+ false /* alwaysKeepCurrent */, 0 /* flags */, true /* forceOverride */);
+ mService.updateSleepIfNeededLocked();
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mWindowManager.executeAppTransition();
+ } finally {
+ mWindowManager.continueSurfaceLayout();
+ }
+ }
+ dismissDockedStackIfNeeded();
+ }
+
+ /**
+ * Called when somebody might want to dismiss the Keyguard.
+ */
+ private void handleDismissKeyguard() {
+ if (mDismissingKeyguardActivity != null) {
+ mWindowManager.dismissKeyguard();
+
+ // If we are about to unocclude the Keyguard, but we can dismiss it without security,
+ // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
+ if (mKeyguardShowing && canDismissKeyguard()
+ && mWindowManager.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE) {
+ mWindowManager.prepareAppTransition(mBeforeUnoccludeTransit,
+ false /* alwaysKeepCurrent */, 0 /* flags */, true /* forceOverride */);
+ mKeyguardGoingAway = true;
+ mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+ mWindowManager.executeAppTransition();
+ }
+ }
+ }
+
+ /**
+ * @return true if Keyguard can be currently dismissed without entering credentials.
+ */
+ private boolean canDismissKeyguard() {
+ return mWindowManager.isKeyguardTrusted() || !mWindowManager.isKeyguardSecure();
+ }
+
+ private int resolveOccludeTransit() {
+ if (mBeforeUnoccludeTransit != TRANSIT_UNSET
+ && mWindowManager.getPendingAppTransition() == TRANSIT_KEYGUARD_UNOCCLUDE
+ && mOccluded) {
+
+ // Reuse old transit in case we are occluding Keyguard again, meaning that we never
+ // actually occclude/unocclude Keyguard, but just run a normal transition.
+ return mBeforeUnoccludeTransit;
+ } else if (!mOccluded) {
+
+ // Save transit in case we dismiss/occlude Keyguard shortly after.
+ mBeforeUnoccludeTransit = mWindowManager.getPendingAppTransition();
+ return TRANSIT_KEYGUARD_UNOCCLUDE;
+ } else {
+ return TRANSIT_KEYGUARD_OCCLUDE;
+ }
+ }
+
+ private void dismissDockedStackIfNeeded() {
+ if (mKeyguardShowing && mOccluded) {
+ // The lock screen is currently showing, but is occluded by a window that can
+ // show on top of the lock screen. In this can we want to dismiss the docked
+ // stack since it will be complicated/risky to try to put the activity on top
+ // of the lock screen in the right fullscreen configuration.
+ mStackSupervisor.moveTasksToFullscreenStackLocked(DOCKED_STACK_ID,
+ mStackSupervisor.mFocusedStack.getStackId() == DOCKED_STACK_ID);
+ }
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ pw.println(prefix + "KeyguardController:");
+ pw.println(prefix + " mKeyguardShowing=" + mKeyguardShowing);
+ pw.println(prefix + " mKeyguardGoingAway=" + mKeyguardGoingAway);
+ pw.println(prefix + " mOccluded=" + mOccluded);
+ pw.println(prefix + " mDismissingKeyguardActivity=" + mDismissingKeyguardActivity);
+ pw.println(prefix + " mVisibilityTransactionDepth=" + mVisibilityTransactionDepth);
+ }
+}
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index b37b3f0..86e3ccc 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -56,8 +56,6 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
import java.util.Objects;
import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
@@ -89,7 +87,6 @@
import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.am.ActivityManagerService.LOCK_SCREEN_SHOWN;
import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
@@ -1700,7 +1697,7 @@
/** Returns the bounds that should be used to launch this task. */
Rect getLaunchBounds() {
// If we're over lockscreen, forget about stack bounds and use fullscreen.
- if (mService.mLockScreenShown == LOCK_SCREEN_SHOWN) {
+ if (mService.mStackSupervisor.mKeyguardController.isKeyguardShowing()) {
return null;
}
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index cda063d..49c4140 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -46,7 +46,9 @@
import android.os.UserManager;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
+import com.android.server.FgThread;
import com.android.server.SystemService;
import org.json.JSONArray;
@@ -111,6 +113,7 @@
private Context mContext;
private long mHalDeviceId;
private int mFailedAttempts;
+ @GuardedBy("this")
private IFingerprintDaemon mDaemon;
private final PowerManager mPowerManager;
private final AlarmManager mAlarmManager;
@@ -195,35 +198,41 @@
public void binderDied() {
Slog.v(TAG, "fingerprintd died");
MetricsLogger.count(mContext, "fingerprintd_died", 1);
- mDaemon = null;
+ synchronized (this) {
+ mDaemon = null;
+ }
mCurrentUserId = UserHandle.USER_CURRENT;
handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
}
public IFingerprintDaemon getFingerprintDaemon() {
- if (mDaemon == null) {
- mDaemon = IFingerprintDaemon.Stub.asInterface(ServiceManager.getService(FINGERPRINTD));
- if (mDaemon != null) {
- try {
- mDaemon.asBinder().linkToDeath(this, 0);
- mDaemon.init(mDaemonCallback);
- mHalDeviceId = mDaemon.openHal();
- if (mHalDeviceId != 0) {
- updateActiveGroup(ActivityManager.getCurrentUser(), null);
- } else {
- Slog.w(TAG, "Failed to open Fingerprint HAL!");
- MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
- mDaemon = null;
+ synchronized (this) {
+ if (mDaemon == null) {
+ mDaemon = IFingerprintDaemon.Stub
+ .asInterface(ServiceManager.getService(FINGERPRINTD));
+ if (mDaemon != null) {
+ try {
+ mDaemon.asBinder().linkToDeath(this, 0);
+ mDaemon.init(mDaemonCallback);
+ mHalDeviceId = mDaemon.openHal();
+ if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
+ if (mHalDeviceId != 0) {
+ updateActiveGroup(ActivityManager.getCurrentUser(), null);
+ } else {
+ Slog.w(TAG, "Failed to open Fingerprint HAL!");
+ MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
+ mDaemon = null;
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to open fingeprintd HAL", e);
+ mDaemon = null; // try again later!
}
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to open fingeprintd HAL", e);
- mDaemon = null; // try again later!
+ } else {
+ Slog.w(TAG, "fingerprint service not available");
}
- } else {
- Slog.w(TAG, "fingerprint service not available");
}
+ return mDaemon;
}
- return mDaemon;
}
protected void handleEnumerate(long deviceId, int[] fingerIds, int[] groupIds) {
@@ -1005,8 +1014,7 @@
@Override
public void onStart() {
publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
- IFingerprintDaemon daemon = getFingerprintDaemon();
- if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
+ FgThread.getHandler().post(() -> getFingerprintDaemon());
listenForUserSwitches();
}
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index bcdeb66..31ed350 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -17,6 +17,7 @@
package com.android.server.notification;
import android.app.Notification;
+import android.app.NotificationManager;
import android.content.Context;
import android.service.notification.NotificationListenerService;
import android.util.Log;
@@ -44,7 +45,7 @@
return null;
}
- if (record.getImportance() >= NotificationListenerService.Ranking.IMPORTANCE_DEFAULT) {
+ if (record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT) {
final Notification notification = record.getNotification();
if ((notification.defaults & Notification.DEFAULT_VIBRATE) != 0 ||
notification.vibrate != null ||
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 4e50567..d782211 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -16,6 +16,8 @@
package com.android.server.notification;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.service.notification.NotificationRankerService.REASON_APP_CANCEL;
import static android.service.notification.NotificationRankerService.REASON_APP_CANCEL_ALL;
import static android.service.notification.NotificationRankerService.REASON_CHANNEL_BANNED;
@@ -40,8 +42,6 @@
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.service.notification.NotificationListenerService.TRIM_FULL;
import static android.service.notification.NotificationListenerService.TRIM_LIGHT;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_NONE;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
@@ -975,6 +975,7 @@
mUsageStats = new NotificationUsageStats(getContext());
mRankingHandler = new RankingHandlerWorker(mRankingThread.getLooper());
mRankingHelper = new RankingHelper(getContext(),
+ getContext().getPackageManager(),
mRankingHandler,
mUsageStats,
extractorNames);
@@ -1538,8 +1539,7 @@
@Override
public void setImportance(String pkg, int uid, int importance) {
enforceSystemOrSystemUI("Caller not system or systemui");
- setNotificationsEnabledForPackageImpl(pkg, uid,
- importance != NotificationListenerService.Ranking.IMPORTANCE_NONE);
+ setNotificationsEnabledForPackageImpl(pkg, uid, importance != IMPORTANCE_NONE);
mRankingHelper.setImportance(pkg, uid, importance);
savePolicyFile();
}
@@ -1567,21 +1567,6 @@
}
@Override
- public void updateNotificationChannel(String pkg, NotificationChannel channel) {
- Preconditions.checkNotNull(channel);
- Preconditions.checkNotNull(channel.getId());
- checkCallerIsSystemOrSameApp(pkg);
- if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
- // cancel
- cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true,
- UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null);
- }
- mRankingHelper.updateNotificationChannel(Binder.getCallingUid(), pkg,
- Binder.getCallingUid(), channel);
- savePolicyFile();
- }
-
- @Override
public NotificationChannel getNotificationChannel(String pkg, String channelId) {
Preconditions.checkNotNull(channelId);
checkCallerIsSystemOrSameApp(pkg);
@@ -1620,7 +1605,7 @@
cancelAllNotificationsInt(MY_UID, MY_PID, pkg, channel.getId(), 0, 0, true,
UserHandle.getUserId(Binder.getCallingUid()), REASON_CHANNEL_BANNED, null);
}
- mRankingHelper.updateNotificationChannel(Binder.getCallingUid(), pkg, uid, channel);
+ mRankingHelper.updateNotificationChannel(pkg, uid, channel);
savePolicyFile();
}
@@ -2814,7 +2799,7 @@
// setup local book-keeping
final NotificationRecord r = new NotificationRecord(getContext(), n,
- mRankingHelper.getNotificationChannel(pkg, callingUid,
+ mRankingHelper.getNotificationChannelWithFallback(pkg, callingUid,
n.getNotification().getNotificationChannel()));
mHandler.post(new EnqueueNotificationRunnable(userId, r));
@@ -3022,7 +3007,8 @@
final String key = record.getKey();
// Should this notification make noise, vibe, or use the LED?
- final boolean aboveThreshold = record.getImportance() >= IMPORTANCE_DEFAULT;
+ final boolean aboveThreshold =
+ record.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT;
final boolean canInterrupt = aboveThreshold && !record.isIntercepted();
if (DBG || record.isIntercepted())
Slog.v(TAG,
@@ -3076,8 +3062,8 @@
} else if (notification.sound != null) {
soundUri = notification.sound;
hasValidSound = (soundUri != null);
- } else if (record.getChannel().getDefaultRingtone() != null) {
- soundUri = record.getChannel().getDefaultRingtone();
+ } else if (record.getChannel().getRingtone() != null) {
+ soundUri = record.getChannel().getRingtone();
hasValidSound = (soundUri != null);
}
@@ -3094,9 +3080,7 @@
// The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback.
final boolean useDefaultVibrate =
(notification.defaults & Notification.DEFAULT_VIBRATE) != 0;
-
final boolean hasChannelVibration = record.getChannel().shouldVibrate();
-
hasValidVibrate = useDefaultVibrate || convertSoundToVibration ||
hasCustomVibrate || hasChannelVibration;
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index c5de93e..a1256db 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -15,12 +15,11 @@
*/
package com.android.server.notification;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MIN;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_DEFAULT;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_LOW;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_MAX;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -30,7 +29,6 @@
import android.graphics.Bitmap;
import android.graphics.drawable.Icon;
import android.media.AudioAttributes;
-import android.net.Uri;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
@@ -140,10 +138,8 @@
importance = IMPORTANCE_DEFAULT;
break;
case Notification.PRIORITY_HIGH:
- importance = IMPORTANCE_HIGH;
- break;
case Notification.PRIORITY_MAX:
- importance = IMPORTANCE_MAX;
+ importance = IMPORTANCE_HIGH;
break;
}
stats.requestedImportance = importance;
@@ -153,7 +149,7 @@
|| n.sound != null
|| n.vibrate != null
|| mNotificationChannel.shouldVibrate()
- || mNotificationChannel.getDefaultRingtone() != null;
+ || mNotificationChannel.getRingtone() != null;
stats.isNoisy = isNoisy;
if (!isNoisy && importance > IMPORTANCE_LOW) {
@@ -167,7 +163,7 @@
}
if (n.fullScreenIntent != null) {
- importance = IMPORTANCE_MAX;
+ importance = IMPORTANCE_HIGH;
}
stats.naturalImportance = importance;
@@ -319,10 +315,11 @@
@Override
public final String toString() {
return String.format(
- "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s importance=%d key=%s: %s)",
+ "NotificationRecord(0x%08x: pkg=%s user=%s id=%d tag=%s importance=%d key=%s" +
+ " channel=%s: %s)",
System.identityHashCode(this),
this.sbn.getPackageName(), this.sbn.getUser(), this.sbn.getId(),
- this.sbn.getTag(), this.mImportance, this.sbn.getKey(),
+ this.sbn.getTag(), this.mImportance, this.sbn.getKey(), this.getChannel().getId(),
this.sbn.getNotification());
}
@@ -384,7 +381,7 @@
}
private void applyUserImportance() {
- if (mUserImportance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
+ if (mUserImportance != IMPORTANCE_UNSPECIFIED) {
mImportance = mUserImportance;
mImportanceExplanation = getUserExplanation();
}
@@ -395,7 +392,7 @@
}
public void setImportance(int importance, CharSequence explanation) {
- if (importance != NotificationListenerService.Ranking.IMPORTANCE_UNSPECIFIED) {
+ if (importance != IMPORTANCE_UNSPECIFIED) {
mImportance = importance;
mImportanceExplanation = explanation;
}
diff --git a/services/core/java/com/android/server/notification/NotificationUsageStats.java b/services/core/java/com/android/server/notification/NotificationUsageStats.java
index 34c5283..e8cf6a1 100644
--- a/services/core/java/com/android/server/notification/NotificationUsageStats.java
+++ b/services/core/java/com/android/server/notification/NotificationUsageStats.java
@@ -16,7 +16,7 @@
package com.android.server.notification;
-import static android.service.notification.NotificationListenerService.Ranking.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
import android.app.Notification;
import android.content.ContentValues;
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 2df4043..cb5fb0d 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -33,8 +33,10 @@
int getImportance(String packageName, int uid);
void createNotificationChannel(String pkg, int uid, NotificationChannel channel);
- void updateNotificationChannel(int callingUid, String pkg, int uid, NotificationChannel channel);
+ void updateNotificationChannel(String pkg, int uid, NotificationChannel channel);
+ void updateNotificationChannelFromRanker(String pkg, int uid, NotificationChannel channel);
NotificationChannel getNotificationChannel(String pkg, int uid, String channelId);
+ NotificationChannel getNotificationChannelWithFallback(String pkg, int uid, String channelId);
void deleteNotificationChannel(String pkg, int uid, String channelId);
ParceledListSlice<NotificationChannel> getNotificationChannels(String pkg, int uid);
}
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index d59115e..d11d4de 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -15,12 +15,17 @@
*/
package com.android.server.notification;
+import com.android.internal.R;
+
import android.app.Notification;
import android.app.NotificationChannel;
+import android.app.NotificationManager;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice;
+import android.os.Build;
import android.os.Process;
import android.os.UserHandle;
import android.service.notification.NotificationListenerService.Ranking;
@@ -28,8 +33,6 @@
import android.util.ArrayMap;
import android.util.Slog;
-import com.android.internal.R;
-
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -63,8 +66,8 @@
private static final String ATT_IMPORTANCE = "importance";
private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT;
- private static final int DEFAULT_VISIBILITY = Ranking.VISIBILITY_NO_OVERRIDE;
- private static final int DEFAULT_IMPORTANCE = Ranking.IMPORTANCE_UNSPECIFIED;
+ private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
+ private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED;
private final NotificationSignalExtractor[] mSignalExtractors;
private final NotificationComparator mPreliminaryComparator = new NotificationComparator();
@@ -76,11 +79,13 @@
private final Context mContext;
private final RankingHandler mRankingHandler;
+ private final PackageManager mPm;
- public RankingHelper(Context context, RankingHandler rankingHandler,
+ public RankingHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
NotificationUsageStats usageStats, String[] extractorNames) {
mContext = context;
mRankingHandler = rankingHandler;
+ mPm = pm;
final int N = extractorNames.length;
mSignalExtractors = new NotificationSignalExtractor[N];
@@ -131,7 +136,6 @@
public void readXml(XmlPullParser parser, boolean forRestore)
throws XmlPullParserException, IOException {
- final PackageManager pm = mContext.getPackageManager();
int type = parser.getEventType();
if (type != XmlPullParser.START_TAG) return;
String tag = parser.getName();
@@ -147,31 +151,24 @@
if (TAG_PACKAGE.equals(tag)) {
int uid = safeInt(parser, ATT_UID, Record.UNKNOWN_UID);
String name = parser.getAttributeValue(null, ATT_NAME);
+ int importance = safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
if (!TextUtils.isEmpty(name)) {
if (forRestore) {
try {
//TODO: http://b/22388012
- uid = pm.getPackageUidAsUser(name, UserHandle.USER_SYSTEM);
+ uid = mPm.getPackageUidAsUser(name, UserHandle.USER_SYSTEM);
} catch (NameNotFoundException e) {
// noop
}
}
- Record r = null;
- if (uid == Record.UNKNOWN_UID) {
- r = mRestoredWithoutUids.get(name);
- if (r == null) {
- r = new Record();
- r.pkg = name;
- mRestoredWithoutUids.put(name, r);
- }
- } else {
- r = getOrCreateRecord(name, uid);
- }
- r.importance = safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
- r.priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY);
- r.visibility = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY);
+ Record r = getOrCreateRecord(name, uid,
+ safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE),
+ safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY),
+ safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY));
+
+ // Channels
final int innerDepth = parser.getDepth();
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
&& (type != XmlPullParser.END_TAG
@@ -184,15 +181,19 @@
if (TAG_CHANNEL.equals(tagName)) {
String id = parser.getAttributeValue(null, ATT_ID);
CharSequence channelName = parser.getAttributeValue(null, ATT_NAME);
+ int channelImportance =
+ safeInt(parser, ATT_IMPORTANCE, DEFAULT_IMPORTANCE);
if (!TextUtils.isEmpty(id)) {
- final NotificationChannel channel =
- new NotificationChannel(id, channelName);
+ final NotificationChannel channel = new NotificationChannel(id,
+ channelName, channelImportance);
channel.populateFromXml(parser);
r.channels.put(id, channel);
}
}
}
+
+ clampDefaultChannel(r);
}
}
}
@@ -204,23 +205,77 @@
return pkg + "|" + uid;
}
- private Record getOrCreateRecord(String pkg, int uid) {
+ private Record getRecord(String pkg, int uid) {
final String key = recordKey(pkg, uid);
- Record r = mRecords.get(key);
+ return mRecords.get(key);
+ }
+
+ private Record getOrCreateRecord(String pkg, int uid) {
+ return getOrCreateRecord(pkg, uid,
+ DEFAULT_IMPORTANCE, DEFAULT_PRIORITY, DEFAULT_VISIBILITY);
+ }
+
+ private Record getOrCreateRecord(String pkg, int uid, int importance, int priority,
+ int visibility) {
+ final String key = recordKey(pkg, uid);
+ Record r = (uid == Record.UNKNOWN_UID) ? mRestoredWithoutUids.get(pkg) : mRecords.get(key);
if (r == null) {
r = new Record();
r.pkg = pkg;
r.uid = uid;
- NotificationChannel defaultChannel = createDefaultChannel();
- r.channels.put(defaultChannel.getId(), defaultChannel);
- mRecords.put(key, r);
+ r.importance = importance;
+ r.priority = priority;
+ r.visibility = visibility;
+ createDefaultChannelIfMissing(r);
+ if (r.uid == Record.UNKNOWN_UID) {
+ mRestoredWithoutUids.put(pkg, r);
+ } else {
+ mRecords.put(key, r);
+ }
}
+ clampDefaultChannel(r);
return r;
}
- private NotificationChannel createDefaultChannel() {
- return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID,
- mContext.getString(R.string.default_notification_channel_label));
+ // Clamp the importance level of the default channel for apps targeting the new SDK version,
+ // unless the user has already changed the importance.
+ private void clampDefaultChannel(Record r) {
+ try {
+ final ApplicationInfo applicationInfo = mPm.getApplicationInfo(r.pkg, 0);
+ if (applicationInfo.targetSdkVersion > Build.VERSION_CODES.N_MR1) {
+ final NotificationChannel defaultChannel =
+ r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID);
+ if ((defaultChannel.getUserLockedFields()
+ & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0) {
+ defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
+ updateConfig();
+ }
+ }
+ } catch (NameNotFoundException e) {
+ // oh well.
+ }
+ }
+
+ private void createDefaultChannelIfMissing(Record r) {
+ if (!r.channels.containsKey(NotificationChannel.DEFAULT_CHANNEL_ID)) {
+ NotificationChannel channel;
+ channel = new NotificationChannel(
+ NotificationChannel.DEFAULT_CHANNEL_ID,
+ mContext.getString(R.string.default_notification_channel_label),
+ r.importance);
+ channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
+ channel.setLockscreenVisibility(r.visibility);
+ if (r.importance != NotificationManager.IMPORTANCE_UNSPECIFIED) {
+ channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+ }
+ if (r.priority != DEFAULT_PRIORITY) {
+ channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY);
+ }
+ if (r.visibility != DEFAULT_VISIBILITY) {
+ channel.lockFields(NotificationChannel.USER_LOCKED_VISIBILITY);
+ }
+ r.channels.put(channel.getId(), channel);
+ }
}
public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
@@ -397,6 +452,10 @@
mContext.getString(R.string.default_notification_channel_label))) {
throw new IllegalArgumentException("Channel already exists");
}
+ if (channel.getImportance() < NotificationManager.IMPORTANCE_NONE
+ || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
+ throw new IllegalArgumentException("Invalid importance level");
+ }
if (channel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
channel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
}
@@ -405,17 +464,12 @@
}
@Override
- public void updateNotificationChannel(int callingUid, String pkg, int uid,
- NotificationChannel updatedChannel) {
+ public void updateNotificationChannel(String pkg, int uid, NotificationChannel updatedChannel) {
Record r = getOrCreateRecord(pkg, uid);
NotificationChannel channel = r.channels.get(updatedChannel.getId());
if (channel == null) {
throw new IllegalArgumentException("Channel does not exist");
}
- if (!isUidSystem(callingUid)) {
- updatedChannel.setImportance(channel.getImportance());
- updatedChannel.setName(channel.getName());
- }
if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
updatedChannel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
}
@@ -424,6 +478,57 @@
}
@Override
+ public void updateNotificationChannelFromRanker(String pkg, int uid,
+ NotificationChannel updatedChannel) {
+ Record r = getOrCreateRecord(pkg, uid);
+ NotificationChannel channel = r.channels.get(updatedChannel.getId());
+ if (channel == null) {
+ throw new IllegalArgumentException("Channel does not exist");
+ }
+
+ if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_IMPORTANCE) == 0) {
+ channel.setImportance(updatedChannel.getImportance());
+ }
+ if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_LIGHTS) == 0) {
+ channel.setLights(updatedChannel.shouldShowLights());
+ }
+ if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_PRIORITY) == 0) {
+ channel.setBypassDnd(updatedChannel.canBypassDnd());
+ }
+ if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_RINGTONE) == 0) {
+ channel.setRingtone(updatedChannel.getRingtone());
+ }
+ if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_VIBRATION) == 0) {
+ channel.setVibration(updatedChannel.shouldVibrate());
+ }
+ if ((channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_VISIBILITY) == 0) {
+ if (updatedChannel.getLockscreenVisibility() == Notification.VISIBILITY_PUBLIC) {
+ channel.setLockscreenVisibility(Ranking.VISIBILITY_NO_OVERRIDE);
+ } else {
+ channel.setLockscreenVisibility(updatedChannel.getLockscreenVisibility());
+ }
+ }
+
+ r.channels.put(channel.getId(), channel);
+ updateConfig();
+ }
+
+ @Override
+ public NotificationChannel getNotificationChannelWithFallback(String pkg, int uid,
+ String channelId) {
+ Record r = getOrCreateRecord(pkg, uid);
+ if (channelId == null) {
+ channelId = NotificationChannel.DEFAULT_CHANNEL_ID;
+ }
+ NotificationChannel channel = r.channels.get(channelId);
+ if (channel != null) {
+ return channel;
+ } else {
+ return r.channels.get(NotificationChannel.DEFAULT_CHANNEL_ID);
+ }
+ }
+
+ @Override
public NotificationChannel getNotificationChannel(String pkg, int uid, String channelId) {
Record r = getOrCreateRecord(pkg, uid);
if (channelId == null) {
@@ -434,8 +539,10 @@
@Override
public void deleteNotificationChannel(String pkg, int uid, String channelId) {
- Record r = getOrCreateRecord(pkg, uid);
- r.channels.remove(channelId);
+ Record r = getRecord(pkg, uid);
+ if (r != null) {
+ r.channels.remove(channelId);
+ }
}
@Override
@@ -446,7 +553,7 @@
for (int i = 0; i < N; i++) {
channels.add(r.channels.valueAt(i));
}
- return new ParceledListSlice<NotificationChannel>(channels);
+ return new ParceledListSlice<>(channels);
}
/**
@@ -459,11 +566,12 @@
}
public void setEnabled(String packageName, int uid, boolean enabled) {
- boolean wasEnabled = getImportance(packageName, uid) != Ranking.IMPORTANCE_NONE;
+ boolean wasEnabled = getImportance(packageName, uid) != NotificationManager.IMPORTANCE_NONE;
if (wasEnabled == enabled) {
return;
}
- setImportance(packageName, uid, enabled ? DEFAULT_IMPORTANCE : Ranking.IMPORTANCE_NONE);
+ setImportance(packageName, uid,
+ enabled ? DEFAULT_IMPORTANCE : NotificationManager.IMPORTANCE_NONE);
}
public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) {
@@ -599,7 +707,7 @@
ArrayMap<Integer, String> packageBans = new ArrayMap<>(N);
for (int i = 0; i < N; i++) {
final Record r = mRecords.valueAt(i);
- if (r.importance == Ranking.IMPORTANCE_NONE) {
+ if (r.importance == NotificationManager.IMPORTANCE_NONE) {
packageBans.put(r.uid, r.pkg);
}
}
@@ -611,14 +719,13 @@
|| mRestoredWithoutUids.isEmpty()) {
return; // nothing to do
}
- final PackageManager pm = mContext.getPackageManager();
boolean updated = false;
for (String pkg : pkgList) {
final Record r = mRestoredWithoutUids.get(pkg);
if (r != null) {
try {
//TODO: http://b/22388012
- r.uid = pm.getPackageUidAsUser(r.pkg, UserHandle.USER_SYSTEM);
+ r.uid = mPm.getPackageUidAsUser(r.pkg, UserHandle.USER_SYSTEM);
mRestoredWithoutUids.remove(pkg);
mRecords.put(recordKey(r.pkg, r.uid), r);
updated = true;
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index d558b07..38d69ed 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -635,7 +635,11 @@
return false; // Shouldn't happen.
}
- if (!isNewApp && !forceRescan) {
+ // Always scan the settings app, since its version code is the same for DR and MR1.
+ // TODO Fix it properly: b/32554059
+ final boolean isSettings = "com.android.settings".equals(getPackageName());
+
+ if (!isNewApp && !forceRescan && !isSettings) {
// Return if the package hasn't changed, ie:
// - version code hasn't change
// - lastUpdateTime hasn't change
@@ -652,6 +656,11 @@
return false;
}
}
+ if (isSettings) {
+ if (ShortcutService.DEBUG) {
+ Slog.d(TAG, "Always scan settings.");
+ }
+ }
} finally {
s.logDurationStat(Stats.PACKAGE_UPDATE_CHECK, start);
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 19bf751..3b5abe8 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -239,10 +239,19 @@
private static List<ResolveInfo> EMPTY_RESOLVE_INFO = new ArrayList<>(0);
- private static Predicate<ResolveInfo> ACTIVITY_NOT_EXPORTED =
- ri -> !ri.activityInfo.exported;
+ // Temporarily reverted to anonymous inner class form due to: b/32554459
+ private static Predicate<ResolveInfo> ACTIVITY_NOT_EXPORTED = new Predicate<ResolveInfo>() {
+ public boolean test(ResolveInfo ri) {
+ return !ri.activityInfo.exported;
+ }
+ };
- private static Predicate<PackageInfo> PACKAGE_NOT_INSTALLED = pi -> !isInstalled(pi);
+ // Temporarily reverted to anonymous inner class form due to: b/32554459
+ private static Predicate<PackageInfo> PACKAGE_NOT_INSTALLED = new Predicate<PackageInfo>() {
+ public boolean test(PackageInfo pi) {
+ return !isInstalled(pi);
+ }
+ };
private final Handler mHandler;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 40dfcda..41fd16b 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -25,13 +25,82 @@
import static android.content.res.Configuration.EMPTY;
import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
-import static android.view.WindowManager.DOCKED_TOP;
import static android.view.WindowManager.DOCKED_LEFT;
import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.DOCKED_TOP;
import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW;
+import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+import static android.view.WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
+import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
+import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.LAST_SYSTEM_WINDOW;
+import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
+import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
+import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
+import static android.view.WindowManager.LayoutParams.TYPE_DRAG;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_CONSUMER;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
+import static android.view.WindowManager.LayoutParams.TYPE_POINTER;
+import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
+import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
+import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
+import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
+import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
+import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
import static android.view.WindowManager.TAKE_SCREENSHOT_SELECTED_REGION;
-import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
@@ -39,6 +108,7 @@
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.StackId;
import android.app.ActivityManagerInternal;
@@ -112,10 +182,10 @@
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
+import android.util.LongSparseArray;
import android.util.MutableBoolean;
import android.util.Slog;
import android.util.SparseArray;
-import android.util.LongSparseArray;
import android.view.Display;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
@@ -133,19 +203,21 @@
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerInternal;
+import android.view.WindowManagerInternal.AppTransitionListener;
import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
+
import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.policy.PhoneWindow;
import com.android.internal.policy.IShortcutService;
+import com.android.internal.policy.PhoneWindow;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ScreenShapeHelper;
import com.android.internal.widget.PointerLocationView;
@@ -154,12 +226,12 @@
import com.android.server.policy.keyguard.KeyguardServiceDelegate;
import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener;
import com.android.server.statusbar.StatusBarManagerInternal;
+import com.android.server.wm.AppTransition;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
-import java.util.HashSet;
import java.util.List;
/**
@@ -280,8 +352,6 @@
/**
* Keyguard stuff
*/
- private WindowState mKeyguardScrim;
- private boolean mKeyguardHidden;
private boolean mKeyguardDrawnOnce;
/* Table of Application Launch keys. Maps from key codes to intent categories.
@@ -582,54 +652,23 @@
WindowState mTopFullscreenOpaqueOrDimmingWindowState;
WindowState mTopDockedOpaqueWindowState;
WindowState mTopDockedOpaqueOrDimmingWindowState;
- HashSet<IApplicationToken> mAppsToBeHidden = new HashSet<IApplicationToken>();
- HashSet<IApplicationToken> mAppsThatDismissKeyguard = new HashSet<IApplicationToken>();
boolean mTopIsFullscreen;
boolean mForceStatusBar;
boolean mForceStatusBarFromKeyguard;
private boolean mForceStatusBarTransparent;
int mNavBarOpacityMode = NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED;
- boolean mHideLockScreen;
boolean mForcingShowNavBar;
int mForcingShowNavBarLayer;
- // States of keyguard dismiss.
- private static final int DISMISS_KEYGUARD_NONE = 0; // Keyguard not being dismissed.
- private static final int DISMISS_KEYGUARD_START = 1; // Keyguard needs to be dismissed.
- private static final int DISMISS_KEYGUARD_CONTINUE = 2; // Keyguard has been dismissed.
- int mDismissKeyguard = DISMISS_KEYGUARD_NONE;
+ private boolean mPendingKeyguardOccluded;
+ private boolean mKeyguardOccludedChanged;
- /**
- * Indicates that we asked the Keyguard to be dismissed and we just wait for the Keyguard to
- * dismiss itself.
- */
- @GuardedBy("Lw")
- private boolean mCurrentlyDismissingKeyguard;
-
- /** The window that is currently dismissing the keyguard. Dismissing the keyguard must only
- * be done once per window. */
- private WindowState mWinDismissingKeyguard;
-
- /** When window is currently dismissing the keyguard, dismissing the keyguard must handle
- * the keygaurd secure state change instantly case, e.g. the use case of inserting a PIN
- * lock SIM card. This variable is used to record the previous keyguard secure state for
- * monitoring secure state change on window dismissing keyguard. */
- private boolean mSecureDismissingKeyguard;
-
- /** The window that is currently showing "over" the keyguard. If there is an app window
- * belonging to another app on top of this the keyguard shows. If there is a fullscreen
- * app window under this, still dismiss the keyguard but don't show the app underneath. Show
- * the wallpaper. */
- private WindowState mWinShowWhenLocked;
-
- boolean mShowingLockscreen;
boolean mShowingDream;
+ private boolean mLastShowingDream;
boolean mDreamingLockscreen;
boolean mDreamingSleepTokenNeeded;
SleepToken mDreamingSleepToken;
SleepToken mScreenOffSleepToken;
- boolean mKeyguardSecure;
- boolean mKeyguardSecureIncludingHidden;
volatile boolean mKeyguardOccluded;
boolean mHomePressed;
boolean mHomeConsumed;
@@ -1911,6 +1950,19 @@
mWindowManagerInternal.registerAppTransitionListener(
mStatusBarController.getAppTransitionListener());
+ mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() {
+ @Override
+ public int onAppTransitionStartingLocked(int transit, IBinder openToken,
+ IBinder closeToken,
+ Animation openAnimation, Animation closeAnimation) {
+ return handleStartTransitionForKeyguardLw(transit, openAnimation);
+ }
+
+ @Override
+ public void onAppTransitionCancelledLocked(int transit) {
+ handleStartTransitionForKeyguardLw(transit, null /* transit */);
+ }
+ });
}
/**
@@ -2316,7 +2368,6 @@
case TYPE_BOOT_PROGRESS:
case TYPE_DISPLAY_OVERLAY:
case TYPE_INPUT_CONSUMER:
- case TYPE_KEYGUARD_SCRIM:
case TYPE_KEYGUARD_DIALOG:
case TYPE_MAGNIFICATION_OVERLAY:
case TYPE_NAVIGATION_BAR:
@@ -2357,7 +2408,7 @@
// remove the wallpaper and keyguard flag so that any change in-flight after setting
// the keyguard as occluded wouldn't set these flags again.
// See {@link #processKeyguardSetHiddenResultLw}.
- if (mKeyguardHidden) {
+ if (mKeyguardOccluded) {
attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
}
@@ -2533,9 +2584,6 @@
case TYPE_INPUT_METHOD_DIALOG:
// on-screen keyboards and other such input method user interfaces go here.
return 13;
- case TYPE_KEYGUARD_SCRIM:
- // the safety window that shows behind keyguard while keyguard is starting
- return 14;
case TYPE_STATUS_BAR_SUB_PANEL:
return 15;
case TYPE_STATUS_BAR:
@@ -2673,26 +2721,17 @@
}
@Override
- public boolean isForceHiding(WindowManager.LayoutParams attrs) {
- return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
- (isKeyguardHostWindow(attrs) &&
- (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) ||
- (attrs.type == TYPE_KEYGUARD_SCRIM);
- }
-
- @Override
public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
return attrs.type == TYPE_STATUS_BAR;
}
@Override
- public boolean canBeForceHidden(WindowState win, WindowManager.LayoutParams attrs) {
- switch (attrs.type) {
+ public boolean canBeHiddenByKeyguardLw(WindowState win) {
+ switch (win.getAttrs().type) {
case TYPE_STATUS_BAR:
case TYPE_NAVIGATION_BAR:
case TYPE_WALLPAPER:
case TYPE_DREAM:
- case TYPE_KEYGUARD_SCRIM:
return false;
default:
// Hide only windows below the keyguard host window.
@@ -2701,9 +2740,34 @@
}
}
- @Override
- public WindowState getWinShowWhenLockedLw() {
- return mWinShowWhenLocked;
+ private boolean shouldBeHiddenByKeyguard(WindowState win, WindowState imeTarget) {
+
+ // Keyguard visibility of window from activities are determined over activity visibility.
+ if (win.getAppToken() != null) {
+ return false;
+ }
+
+ final LayoutParams attrs = win.getAttrs();
+ final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleLw() &&
+ ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
+ || !canBeHiddenByKeyguardLw(imeTarget));
+
+ // Show IME over the keyguard if the target allows it
+ boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
+ && showImeOverKeyguard;;
+
+ if (isKeyguardLocked() && isKeyguardOccluded()) {
+ // Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
+ allowWhenLocked |= (attrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
+ // Show error dialogs over apps that are shown on lockscreen
+ || (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
+ }
+
+ boolean keyguardLocked = isKeyguardLocked();
+ boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
+ && !mWindowManagerInternal.isStackVisible(DOCKED_STACK_ID);
+ return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == Display.DEFAULT_DISPLAY)
+ || hideDockDivider;
}
/** {@inheritDoc} */
@@ -2771,7 +2835,7 @@
// Assumes it's safe to show starting windows of launched apps while
// the keyguard is being hidden. This is okay because starting windows never show
// secret information.
- if (mKeyguardHidden) {
+ if (mKeyguardOccluded) {
windowFlags |= FLAG_SHOW_WHEN_LOCKED;
}
}
@@ -2904,12 +2968,6 @@
android.Manifest.permission.STATUS_BAR_SERVICE,
"PhoneWindowManager");
break;
- case TYPE_KEYGUARD_SCRIM:
- if (mKeyguardScrim != null) {
- return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
- }
- mKeyguardScrim = win;
- break;
}
return WindowManagerGlobal.ADD_OKAY;
}
@@ -2920,11 +2978,7 @@
if (mStatusBar == win) {
mStatusBar = null;
mStatusBarController.setWindow(null);
- mKeyguardDelegate.showScrim();
- } else if (mKeyguardScrim == win) {
- Log.v(TAG, "Removing keyguard scrim");
- mKeyguardScrim = null;
- } if (mNavigationBar == win) {
+ } else if (mNavigationBar == win) {
mNavigationBar = null;
mNavigationBarController.setWindow(null);
}
@@ -3081,7 +3135,7 @@
}
@Override
- public Animation createForceHideEnterAnimation(boolean onWallpaper,
+ public Animation createHiddenByKeyguardExit(boolean onWallpaper,
boolean goingToNotificationShade) {
if (goingToNotificationShade) {
return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
@@ -3102,7 +3156,7 @@
@Override
- public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) {
+ public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
if (goingToNotificationShade) {
return null;
} else {
@@ -3236,8 +3290,7 @@
WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
if (attrs != null) {
final int type = attrs.type;
- if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
- || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
+ if (type == TYPE_KEYGUARD_DIALOG
|| (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
// the "app" is keyguard, so give it the key
return 0;
@@ -3703,12 +3756,35 @@
}
@Override
- public boolean canShowDismissingWindowWhileLockedLw() {
- // If the keyguard is trusted, it will unlock without a challenge. Therefore, if we are in
- // the process of dismissing Keyguard, we don't need to hide them as the phone will be
- // unlocked right away in any case.
- return mKeyguardDelegate != null && mKeyguardDelegate.isTrusted()
- && mCurrentlyDismissingKeyguard;
+ public void onKeyguardOccludedChangedLw(boolean occluded) {
+ if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
+ mPendingKeyguardOccluded = occluded;
+ mKeyguardOccludedChanged = true;
+ } else {
+ setKeyguardOccludedLw(occluded);
+ }
+ }
+
+ private int handleStartTransitionForKeyguardLw(int transit, @Nullable Animation anim) {
+ if (mKeyguardOccludedChanged) {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
+ + mPendingKeyguardOccluded);
+ mKeyguardOccludedChanged = false;
+ if (setKeyguardOccludedLw(mPendingKeyguardOccluded)) {
+ return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
+ }
+ }
+ if (AppTransition.isKeyguardGoingAwayTransit(transit)) {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "Starting keyguard exit animation");
+ final long startTime = anim != null
+ ? SystemClock.uptimeMillis() + anim.getStartOffset()
+ : SystemClock.uptimeMillis();
+ final long duration = anim != null
+ ? anim.getDuration()
+ : 0;
+ startKeyguardExitAnimation(startTime, duration);
+ }
+ return 0;
}
private void launchAssistLongPressAction() {
@@ -3853,7 +3929,7 @@
return;
}
- if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
+ if (!mKeyguardOccluded && mKeyguardDelegate.isInputRestricted()) {
// when in keyguard restricted mode, must first verify unlock
// before launching home
mKeyguardDelegate.verifyUnlock(new OnKeyguardExitResult() {
@@ -4166,7 +4242,7 @@
boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
boolean navAllowedHidden = immersive || immersiveSticky;
navTranslucent &= !immersiveSticky; // transient trumps translucent
- boolean isKeyguardShowing = isStatusBarKeyguard() && !mHideLockScreen;
+ boolean isKeyguardShowing = isStatusBarKeyguard() && !mKeyguardOccluded;
if (!isKeyguardShowing) {
navTranslucent &= areTranslucentBarsAllowed();
}
@@ -5073,31 +5149,23 @@
mTopFullscreenOpaqueOrDimmingWindowState = null;
mTopDockedOpaqueWindowState = null;
mTopDockedOpaqueOrDimmingWindowState = null;
- mAppsToBeHidden.clear();
- mAppsThatDismissKeyguard.clear();
mForceStatusBar = false;
mForceStatusBarFromKeyguard = false;
mForceStatusBarTransparent = false;
mForcingShowNavBar = false;
mForcingShowNavBarLayer = -1;
- mHideLockScreen = false;
mAllowLockscreenWhenOn = false;
- mDismissKeyguard = DISMISS_KEYGUARD_NONE;
- mShowingLockscreen = false;
mShowingDream = false;
- mWinShowWhenLocked = null;
- mKeyguardSecure = isKeyguardSecure(mCurrentUserId);
- mKeyguardSecureIncludingHidden = mKeyguardSecure
- && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
}
/** {@inheritDoc} */
@Override
public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
- WindowState attached) {
+ WindowState attached, WindowState imeTarget) {
if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
+ win.isVisibleOrBehindKeyguardLw());
+ applyKeyguardPolicyLw(win, imeTarget);
final int fl = PolicyControl.getWindowFlags(win, attrs);
if (mTopFullscreenOpaqueWindowState == null
&& win.isVisibleLw() && attrs.type == TYPE_INPUT_METHOD) {
@@ -5107,7 +5175,6 @@
if (attrs.type == TYPE_STATUS_BAR) {
if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
mForceStatusBarFromKeyguard = true;
- mShowingLockscreen = true;
}
if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) {
mForceStatusBarTransparent = true;
@@ -5116,17 +5183,11 @@
boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
&& attrs.type < FIRST_SYSTEM_WINDOW;
- final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
- final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
final int stackId = win.getStackId();
if (mTopFullscreenOpaqueWindowState == null &&
win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
- if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
- mForceStatusBarFromKeyguard = true;
- } else {
- mForceStatusBar = true;
- }
+ mForceStatusBar = true;
}
if (attrs.type == TYPE_DREAM) {
// If the lockscreen was showing when the dream started then wait
@@ -5138,77 +5199,20 @@
}
}
- final IApplicationToken appToken = win.getAppToken();
-
// For app windows that are not attached, we decide if all windows in the app they
// represent should be hidden or if we should hide the lockscreen. For attached app
// windows we defer the decision to the window it is attached to.
if (appWindow && attached == null) {
- if (showWhenLocked) {
- // Remove any previous windows with the same appToken.
- mAppsToBeHidden.remove(appToken);
- mAppsThatDismissKeyguard.remove(appToken);
- if (mAppsToBeHidden.isEmpty()) {
- if (dismissKeyguard && !mKeyguardSecure) {
- mAppsThatDismissKeyguard.add(appToken);
- } else if (win.isDrawnLw() || win.hasAppShownWindows()) {
- mWinShowWhenLocked = win;
- mHideLockScreen = true;
- mForceStatusBarFromKeyguard = false;
- }
- }
- } else if (dismissKeyguard) {
- if (mKeyguardSecure) {
- mAppsToBeHidden.add(appToken);
- } else {
- mAppsToBeHidden.remove(appToken);
- }
- mAppsThatDismissKeyguard.add(appToken);
- } else {
- mAppsToBeHidden.add(appToken);
- }
if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
mTopFullscreenOpaqueWindowState = win;
if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
mTopFullscreenOpaqueOrDimmingWindowState = win;
}
- if (!mAppsThatDismissKeyguard.isEmpty() &&
- mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
- if (DEBUG_LAYOUT) Slog.v(TAG,
- "Setting mDismissKeyguard true by win " + win);
- mDismissKeyguard = (mWinDismissingKeyguard == win
- && mSecureDismissingKeyguard == mKeyguardSecure)
- ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
- mWinDismissingKeyguard = win;
- mSecureDismissingKeyguard = mKeyguardSecure;
- mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
- } else if (mAppsToBeHidden.isEmpty() && showWhenLocked
- && (win.isDrawnLw() || win.hasAppShownWindows())) {
- if (DEBUG_LAYOUT) Slog.v(TAG,
- "Setting mHideLockScreen to true by win " + win);
- mHideLockScreen = true;
- mForceStatusBarFromKeyguard = false;
- }
if ((fl & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON) != 0) {
mAllowLockscreenWhenOn = true;
}
}
-
- if (!mKeyguardHidden && mWinShowWhenLocked != null &&
- mWinShowWhenLocked.getAppToken() != win.getAppToken() &&
- (attrs.flags & FLAG_SHOW_WHEN_LOCKED) == 0) {
- win.hideLw(false);
- }
- }
- } else if (mTopFullscreenOpaqueWindowState == null && mWinShowWhenLocked == null) {
- // No TopFullscreenOpaqueWindow is showing, but we found a SHOW_WHEN_LOCKED window
- // that is being hidden in an animation - keep the
- // keyguard hidden until the new window shows up and
- // we know whether to show the keyguard or not.
- if (win.isAnimatingLw() && appWindow && showWhenLocked && mKeyguardHidden) {
- mHideLockScreen = true;
- mWinShowWhenLocked = win;
}
}
@@ -5255,6 +5259,16 @@
}
}
+ private void applyKeyguardPolicyLw(WindowState win, WindowState imeTarget) {
+ if (canBeHiddenByKeyguardLw(win)) {
+ if (shouldBeHiddenByKeyguard(win, imeTarget)) {
+ win.hideLw(false /* doAnimation */);
+ } else {
+ win.showLw(false /* doAnimation */);
+ }
+ }
+ }
+
private boolean isFullscreen(WindowManager.LayoutParams attrs) {
return attrs.x == 0 && attrs.y == 0
&& attrs.width == WindowManager.LayoutParams.MATCH_PARENT
@@ -5264,17 +5278,6 @@
/** {@inheritDoc} */
@Override
public int finishPostLayoutPolicyLw() {
- if (mWinShowWhenLocked != null && mTopFullscreenOpaqueWindowState != null &&
- mWinShowWhenLocked.getAppToken() != mTopFullscreenOpaqueWindowState.getAppToken()
- && isKeyguardLocked()) {
- // A dialog is dismissing the keyguard. Put the wallpaper behind it and hide the
- // fullscreen window.
- // TODO: Make sure FLAG_SHOW_WALLPAPER is restored when dialog is dismissed. Or not.
- mWinShowWhenLocked.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
- mTopFullscreenOpaqueWindowState.hideLw(false);
- mTopFullscreenOpaqueWindowState = mWinShowWhenLocked;
- }
-
int changes = 0;
boolean topIsFullscreen = false;
@@ -5287,7 +5290,7 @@
// started while the lockscreen was showing and remember this state
// while the dream is showing.
if (!mShowingDream) {
- mDreamingLockscreen = mShowingLockscreen;
+ mDreamingLockscreen = isKeyguardShowingAndNotOccluded();
if (mDreamingSleepTokenNeeded) {
mDreamingSleepTokenNeeded = false;
mHandler.obtainMessage(MSG_UPDATE_DREAMING_SLEEP_TOKEN, 0, 1).sendToTarget();
@@ -5378,79 +5381,17 @@
mTopIsFullscreen = topIsFullscreen;
}
- // Hide the key guard if a visible window explicitly specifies that it wants to be
- // displayed when the screen is locked.
- if (mKeyguardDelegate != null && mStatusBar != null) {
- if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
- + mHideLockScreen);
- if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
- mKeyguardHidden = true;
- if (setKeyguardOccludedLw(true)) {
- changes |= FINISH_LAYOUT_REDO_LAYOUT
- | FINISH_LAYOUT_REDO_CONFIG
- | FINISH_LAYOUT_REDO_WALLPAPER;
- }
- if (mKeyguardDelegate.isShowing()) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mKeyguardDelegate.keyguardDone(false, false);
- }
- });
- }
- } else if (mHideLockScreen) {
- mKeyguardHidden = true;
- mWinDismissingKeyguard = null;
- if (setKeyguardOccludedLw(true)) {
- changes |= FINISH_LAYOUT_REDO_LAYOUT
- | FINISH_LAYOUT_REDO_CONFIG
- | FINISH_LAYOUT_REDO_WALLPAPER;
- }
- } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
- mKeyguardHidden = false;
- boolean dismissKeyguard = false;
- final boolean trusted = mKeyguardDelegate.isTrusted();
- if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
- final boolean willDismiss = trusted && mKeyguardOccluded
- && mKeyguardDelegate != null && mKeyguardDelegate.isShowing();
- if (willDismiss) {
- mCurrentlyDismissingKeyguard = true;
- }
- dismissKeyguard = true;
- }
-
- // If we are currently dismissing Keyguard, there is no need to unocclude it.
- if (!mCurrentlyDismissingKeyguard) {
- if (setKeyguardOccludedLw(false)) {
- changes |= FINISH_LAYOUT_REDO_LAYOUT
- | FINISH_LAYOUT_REDO_CONFIG
- | FINISH_LAYOUT_REDO_WALLPAPER;
- }
- }
-
- if (dismissKeyguard) {
- // Only launch the next keyguard unlock window once per window.
- mHandler.post(() -> mKeyguardDelegate.dismiss(
- trusted /* allowWhileOccluded */));
- }
- } else {
- mWinDismissingKeyguard = null;
- mSecureDismissingKeyguard = false;
- mKeyguardHidden = false;
- if (setKeyguardOccludedLw(false)) {
- changes |= FINISH_LAYOUT_REDO_LAYOUT
- | FINISH_LAYOUT_REDO_CONFIG
- | FINISH_LAYOUT_REDO_WALLPAPER;
- }
- }
- }
-
if ((updateSystemUiVisibilityLw()&SYSTEM_UI_CHANGING_LAYOUT) != 0) {
// If the navigation bar has been hidden or shown, we need to do another
// layout pass to update that window.
changes |= FINISH_LAYOUT_REDO_LAYOUT;
}
+ if (mShowingDream != mLastShowingDream) {
+ mLastShowingDream = mShowingDream;
+ mWindowManagerFuncs.notifyShowingDreamChanged();
+ }
+
// update since mAllowLockscreenWhenOn might have changed
updateLockScreenTimeout();
return changes;
@@ -5462,6 +5403,7 @@
* @return Whether the flags have changed and we have to redo the layout.
*/
private boolean setKeyguardOccludedLw(boolean isOccluded) {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
boolean wasOccluded = mKeyguardOccluded;
boolean showing = mKeyguardDelegate.isShowing();
if (wasOccluded && !isOccluded && showing) {
@@ -5471,9 +5413,6 @@
if (!mKeyguardDelegate.hasLockscreenWallpaper()) {
mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
}
- Animation anim = AnimationUtils.loadAnimation(mContext,
- com.android.internal.R.anim.wallpaper_open_exit);
- mWindowManagerFuncs.overridePlayingAppAnimationsLw(anim);
return true;
} else if (!wasOccluded && isOccluded && showing) {
mKeyguardOccluded = true;
@@ -5490,14 +5429,6 @@
}
}
- private void onKeyguardShowingStateChanged(boolean showing) {
- if (!showing) {
- synchronized (mWindowManagerFuncs.getWindowManagerLock()) {
- mCurrentlyDismissingKeyguard = false;
- }
- }
- }
-
private boolean isStatusBarKeyguard() {
return mStatusBar != null
&& (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
@@ -5505,7 +5436,7 @@
@Override
public boolean allowAppAnimationsLw() {
- if (isStatusBarKeyguard() || mShowingDream) {
+ if (mShowingDream) {
// If keyguard or dreams is currently visible, no reason to animate behind it.
return false;
}
@@ -6657,6 +6588,12 @@
return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
}
+ @Override
+ public boolean isKeyguardTrustedLw() {
+ if (mKeyguardDelegate == null) return false;
+ return mKeyguardDelegate.isTrusted();
+ }
+
/** {@inheritDoc} */
@Override
public boolean isKeyguardLocked() {
@@ -6672,8 +6609,9 @@
/** {@inheritDoc} */
@Override
- public boolean isKeyguardShowingOrOccluded() {
- return mKeyguardDelegate == null ? false : mKeyguardDelegate.isShowing();
+ public boolean isKeyguardOccluded() {
+ if (mKeyguardDelegate == null) return false;
+ return mKeyguardOccluded;
}
/** {@inheritDoc} */
@@ -6687,25 +6625,9 @@
public void dismissKeyguardLw() {
if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- // ask the keyguard to prompt the user to authenticate if necessary
- mKeyguardDelegate.dismiss(false /* allowWhileOccluded */);
- }
- });
- }
- }
- @Override
- public void notifyActivityDrawnForKeyguardLw() {
- if (mKeyguardDelegate != null) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mKeyguardDelegate.onActivityDrawn();
- }
- });
+ // ask the keyguard to prompt the user to authenticate if necessary
+ mKeyguardDelegate.dismiss(true /* allowWhileOccluded */);
}
}
@@ -6717,6 +6639,11 @@
}
@Override
+ public boolean isShowingDreamLw() {
+ return mShowingDream;
+ }
+
+ @Override
public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
if (mKeyguardDelegate != null) {
if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
@@ -7028,8 +6955,7 @@
/** {@inheritDoc} */
@Override
public void systemReady() {
- mKeyguardDelegate = new KeyguardServiceDelegate(mContext,
- this::onKeyguardShowingStateChanged);
+ mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
mKeyguardDelegate.onSystemReady();
readCameraLensCoverState();
@@ -7576,7 +7502,7 @@
}
}
final WindowState win = winCandidate;
- if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
+ if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mKeyguardOccluded) {
// We are updating at a point where the keyguard has gotten
// focus, but we were last in a state where the top window is
// hiding it. This is probably because the keyguard as been
@@ -7633,7 +7559,7 @@
}
private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
- WindowState statusColorWin = isStatusBarKeyguard() && !mHideLockScreen
+ WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
? mStatusBar
: opaqueOrDimming;
@@ -7674,7 +7600,7 @@
final boolean forceOpaqueStatusBar = mForceShowSystemBars && !mForceStatusBarFromKeyguard;
// apply translucent bar vis flags
- WindowState fullscreenTransWin = isStatusBarKeyguard() && !mHideLockScreen
+ WindowState fullscreenTransWin = isStatusBarKeyguard() && !mKeyguardOccluded
? mStatusBar
: mTopFullscreenOpaqueWindowState;
vis = mStatusBarController.applyTranslucentFlagLw(fullscreenTransWin, vis, oldVis);
@@ -7700,7 +7626,7 @@
| View.SYSTEM_UI_FLAG_IMMERSIVE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
- if (mHideLockScreen) {
+ if (mKeyguardOccluded) {
flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
}
vis = (vis & ~flags) | (oldVis & flags);
@@ -8069,8 +7995,7 @@
pw.print(","); pw.print(mDockBottom); pw.println(")");
pw.print(prefix); pw.print("mDockLayer="); pw.print(mDockLayer);
pw.print(" mStatusBarLayer="); pw.println(mStatusBarLayer);
- pw.print(prefix); pw.print("mShowingLockscreen="); pw.print(mShowingLockscreen);
- pw.print(" mShowingDream="); pw.print(mShowingDream);
+ pw.print(prefix); pw.print("mShowingDream="); pw.print(mShowingDream);
pw.print(" mDreamingLockscreen="); pw.print(mDreamingLockscreen);
pw.print(" mDreamingSleepToken="); pw.println(mDreamingSleepToken);
if (mLastInputMethodWindow != null) {
@@ -8098,10 +8023,6 @@
pw.print(prefix); pw.print("mFocusedApp=");
pw.println(mFocusedApp);
}
- if (mWinDismissingKeyguard != null) {
- pw.print(prefix); pw.print("mWinDismissingKeyguard=");
- pw.println(mWinDismissingKeyguard);
- }
if (mTopFullscreenOpaqueWindowState != null) {
pw.print(prefix); pw.print("mTopFullscreenOpaqueWindowState=");
pw.println(mTopFullscreenOpaqueWindowState);
@@ -8116,14 +8037,13 @@
pw.println(mForcingShowNavBarLayer);
}
pw.print(prefix); pw.print("mTopIsFullscreen="); pw.print(mTopIsFullscreen);
- pw.print(" mHideLockScreen="); pw.println(mHideLockScreen);
+ pw.print(" mKeyguardOccluded="); pw.println(mKeyguardOccluded);
+ pw.print(" mKeyguardOccludedChanged="); pw.println(mKeyguardOccludedChanged);
+ pw.print(" mPendingKeyguardOccluded="); pw.println(mPendingKeyguardOccluded);
pw.print(prefix); pw.print("mForceStatusBar="); pw.print(mForceStatusBar);
pw.print(" mForceStatusBarFromKeyguard=");
pw.println(mForceStatusBarFromKeyguard);
- pw.print(prefix); pw.print("mDismissKeyguard="); pw.print(mDismissKeyguard);
- pw.print(" mCurrentlyDismissingKeyguard="); pw.println(mCurrentlyDismissingKeyguard);
- pw.print(" mWinDismissingKeyguard="); pw.print(mWinDismissingKeyguard);
- pw.print(" mHomePressed="); pw.println(mHomePressed);
+ pw.print(prefix); pw.print("mHomePressed="); pw.println(mHomePressed);
pw.print(prefix); pw.print("mAllowLockscreenWhenOn="); pw.print(mAllowLockscreenWhenOn);
pw.print(" mLockScreenTimeout="); pw.print(mLockScreenTimeout);
pw.print(" mLockScreenTimerActive="); pw.println(mLockScreenTimerActive);
diff --git a/services/core/java/com/android/server/policy/StatusBarController.java b/services/core/java/com/android/server/policy/StatusBarController.java
index 1dbc44e..7d67b60 100644
--- a/services/core/java/com/android/server/policy/StatusBarController.java
+++ b/services/core/java/com/android/server/policy/StatusBarController.java
@@ -56,8 +56,8 @@
}
@Override
- public void onAppTransitionStartingLocked(IBinder openToken, IBinder closeToken,
- final Animation openAnimation, final Animation closeAnimation) {
+ public int onAppTransitionStartingLocked(int transit, IBinder openToken,
+ IBinder closeToken, final Animation openAnimation, final Animation closeAnimation) {
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -71,10 +71,11 @@
}
}
});
+ return 0;
}
@Override
- public void onAppTransitionCancelledLocked() {
+ public void onAppTransitionCancelledLocked(int transit) {
mHandler.post(new Runnable() {
@Override
public void run() {
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 10c237f..28f36f7 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -1,12 +1,13 @@
package com.android.server.policy.keyguard;
+import android.app.ActivityManager;
+import android.app.ActivityManagerInternal;
+import android.app.ActivityManagerNative;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
import android.content.res.Resources;
-import android.graphics.PixelFormat;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -15,15 +16,13 @@
import android.util.Log;
import android.util.Slog;
import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
import android.view.WindowManagerPolicy.OnKeyguardExitResult;
import com.android.internal.policy.IKeyguardDrawnCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService;
+import com.android.server.LocalServices;
import com.android.server.UiThread;
-import com.android.server.policy.keyguard.KeyguardStateMonitor.OnShowingStateChangedCallback;
import java.io.PrintWriter;
@@ -46,23 +45,13 @@
protected KeyguardServiceWrapper mKeyguardService;
private final Context mContext;
- private final View mScrim; // shown if keyguard crashes
- private final Handler mScrimHandler;
+ private final Handler mHandler;
private final KeyguardState mKeyguardState = new KeyguardState();
private DrawnListener mDrawnListenerWhenConnect;
- private final OnShowingStateChangedCallback mShowingStateChangedCallback;
private static final class KeyguardState {
KeyguardState() {
- // Assume keyguard is showing and secure until we know for sure. This is here in
- // the event something checks before the service is actually started.
- // KeyguardService itself should default to this state until the real state is known.
- showing = true;
- showingAndNotOccluded = true;
- secure = true;
- deviceHasKeyguard = true;
- enabled = true;
- currentUser = UserHandle.USER_NULL;
+ reset();
}
boolean showing;
boolean showingAndNotOccluded;
@@ -78,6 +67,18 @@
public boolean bootCompleted;
public int screenState;
public int interactiveState;
+
+ private void reset() {
+ // Assume keyguard is showing and secure until we know for sure. This is here in
+ // the event something checks before the service is actually started.
+ // KeyguardService itself should default to this state until the real state is known.
+ showing = true;
+ showingAndNotOccluded = true;
+ secure = true;
+ deviceHasKeyguard = true;
+ enabled = true;
+ currentUser = UserHandle.USER_NULL;
+ }
};
public interface DrawnListener {
@@ -98,7 +99,6 @@
if (mDrawnListener != null) {
mDrawnListener.onDrawn();
}
- hideScrim();
}
};
@@ -119,12 +119,9 @@
}
};
- public KeyguardServiceDelegate(Context context,
- OnShowingStateChangedCallback showingStateChangedCallback) {
+ public KeyguardServiceDelegate(Context context) {
mContext = context;
- mScrimHandler = UiThread.getHandler();
- mShowingStateChangedCallback = showingStateChangedCallback;
- mScrim = createScrim(context, mScrimHandler);
+ mHandler = UiThread.getHandler();
}
public void bindService(Context context) {
@@ -137,7 +134,7 @@
intent.setComponent(keyguardComponent);
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
- Context.BIND_AUTO_CREATE, mScrimHandler, UserHandle.SYSTEM)) {
+ Context.BIND_AUTO_CREATE, mHandler, UserHandle.SYSTEM)) {
Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent);
mKeyguardState.showing = false;
mKeyguardState.showingAndNotOccluded = false;
@@ -147,7 +144,6 @@
// is at least self-healing but a race condition here can lead to the scrim being
// stuck on keyguard-less devices.
mKeyguardState.deviceHasKeyguard = false;
- hideScrim();
}
} else {
if (DEBUG) Log.v(TAG, "*** Keyguard started");
@@ -159,7 +155,7 @@
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
mKeyguardService = new KeyguardServiceWrapper(mContext,
- IKeyguardService.Stub.asInterface(service), mShowingStateChangedCallback);
+ IKeyguardService.Stub.asInterface(service));
if (mKeyguardState.systemIsReady) {
// If the system is ready, it means keyguard crashed and restarted.
mKeyguardService.onSystemReady();
@@ -196,8 +192,15 @@
public void onServiceDisconnected(ComponentName name) {
if (DEBUG) Log.v(TAG, "*** Keyguard disconnected (boo!)");
mKeyguardService = null;
+ mKeyguardState.reset();
+ mHandler.post(() -> {
+ try {
+ ActivityManagerNative.getDefault().setLockScreenShown(true);
+ } catch (RemoteException e) {
+ // Local call.
+ }
+ });
}
-
};
public boolean isShowing() {
@@ -234,12 +237,6 @@
}
}
- public void keyguardDone(boolean authenticated, boolean wakeup) {
- if (mKeyguardService != null) {
- mKeyguardService.keyguardDone(authenticated, wakeup);
- }
- }
-
public void setOccluded(boolean isOccluded, boolean animate) {
if (mKeyguardService != null) {
if (DEBUG) Log.v(TAG, "setOccluded(" + isOccluded + ") animate=" + animate);
@@ -301,7 +298,6 @@
// This shouldn't happen, but if it does, show the scrim immediately and
// invoke the listener's callback after the service actually connects.
mDrawnListenerWhenConnect = drawnListener;
- showScrim();
}
mKeyguardState.screenState = SCREEN_STATE_TURNING_ON;
}
@@ -369,61 +365,6 @@
}
}
- private static View createScrim(Context context, Handler handler) {
- final View view = new View(context);
-
- int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
- | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
- | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
- | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
- ;
-
- final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
- final int type = WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
- stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);
- lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
- lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
- lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED;
- lp.setTitle("KeyguardScrim");
- final WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- // Disable pretty much everything in statusbar until keyguard comes back and we know
- // the state of the world.
- view.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME
- | View.STATUS_BAR_DISABLE_BACK
- | View.STATUS_BAR_DISABLE_RECENT
- | View.STATUS_BAR_DISABLE_EXPAND
- | View.STATUS_BAR_DISABLE_SEARCH);
- handler.post(new Runnable() {
- @Override
- public void run() {
- wm.addView(view, lp);
- }
- });
- return view;
- }
-
- public void showScrim() {
- synchronized (mKeyguardState) {
- if (!mKeyguardState.deviceHasKeyguard) return;
- mScrimHandler.post(new Runnable() {
- @Override
- public void run() {
- mScrim.setVisibility(View.VISIBLE);
- }
- });
- }
- }
-
- public void hideScrim() {
- mScrimHandler.post(new Runnable() {
- @Override
- public void run() {
- mScrim.setVisibility(View.GONE);
- }
- });
- }
-
public void onBootCompleted() {
if (mKeyguardService != null) {
mKeyguardService.onBootCompleted();
@@ -431,12 +372,6 @@
mKeyguardState.bootCompleted = true;
}
- public void onActivityDrawn() {
- if (mKeyguardService != null) {
- mKeyguardService.onActivityDrawn();
- }
- }
-
public void dump(String prefix, PrintWriter pw) {
pw.println(prefix + TAG);
prefix += " ";
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index acc67db..b457f8d 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -26,7 +26,6 @@
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService;
import com.android.internal.policy.IKeyguardStateCallback;
-import com.android.server.policy.keyguard.KeyguardStateMonitor.OnShowingStateChangedCallback;
import java.io.PrintWriter;
@@ -40,11 +39,9 @@
private IKeyguardService mService;
private String TAG = "KeyguardServiceWrapper";
- public KeyguardServiceWrapper(Context context, IKeyguardService service,
- OnShowingStateChangedCallback showingStateChangedCallback) {
+ public KeyguardServiceWrapper(Context context, IKeyguardService service) {
mService = service;
- mKeyguardStateMonitor = new KeyguardStateMonitor(context, service,
- showingStateChangedCallback);
+ mKeyguardStateMonitor = new KeyguardStateMonitor(context, service);
}
@Override // Binder interface
@@ -57,15 +54,6 @@
}
@Override // Binder interface
- public void keyguardDone(boolean authenticated, boolean wakeup) {
- try {
- mService.keyguardDone(authenticated, wakeup);
- } catch (RemoteException e) {
- Slog.w(TAG , "Remote Exception", e);
- }
- }
-
- @Override // Binder interface
public void setOccluded(boolean isOccluded, boolean animate) {
try {
mService.setOccluded(isOccluded, animate);
@@ -229,15 +217,6 @@
}
@Override // Binder interface
- public void onActivityDrawn() {
- try {
- mService.onActivityDrawn();
- } catch (RemoteException e) {
- Slog.w(TAG , "Remote Exception", e);
- }
- }
-
- @Override // Binder interface
public IBinder asBinder() {
return mService.asBinder();
}
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
index 712b625..f19f0aa 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java
@@ -49,13 +49,11 @@
private int mCurrentUserId;
private final LockPatternUtils mLockPatternUtils;
- private final OnShowingStateChangedCallback mOnShowingStateChangedCallback;
- public KeyguardStateMonitor(Context context, IKeyguardService service,
- OnShowingStateChangedCallback showingStateChangedCallback) {
+ public KeyguardStateMonitor(Context context, IKeyguardService service) {
mLockPatternUtils = new LockPatternUtils(context);
mCurrentUserId = ActivityManager.getCurrentUser();
- mOnShowingStateChangedCallback = showingStateChangedCallback;
+
try {
service.addStateMonitorCallback(this);
} catch (RemoteException e) {
@@ -86,7 +84,6 @@
@Override // Binder interface
public void onShowingStateChanged(boolean showing) {
mIsShowing = showing;
- mOnShowingStateChangedCallback.onShowingStateChanged(showing);
}
@Override // Binder interface
@@ -126,8 +123,4 @@
pw.println(prefix + "mTrusted=" + mTrusted);
pw.println(prefix + "mCurrentUserId=" + mCurrentUserId);
}
-
- public interface OnShowingStateChangedCallback {
- void onShowingStateChanged(boolean showing);
- }
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index bde65ed..670b9cc 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -1283,8 +1283,7 @@
}
private static boolean isReportedWindowType(int windowType) {
- return (windowType != WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
- && windowType != WindowManager.LayoutParams.TYPE_WALLPAPER
+ return (windowType != WindowManager.LayoutParams.TYPE_WALLPAPER
&& windowType != WindowManager.LayoutParams.TYPE_BOOT_PROGRESS
&& windowType != WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY
&& windowType != WindowManager.LayoutParams.TYPE_DRAG
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index cd46165..862c145 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -135,6 +135,21 @@
public static final int TRANSIT_ACTIVITY_RELAUNCH = 18;
/** A task is being docked from recents. */
public static final int TRANSIT_DOCK_TASK_FROM_RECENTS = 19;
+ /** Keyguard is going away */
+ public static final int TRANSIT_KEYGUARD_GOING_AWAY = 20;
+ /** Keyguard is going away with showing an activity behind that requests wallpaper */
+ public static final int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21;
+ /** Keyguard is being occluded */
+ public static final int TRANSIT_KEYGUARD_OCCLUDE = 22;
+ /** Keyguard is being unoccluded */
+ public static final int TRANSIT_KEYGUARD_UNOCCLUDE = 23;
+
+ /** Transition flag: Keyguard is going away, but keeping the notification shade open */
+ public static final int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE = 0x1;
+ /** Transition flag: Keyguard is going away, but doesn't want an animation for it */
+ public static final int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION = 0x2;
+ /** Transition flag: Keyguard is going away while it was showing the system wallpaper. */
+ public static final int TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER = 0x4;
/** Fraction of animation at which the recents thumbnail stays completely transparent */
private static final float RECENTS_THUMBNAIL_FADEIN_FRACTION = 0.5f;
@@ -162,6 +177,7 @@
private final WindowManagerService mService;
private int mNextAppTransition = TRANSIT_UNSET;
+ private int mNextAppTransitionFlags = 0;
private int mLastUsedAppTransition = TRANSIT_UNSET;
private String mLastOpeningApp;
private String mLastClosingApp;
@@ -286,8 +302,9 @@
return mNextAppTransition;
}
- private void setAppTransition(int transit) {
+ private void setAppTransition(int transit, int flags) {
mNextAppTransition = transit;
+ mNextAppTransitionFlags |= flags;
setLastAppTransition(TRANSIT_UNSET, null, null);
}
@@ -372,27 +389,33 @@
return false;
}
- void goodToGo(AppWindowAnimator topOpeningAppAnimator, AppWindowAnimator topClosingAppAnimator,
- ArraySet<AppWindowToken> openingApps, ArraySet<AppWindowToken> closingApps) {
- int appTransition = mNextAppTransition;
+ /**
+ * @return bit-map of WindowManagerPolicy#FINISH_LAYOUT_REDO_* to indicate whether another
+ * layout pass needs to be done
+ */
+ int goodToGo(int transit, AppWindowAnimator topOpeningAppAnimator,
+ AppWindowAnimator topClosingAppAnimator, ArraySet<AppWindowToken> openingApps,
+ ArraySet<AppWindowToken> closingApps) {
mNextAppTransition = TRANSIT_UNSET;
+ mNextAppTransitionFlags = 0;
mAppTransitionState = APP_STATE_RUNNING;
- notifyAppTransitionStartingLocked(
+ int redoLayout = notifyAppTransitionStartingLocked(transit,
topOpeningAppAnimator != null ? topOpeningAppAnimator.mAppToken.token : null,
topClosingAppAnimator != null ? topClosingAppAnimator.mAppToken.token : null,
topOpeningAppAnimator != null ? topOpeningAppAnimator.animation : null,
topClosingAppAnimator != null ? topClosingAppAnimator.animation : null);
mService.getDefaultDisplayContentLocked().getDockedDividerController()
- .notifyAppTransitionStarting(openingApps, appTransition);
+ .notifyAppTransitionStarting(openingApps, transit);
// Prolong the start for the transition when docking a task from recents, unless recents
// ended it already then we don't need to wait.
- if (mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS && !mProlongedAnimationsEnded) {
+ if (transit == TRANSIT_DOCK_TASK_FROM_RECENTS && !mProlongedAnimationsEnded) {
for (int i = openingApps.size() - 1; i >= 0; i--) {
final AppWindowAnimator appAnimator = openingApps.valueAt(i).mAppAnimator;
appAnimator.startProlongAnimation(PROLONG_ANIMATION_AT_START);
}
}
+ return redoLayout;
}
/**
@@ -413,10 +436,11 @@
}
void freeze() {
- setAppTransition(AppTransition.TRANSIT_UNSET);
+ final int transit = mNextAppTransition;
+ setAppTransition(AppTransition.TRANSIT_UNSET, 0 /* flags */);
clear();
setReady();
- notifyAppTransitionCancelledLocked();
+ notifyAppTransitionCancelledLocked(transit);
}
void registerListenerLocked(AppTransitionListener listener) {
@@ -435,18 +459,20 @@
}
}
- private void notifyAppTransitionCancelledLocked() {
+ private void notifyAppTransitionCancelledLocked(int transit) {
for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onAppTransitionCancelledLocked();
+ mListeners.get(i).onAppTransitionCancelledLocked(transit);
}
}
- private void notifyAppTransitionStartingLocked(IBinder openToken,
+ private int notifyAppTransitionStartingLocked(int transit, IBinder openToken,
IBinder closeToken, Animation openAnimation, Animation closeAnimation) {
+ int redoLayout = 0;
for (int i = 0; i < mListeners.size(); i++) {
- mListeners.get(i).onAppTransitionStartingLocked(openToken, closeToken, openAnimation,
- closeAnimation);
+ redoLayout |= mListeners.get(i).onAppTransitionStartingLocked(transit, openToken,
+ closeToken, openAnimation, closeAnimation);
}
+ return redoLayout;
}
private AttributeCache.Entry getCachedAnimations(WindowManager.LayoutParams lp) {
@@ -1406,7 +1432,8 @@
boolean canSkipFirstFrame() {
return mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM
&& mNextAppTransitionType != NEXT_TRANSIT_TYPE_CUSTOM_IN_PLACE
- && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CLIP_REVEAL;
+ && mNextAppTransitionType != NEXT_TRANSIT_TYPE_CLIP_REVEAL
+ && mNextAppTransition != TRANSIT_KEYGUARD_GOING_AWAY;
}
/**
@@ -1435,7 +1462,13 @@
@Nullable Rect surfaceInsets, boolean isVoiceInteraction, boolean freeform,
int taskId) {
Animation a;
- if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN
+ if (isKeyguardGoingAwayTransit(transit) && enter) {
+ a = loadKeyguardExitAnimation(transit);
+ } else if (transit == TRANSIT_KEYGUARD_OCCLUDE) {
+ a = null;
+ } else if (transit == TRANSIT_KEYGUARD_UNOCCLUDE && !enter) {
+ a = loadAnimationRes(lp, com.android.internal.R.anim.wallpaper_open_exit);
+ } else if (isVoiceInteraction && (transit == TRANSIT_ACTIVITY_OPEN
|| transit == TRANSIT_TASK_OPEN
|| transit == TRANSIT_TASK_TO_FRONT)) {
a = loadAnimationRes(lp, enter
@@ -1590,14 +1623,30 @@
return a;
}
+ private Animation loadKeyguardExitAnimation(int transit) {
+ if ((mNextAppTransitionFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) != 0) {
+ return null;
+ }
+ final boolean toShade =
+ (mNextAppTransitionFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0;
+ return mService.mPolicy.createHiddenByKeyguardExit(
+ transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER, toShade);
+ }
+
int getAppStackClipMode() {
return mNextAppTransition == TRANSIT_ACTIVITY_RELAUNCH
|| mNextAppTransition == TRANSIT_DOCK_TASK_FROM_RECENTS
+ || mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY
+ || mNextAppTransition == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
|| mNextAppTransitionType == NEXT_TRANSIT_TYPE_CLIP_REVEAL
? STACK_CLIP_NONE
: STACK_CLIP_AFTER_ANIM;
}
+ public int getTransitFlags() {
+ return mNextAppTransitionFlags;
+ }
+
void postAnimationCallback() {
if (mNextAppTransitionCallback != null) {
mService.mH.sendMessage(mService.mH.obtainMessage(H.DO_ANIMATION_CALLBACK,
@@ -1819,6 +1868,18 @@
case TRANSIT_DOCK_TASK_FROM_RECENTS: {
return "TRANSIT_DOCK_TASK_FROM_RECENTS";
}
+ case TRANSIT_KEYGUARD_GOING_AWAY: {
+ return "TRANSIT_KEYGUARD_GOING_AWAY";
+ }
+ case TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER: {
+ return "TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER";
+ }
+ case TRANSIT_KEYGUARD_OCCLUDE: {
+ return "TRANSIT_KEYGUARD_OCCLUDE";
+ }
+ case TRANSIT_KEYGUARD_UNOCCLUDE: {
+ return "TRANSIT_KEYGUARD_UNOCCLUDE";
+ }
default: {
return "<UNKNOWN>";
}
@@ -1933,22 +1994,24 @@
* @return true if transition is not running and should not be skipped, false if transition is
* already running
*/
- boolean prepareAppTransitionLocked(int transit, boolean alwaysKeepCurrent) {
+ boolean prepareAppTransitionLocked(int transit, boolean alwaysKeepCurrent, int flags,
+ boolean forceOverride) {
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Prepare app transition:"
+ " transit=" + appTransitionToString(transit)
+ " " + this
+ " alwaysKeepCurrent=" + alwaysKeepCurrent
+ " Callers=" + Debug.getCallers(3));
- if (!isTransitionSet() || mNextAppTransition == TRANSIT_NONE) {
- setAppTransition(transit);
+ if (forceOverride || isKeyguardTransit(transit) || !isTransitionSet()
+ || mNextAppTransition == TRANSIT_NONE) {
+ setAppTransition(transit, flags);
} else if (!alwaysKeepCurrent) {
if (transit == TRANSIT_TASK_OPEN && isTransitionEqual(TRANSIT_TASK_CLOSE)) {
// Opening a new task always supersedes a close for the anim.
- setAppTransition(transit);
+ setAppTransition(transit, flags);
} else if (transit == TRANSIT_ACTIVITY_OPEN
&& isTransitionEqual(TRANSIT_ACTIVITY_CLOSE)) {
// Opening a new activity always supersedes a close for the anim.
- setAppTransition(transit);
+ setAppTransition(transit, flags);
}
}
boolean prepared = prepare();
@@ -1960,6 +2023,20 @@
}
/**
+ * @return true if {@param transit} is representing a transition in which Keyguard is going
+ * away, false otherwise
+ */
+ public static boolean isKeyguardGoingAwayTransit(int transit) {
+ return transit == TRANSIT_KEYGUARD_GOING_AWAY
+ || transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+ }
+
+ private static boolean isKeyguardTransit(int transit) {
+ return isKeyguardGoingAwayTransit(transit) || transit == TRANSIT_KEYGUARD_OCCLUDE
+ || transit == TRANSIT_KEYGUARD_UNOCCLUDE;
+ }
+
+ /**
* @return whether the specified {@param uiMode} is the TV mode.
*/
private boolean isTvUiMode(int uiMode) {
diff --git a/services/core/java/com/android/server/wm/AppWindowAnimator.java b/services/core/java/com/android/server/wm/AppWindowAnimator.java
index e774259..e1b598a 100644
--- a/services/core/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/core/java/com/android/server/wm/AppWindowAnimator.java
@@ -17,6 +17,8 @@
package com.android.server.wm;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+
+import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
@@ -95,6 +97,8 @@
// that if recents doesn't tell us to remove the prolonged animation, we will get rid of it
// when new animation is set.
private boolean mClearProlongedAnimation;
+ private int mTransit;
+ private int mTransitFlags;
/** WindowStateAnimator from mAppAnimator.allAppWindows as of last performLayout */
ArrayList<WindowStateAnimator> mAllAppWinAnimators = new ArrayList<>();
@@ -114,15 +118,16 @@
mAnimator = mService.mAnimator;
}
- public void setAnimation(Animation anim, int width, int height, boolean skipFirstFrame,
- int stackClip) {
+ public void setAnimation(Animation anim, int width, int height, int parentWidth,
+ int parentHeight, boolean skipFirstFrame, int stackClip, int transit,
+ int transitFlags) {
if (WindowManagerService.localLOGV) Slog.v(TAG, "Setting animation in " + mAppToken
+ ": " + anim + " wxh=" + width + "x" + height
+ " hasContentToDisplay=" + mAppToken.hasContentToDisplay());
animation = anim;
animating = false;
if (!anim.isInitialized()) {
- anim.initialize(width, height, width, height);
+ anim.initialize(width, height, parentWidth, parentHeight);
}
anim.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
anim.scaleCurrentDuration(mService.getTransitionAnimationScaleLocked());
@@ -144,7 +149,9 @@
hasTransformation = true;
mStackClip = stackClip;
- this.mSkipFirstFrame = skipFirstFrame;
+ mSkipFirstFrame = skipFirstFrame;
+ mTransit = transit;
+ mTransitFlags = transitFlags;
if (!mAppToken.fillsParent()) {
anim.setBackgroundColor(0);
@@ -185,12 +192,22 @@
mAppToken.clearAllDrawn();
}
mStackClip = STACK_CLIP_BEFORE_ANIM;
+ mTransit = TRANSIT_UNSET;
+ mTransitFlags = 0;
}
public boolean isAnimating() {
return animation != null || mAppToken.inPendingTransaction;
}
+ public int getTransit() {
+ return mTransit;
+ }
+
+ int getTransitFlags() {
+ return mTransitFlags;
+ }
+
public void clearThumbnail() {
if (thumbnail != null) {
thumbnail.hide();
@@ -216,6 +233,7 @@
toAppAnimator.updateLayers();
updateLayers();
toAppAnimator.usingTransferredAnimation = true;
+ toAppAnimator.mTransit = mTransit;
}
if (transferWinAnimator != null) {
mAllAppWinAnimators.remove(transferWinAnimator);
@@ -435,6 +453,8 @@
if (animating || animation != null) {
pw.print(prefix); pw.print("animating="); pw.println(animating);
pw.print(prefix); pw.print("animation="); pw.println(animation);
+ pw.print(prefix); pw.print("mTransit="); pw.println(mTransit);
+ pw.print(prefix); pw.print("mTransitFlags="); pw.println(mTransitFlags);
}
if (hasTransformation) {
pw.print(prefix); pw.print("XForm: ");
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index e3588ff..a44c8aa 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -19,6 +19,8 @@
import static android.app.ActivityManager.StackId;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -152,6 +154,9 @@
int mRotationAnimationHint;
private int mPendingRelaunchCount;
+ private boolean mLastContainsShowWhenLockedWindow;
+ private boolean mLastContainsDismissKeyguardWindow;
+
private ArrayList<WindowSurfaceController.SurfaceControlWithBackground> mSurfaceViewBackgrounds =
new ArrayList<>();
@@ -718,6 +723,13 @@
if (gotReplacementWindow) {
mService.scheduleWindowReplacementTimeouts(this);
}
+ checkKeyguardFlagsChanged();
+ }
+
+ @Override
+ void removeChild(WindowState child) {
+ super.removeChild(child);
+ checkKeyguardFlagsChanged();
}
private boolean waitingForReplacement() {
@@ -808,21 +820,6 @@
}
}
- /**
- * See {@link WindowManagerService#overridePlayingAppAnimationsLw}
- */
- void overridePlayingAppAnimations(Animation a) {
- if (mAppAnimator.isAnimating()) {
- final WindowState win = findMainWindow();
- if (win == null) {
- return;
- }
- final int width = win.mContainingFrame.width();
- final int height = win.mContainingFrame.height();
- mAppAnimator.setAnimation(a, width, height, false, STACK_CLIP_NONE);
- }
- }
-
void resetJustMovedInStack() {
for (int i = mChildren.size() - 1; i >= 0; i--) {
(mChildren.get(i)).resetJustMovedInStack();
@@ -1224,6 +1221,35 @@
mFillsParent = fillsParent;
}
+ boolean containsDismissKeyguardWindow() {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean containsShowWhenLockedWindow() {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void checkKeyguardFlagsChanged() {
+ final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
+ final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
+ if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
+ || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
+ mService.notifyKeyguardFlagsChanged(null /* callback */);
+ }
+ mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
+ mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
+ }
+
@Override
void dump(PrintWriter pw, String prefix) {
super.dump(pw, prefix);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 793d2fe..1960285 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -62,31 +62,23 @@
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
-import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
-import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
-import static com.android.server.wm.WindowAnimator.KEYGUARD_ANIMATING_OUT;
-import static com.android.server.wm.WindowAnimator.KEYGUARD_ANIM_TIMEOUT_MS;
-import static com.android.server.wm.WindowAnimator.KEYGUARD_NOT_SHOWN;
-import static com.android.server.wm.WindowAnimator.KEYGUARD_SHOWN;
+
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -105,8 +97,6 @@
import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
-import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
-import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
import android.annotation.NonNull;
@@ -133,8 +123,6 @@
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowManagerPolicy;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.view.IInputMethodClient;
@@ -467,24 +455,7 @@
}
mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
- if (policy.isKeyguardLocked()) {
- // The screen is locked and no top system window is requesting an orientation.
- // Return either the orientation of the show-when-locked app (if there is any) or
- // the orientation of the keyguard. No point in searching from the rest of apps.
- WindowState winShowWhenLocked = (WindowState) policy.getWinShowWhenLockedLw();
- AppWindowToken appShowWhenLocked = winShowWhenLocked == null
- ? null : winShowWhenLocked.mAppToken;
- if (appShowWhenLocked != null) {
- int req = appShowWhenLocked.getOrientation();
- if (req == SCREEN_ORIENTATION_BEHIND) {
- req = mService.mLastKeyguardForcedOrientation;
- }
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Done at " + appShowWhenLocked
- + " -- show when locked, return " + req);
- return req;
- }
- if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
- "No one is requesting an orientation when the screen is locked");
+ if (policy.isKeyguardShowingAndNotOccluded()) {
return mService.mLastKeyguardForcedOrientation;
}
}
@@ -639,7 +610,7 @@
win.getTouchableRegion(mTmpRegion);
mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
}
- if (getDockedStackVisibleForUserLocked() != null) {
+ if (getDockedStackLocked() != null) {
mDividerControllerLocked.getTouchRegion(mTmpRect);
mTmpRegion.set(mTmpRect);
mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
@@ -991,11 +962,10 @@
/**
* Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not
- * visible, as long as it's not hidden because the current user doesn't have any tasks there.
+ * visible.
*/
- TaskStack getDockedStackVisibleForUserLocked() {
- final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
- return (stack != null && stack.isVisible(true /* ignoreKeyguard */)) ? stack : null;
+ TaskStack getDockedStackIgnoringVisibility() {
+ return mService.mStackIdToStack.get(DOCKED_STACK_ID);
}
/** Find the visible, touch-deliverable window under the given point */
@@ -2082,6 +2052,20 @@
}
}
+ /**
+ * Starts the Keyguard exit animation on all windows that don't belong to an app token.
+ */
+ void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) {
+ final WindowManagerPolicy policy = mService.mPolicy;
+ for (int i = mWindows.size() - 1; i >= 0; i--) {
+ final WindowState window = mWindows.get(i);
+ if (window.mAppToken == null && policy.canBeHiddenByKeyguardLw(window)) {
+ window.mWinAnimator.setAnimation(
+ policy.createHiddenByKeyguardExit(onWallpaper, goingToShade));
+ }
+ }
+ }
+
boolean checkWaitingForWindows() {
boolean haveBootMsg = false;
@@ -2137,59 +2121,10 @@
}
void updateWindowsForAnimator(WindowAnimator animator) {
- final WindowManagerPolicy policy = animator.mPolicy;
- final int keyguardGoingAwayFlags = animator.mKeyguardGoingAwayFlags;
- final boolean keyguardGoingAwayToShade =
- (keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0;
- final boolean keyguardGoingAwayNoAnimation =
- (keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0;
- final boolean keyguardGoingAwayWithWallpaper =
- (keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0;
-
- if (animator.mKeyguardGoingAway) {
- for (int i = mWindows.size() - 1; i >= 0; i--) {
- WindowState win = mWindows.get(i);
- if (!policy.isKeyguardHostWindow(win.mAttrs)) {
- continue;
- }
- final WindowStateAnimator winAnimator = win.mWinAnimator;
- if (policy.isKeyguardShowingAndNotOccluded()) {
- if (!winAnimator.mAnimating) {
- if (DEBUG_KEYGUARD) Slog.d(TAG,
- "updateWindowsForAnimator: creating delay animation");
-
- // Create a new animation to delay until keyguard is gone on its own.
- winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f);
- winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
- winAnimator.mAnimationIsEntrance = false;
- winAnimator.mAnimationStartTime = -1;
- winAnimator.mKeyguardGoingAwayAnimation = true;
- winAnimator.mKeyguardGoingAwayWithWallpaper
- = keyguardGoingAwayWithWallpaper;
- }
- } else {
- if (DEBUG_KEYGUARD) Slog.d(TAG,
- "updateWindowsForAnimator: StatusBar is no longer keyguard");
- animator.mKeyguardGoingAway = false;
- winAnimator.clearAnimation();
- }
- break;
- }
- }
-
- animator.mForceHiding = KEYGUARD_NOT_SHOWN;
-
- boolean wallpaperInUnForceHiding = false;
- boolean startingInUnForceHiding = false;
- ArrayList<WindowStateAnimator> unForceHiding = null;
- WindowState wallpaper = null;
final WallpaperController wallpaperController = mWallpaperController;
for (int i = mWindows.size() - 1; i >= 0; i--) {
WindowState win = mWindows.get(i);
WindowStateAnimator winAnimator = win.mWinAnimator;
- final int flags = win.mAttrs.flags;
- boolean canBeForceHidden = policy.canBeForceHidden(win, win.mAttrs);
- boolean shouldBeForceHidden = animator.shouldForceHide(win);
if (winAnimator.hasSurface()) {
final boolean wasAnimating = winAnimator.mWasAnimating;
final boolean nowAnimating = winAnimator.stepAnimationLocked(animator.mCurrentTime);
@@ -2208,129 +2143,6 @@
"updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
}
}
-
- if (policy.isForceHiding(win.mAttrs)) {
- if (!wasAnimating && nowAnimating) {
- if (DEBUG_KEYGUARD || DEBUG_ANIM || DEBUG_VISIBILITY) Slog.v(TAG,
- "Animation started that could impact force hide: " + win);
- animator.mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats(
- "updateWindowsAndWallpaperLocked 3", pendingLayoutChanges);
- }
- mService.mFocusMayChange = true;
- } else if (animator.mKeyguardGoingAway && !nowAnimating) {
- // Timeout!!
- Slog.e(TAG, "Timeout waiting for animation to startup");
- policy.startKeyguardExitAnimation(0, 0);
- animator.mKeyguardGoingAway = false;
- }
- if (win.isReadyForDisplay()) {
- if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) {
- animator.mForceHiding = KEYGUARD_ANIMATING_OUT;
- } else {
- animator.mForceHiding = win.isDrawnLw()
- ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
- }
- }
- if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
- "Force hide " + animator.forceHidingToString()
- + " hasSurface=" + win.mHasSurface
- + " policyVis=" + win.mPolicyVisibility
- + " destroying=" + win.mDestroying
- + " parentHidden=" + win.isParentWindowHidden()
- + " vis=" + win.mViewVisibility
- + " hidden=" + win.mToken.hidden
- + " anim=" + win.mWinAnimator.mAnimation);
- } else if (canBeForceHidden) {
- if (shouldBeForceHidden) {
- if (!win.hideLw(false, false)) {
- // Was already hidden
- continue;
- }
- if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
- "Now policy hidden: " + win);
- } else {
- final Animation postKeyguardExitAnimation =
- animator.mPostKeyguardExitAnimation;
- boolean applyExistingExitAnimation = postKeyguardExitAnimation != null
- && !postKeyguardExitAnimation.hasEnded()
- && !winAnimator.mKeyguardGoingAwayAnimation
- && win.hasDrawnLw()
- && !win.isChildWindow()
- && !win.mIsImWindow
- && isDefaultDisplay;
-
- // If the window is already showing and we don't need to apply an existing
- // Keyguard exit animation, skip.
- if (!win.showLw(false, false) && !applyExistingExitAnimation) {
- continue;
- }
- final boolean visibleNow = win.isVisibleNow();
- if (!visibleNow) {
- // Couldn't really show, must showLw() again when win becomes visible.
- win.hideLw(false, false);
- continue;
- }
- if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
- "Now policy shown: " + win);
- if ((animator.mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
- && !win.isChildWindow()) {
- if (unForceHiding == null) {
- unForceHiding = new ArrayList<>();
- }
- unForceHiding.add(winAnimator);
- if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
- wallpaperInUnForceHiding = true;
- }
- if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
- startingInUnForceHiding = true;
- }
- } else if (applyExistingExitAnimation) {
- // We're already in the middle of an animation. Use the existing
- // animation to bring in this window.
- if (DEBUG_KEYGUARD) Slog.v(TAG,
- "Applying existing Keyguard exit animation to new window: win="
- + win);
-
- final Animation a = policy.createForceHideEnterAnimation(false,
- keyguardGoingAwayToShade);
- winAnimator.setAnimation(a, postKeyguardExitAnimation.getStartTime(),
- STACK_CLIP_BEFORE_ANIM);
- winAnimator.mKeyguardGoingAwayAnimation = true;
- winAnimator.mKeyguardGoingAwayWithWallpaper
- = keyguardGoingAwayWithWallpaper;
- }
- final WindowState currentFocus = mService.mCurrentFocus;
- if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
- // We are showing on top of the current
- // focus, so re-evaluate focus to make
- // sure it is correct.
- if (DEBUG_FOCUS_LIGHT) Slog.v(TAG,
- "updateWindowsForAnimator: setting mFocusMayChange true");
- mService.mFocusMayChange = true;
- }
- }
- if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
- animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
- pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
- if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats(
- "updateWindowsAndWallpaperLocked 4", pendingLayoutChanges);
- }
- }
- }
- }
-
- // If the window doesn't have a surface, the only thing we care about is the correct
- // policy visibility.
- else if (canBeForceHidden) {
- if (shouldBeForceHidden) {
- win.hideLw(false, false);
- } else {
- win.showLw(false, false);
- }
}
final AppWindowToken atoken = win.mAppToken;
@@ -2355,77 +2167,7 @@
appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
}
}
- if (win.mIsWallpaper) {
- wallpaper = win;
- }
} // end forall windows
-
- // If we have windows that are being shown due to them no longer being force-hidden, apply
- // the appropriate animation to them if animations are not disabled.
- if (unForceHiding != null) {
- if (!keyguardGoingAwayNoAnimation) {
- boolean first = true;
- for (int i=unForceHiding.size()-1; i>=0; i--) {
- final WindowStateAnimator winAnimator = unForceHiding.get(i);
- final Animation a = policy.createForceHideEnterAnimation(
- wallpaperInUnForceHiding && !startingInUnForceHiding,
- keyguardGoingAwayToShade);
- if (a != null) {
- if (DEBUG_KEYGUARD) Slog.v(TAG,
- "Starting keyguard exit animation on window " + winAnimator.mWin);
- winAnimator.setAnimation(a, STACK_CLIP_BEFORE_ANIM);
- winAnimator.mKeyguardGoingAwayAnimation = true;
- winAnimator.mKeyguardGoingAwayWithWallpaper
- = keyguardGoingAwayWithWallpaper;
- if (first) {
- animator.mPostKeyguardExitAnimation = a;
- animator.mPostKeyguardExitAnimation.setStartTime(animator.mCurrentTime);
- first = false;
- }
- }
- }
- } else if (animator.mKeyguardGoingAway) {
- policy.startKeyguardExitAnimation(animator.mCurrentTime, 0 /* duration */);
- animator.mKeyguardGoingAway = false;
- }
-
-
- // Wallpaper is going away in un-force-hide motion, animate it as well.
- if (!wallpaperInUnForceHiding && wallpaper != null && !keyguardGoingAwayNoAnimation) {
- if (DEBUG_KEYGUARD) Slog.d(TAG,
- "updateWindowsForAnimator: wallpaper animating away");
- final Animation a = policy.createForceHideWallpaperExitAnimation(
- keyguardGoingAwayToShade);
- if (a != null) {
- wallpaper.mWinAnimator.setAnimation(a);
- }
- }
- }
-
- if (animator.mPostKeyguardExitAnimation != null) {
- // We're in the midst of a keyguard exit animation.
- if (animator.mKeyguardGoingAway) {
- policy.startKeyguardExitAnimation(animator.mCurrentTime +
- animator.mPostKeyguardExitAnimation.getStartOffset(),
- animator.mPostKeyguardExitAnimation.getDuration());
- animator.mKeyguardGoingAway = false;
- }
- // mPostKeyguardExitAnimation might either be ended normally, cancelled, or "orphaned",
- // meaning that the window it was running on was removed. We check for hasEnded() for
- // ended normally and cancelled case, and check the time for the "orphaned" case.
- else if (animator.mPostKeyguardExitAnimation.hasEnded()
- || animator.mCurrentTime - animator.mPostKeyguardExitAnimation.getStartTime()
- > animator.mPostKeyguardExitAnimation.getDuration()) {
- // Done with the animation, reset.
- if (DEBUG_KEYGUARD) Slog.v(TAG, "Done with Keyguard exit animations.");
- animator.mPostKeyguardExitAnimation = null;
- }
- }
-
- final WindowState winShowWhenLocked = (WindowState) policy.getWinShowWhenLockedLw();
- if (winShowWhenLocked != null) {
- animator.mLastShowWinWhenLocked = winShowWhenLocked;
- }
}
void updateWallpaperForAnimator(WindowAnimator animator) {
@@ -2591,18 +2333,12 @@
final WindowManagerPolicy policy = mService.mPolicy;
for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
final WindowState win = mWindows.get(winNdx);
- final boolean isForceHiding = policy.isForceHiding(win.mAttrs);
final boolean keyguard = policy.isKeyguardHostWindow(win.mAttrs);
- if (win.isVisibleLw() && (win.mAppToken != null || isForceHiding || keyguard)) {
+ if (win.isVisibleLw() && (win.mAppToken != null || keyguard)) {
win.mWinAnimator.mDrawState = DRAW_PENDING;
// Force add to mResizingWindows.
win.mLastContentInsets.set(-1, -1, -1, -1);
mService.mWaitingForDrawn.add(win);
-
- // No need to wait for the windows below Keyguard.
- if (isForceHiding) {
- return;
- }
}
}
}
@@ -2650,7 +2386,7 @@
if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
if (mService.updateOrientationFromAppTokensLocked(true, mDisplayId)) {
setLayoutNeeded();
- mService.mH.sendEmptyMessage(SEND_NEW_CONFIGURATION);
+ mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
}
}
@@ -2672,9 +2408,8 @@
mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
for (int i = mWindows.size() - 1; i >= 0; i--) {
final WindowState w = mWindows.get(i);
- if (w.mHasSurface) {
- mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow());
- }
+ mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
+ mService.mInputMethodTarget);
}
pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
@@ -2855,7 +2590,7 @@
// Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
// wasting time and funky changes while a window is animating away.
- final boolean gone = (behindDream && mService.mPolicy.canBeForceHidden(win, win.mAttrs))
+ final boolean gone = (behindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win))
|| win.isGoneForLayoutLw();
if (DEBUG_LAYOUT && !win.mLayoutAttached) {
@@ -2927,7 +2662,7 @@
// If this view is GONE, then skip it -- keep the current frame, and let the caller
// know so they can ignore it if they want. (We do the normal layout for INVISIBLE
// windows, since that means "perform layout as normal, just don't display").
- if (attachedBehindDream && mService.mPolicy.canBeForceHidden(win, win.mAttrs)) {
+ if (attachedBehindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win)) {
continue;
}
if ((win.mViewVisibility != GONE && win.mRelayoutCalled) || !win.mHaveFrame
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 530fb1b..743caf8 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -44,7 +44,6 @@
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.IDockedStackListener;
-import android.view.SurfaceControl;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
@@ -57,7 +56,6 @@
import com.android.server.wm.WindowManagerService.H;
import java.io.PrintWriter;
-import java.util.ArrayList;
/**
* Keeps information about the docked stack divider.
@@ -283,7 +281,7 @@
if (mWindow == null) {
return;
}
- TaskStack stack = mDisplayContent.mService.mStackIdToStack.get(DOCKED_STACK_ID);
+ TaskStack stack = mDisplayContent.getDockedStackIgnoringVisibility();
// If the stack is invisible, we policy force hide it in WindowAnimator.shouldForceHide
final boolean visible = stack != null;
@@ -536,7 +534,7 @@
}
private void checkMinimizeChanged(boolean animate) {
- if (mDisplayContent.getDockedStackVisibleForUserLocked() == null) {
+ if (mDisplayContent.getDockedStackIgnoringVisibility() == null) {
return;
}
final TaskStack homeStack = mDisplayContent.getHomeStack();
@@ -683,7 +681,7 @@
}
private boolean setMinimizedDockedStack(boolean minimized) {
- final TaskStack stack = mDisplayContent.getDockedStackVisibleForUserLocked();
+ final TaskStack stack = mDisplayContent.getDockedStackIgnoringVisibility();
notifyDockedStackMinimizedChanged(minimized, 0);
return stack != null && stack.setAdjustedForMinimizedDock(minimized ? 1f : 0f);
}
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index a28dc10..26f79a9 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -483,6 +483,7 @@
appToken.voiceInteraction);
mService.mOpeningApps.remove(appToken);
+ mService.mUnknownAppVisibilityController.appRemoved(appToken);
appToken.waitingToShow = false;
if (mService.mClosingApps.contains(appToken)) {
delayed = true;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7f543f9..b889db2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -350,7 +350,7 @@
return mFillsParent
|| !StackId.isTaskResizeableByDockedStack(mStack.mStackId)
|| displayContent == null
- || displayContent.getDockedStackVisibleForUserLocked() != null;
+ || displayContent.getDockedStackIgnoringVisibility() != null;
}
/** Original bounds of the task if applicable, otherwise fullscreen rect. */
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 4d8f29d..fff2981 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -871,7 +871,7 @@
mAdjustImeAmount = adjustAmount;
mAdjustDividerAmount = adjustDividerAmount;
updateAdjustedBounds();
- return isVisible(true /* ignoreKeyguard */);
+ return isVisible();
} else {
return false;
}
@@ -907,7 +907,7 @@
if (minimizeAmount != mMinimizeAmount) {
mMinimizeAmount = minimizeAmount;
updateAdjustedBounds();
- return isVisible(true /* ignoreKeyguard */);
+ return isVisible();
} else {
return false;
}
@@ -1218,21 +1218,6 @@
}
}
- boolean isVisible() {
- return isVisible(false /* ignoreKeyguard */);
- }
-
- boolean isVisible(boolean ignoreKeyguard) {
- final boolean keyguardOn = mService.mPolicy.isKeyguardShowingOrOccluded()
- && !mService.mAnimator.mKeyguardGoingAway;
- if (!ignoreKeyguard && keyguardOn && !StackId.isAllowedOverLockscreen(mStackId)) {
- // The keyguard is showing and the stack shouldn't show on top of the keyguard.
- return false;
- }
-
- return super.isVisible();
- }
-
boolean hasTaskForUser(int userId) {
for (int i = mChildren.size() - 1; i >= 0; i--) {
final Task task = mChildren.get(i);
diff --git a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
new file mode 100644
index 0000000..2f49c82
--- /dev/null
+++ b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import android.annotation.NonNull;
+import android.util.ArrayMap;
+
+import com.android.server.wm.WindowManagerService.H;
+
+import java.io.PrintWriter;
+
+/**
+ * Manages the set of {@link AppWindowToken}s for which we don't know yet whether it's visible or
+ * not. This happens when starting an activity while the lockscreen is showing. In that case, the
+ * keyguard flags an app might set influence it's visibility, so we wait until this is resolved to
+ * start the transition to avoid flickers.
+ */
+class UnknownAppVisibilityController {
+
+ /**
+ * We are currently waiting until the app is done resuming.
+ */
+ private static final int UNKNOWN_STATE_WAITING_RESUME = 1;
+
+ /**
+ * The activity has finished resuming, and we are waiting on the next relayout.
+ */
+ private static final int UNKNOWN_STATE_WAITING_RELAYOUT = 2;
+
+ /**
+ * The client called {@link Session#relayout} with the appropriate Keyguard flags and we are
+ * waiting until activity manager has updated the visibilities of all the apps.
+ */
+ private static final int UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE = 3;
+
+ // Set of apps for which we don't know yet whether it's visible or not, depending on what kind
+ // of lockscreen flags the app might set during its first relayout.
+ private final ArrayMap<AppWindowToken, Integer> mUnknownApps = new ArrayMap<>();
+
+ private final WindowManagerService mService;
+
+ UnknownAppVisibilityController(WindowManagerService service) {
+ mService = service;
+ }
+
+ boolean allResolved() {
+ return mUnknownApps.isEmpty();
+ }
+
+ void clear() {
+ mUnknownApps.clear();
+ }
+
+ String getDebugMessage() {
+ final StringBuilder builder = new StringBuilder();
+ for (int i = mUnknownApps.size() - 1; i >= 0; i--) {
+ builder.append("app=").append(mUnknownApps.keyAt(i))
+ .append(" state=").append(mUnknownApps.valueAt(i));
+ if (i != 0) {
+ builder.append(' ');
+ }
+ }
+ return builder.toString();
+ }
+
+ void appRemoved(@NonNull AppWindowToken appWindow) {
+ mUnknownApps.remove(appWindow);
+ }
+
+ /**
+ * Notifies that {@param appWindow} has been launched behind Keyguard, and we need to wait until
+ * it is resumed and relaid out to resolve the visibility.
+ */
+ void notifyLaunched(@NonNull AppWindowToken appWindow) {
+ mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_RESUME);
+ }
+
+ /**
+ * Notifies that {@param appWindow} has finished resuming.
+ */
+ void notifyAppResumedFinished(@NonNull AppWindowToken appWindow) {
+ if (mUnknownApps.containsKey(appWindow)
+ && mUnknownApps.get(appWindow) == UNKNOWN_STATE_WAITING_RESUME) {
+ mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_RELAYOUT);
+ }
+ }
+
+ /**
+ * Notifies that {@param appWindow} has relaid out.
+ */
+ void notifyRelayouted(@NonNull AppWindowToken appWindow) {
+ if (!mUnknownApps.containsKey(appWindow)) {
+ return;
+ }
+ int state = mUnknownApps.get(appWindow);
+ if (state == UNKNOWN_STATE_WAITING_RELAYOUT) {
+ mUnknownApps.put(appWindow, UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE);
+ mService.notifyKeyguardFlagsChanged(this::notifyVisibilitiesUpdated);
+ }
+ }
+
+ private void notifyVisibilitiesUpdated() {
+ boolean changed = false;
+ for (int i = mUnknownApps.size() - 1; i >= 0; i--) {
+ if (mUnknownApps.valueAt(i) == UNKNOWN_STATE_WAITING_VISIBILITY_UPDATE) {
+ mUnknownApps.removeAt(i);
+ changed = true;
+ }
+ }
+ if (changed) {
+ mService.mWindowPlacerLocked.performSurfacePlacement();
+ }
+ }
+
+ void dump(PrintWriter pw, String prefix) {
+ if (mUnknownApps.isEmpty()) {
+ return;
+ }
+ pw.println(prefix + "Unknown visibilities:");
+ for (int i = mUnknownApps.size() - 1; i >= 0; i--) {
+ pw.println(prefix + " app=" + mUnknownApps.keyAt(i)
+ + " state=" + mUnknownApps.valueAt(i));
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index c9f1ffc..250d381 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -18,9 +18,12 @@
import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+
+import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
@@ -39,6 +42,7 @@
import android.util.Slog;
import android.view.DisplayInfo;
import android.view.WindowManager;
+import android.view.animation.Animation;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -126,6 +130,16 @@
return isWallpaperVisible(mWallpaperTarget);
}
+ /**
+ * Starts {@param a} on all wallpaper windows.
+ */
+ void startWallpaperAnimation(Animation a) {
+ for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
+ final WindowToken token = mWallpaperTokens.get(curTokenNdx);
+ token.startAnimation(a);
+ }
+ }
+
private boolean isWallpaperVisible(WindowState wallpaperTarget) {
if (DEBUG_WALLPAPER) Slog.v(TAG, "Wallpaper vis: target " + wallpaperTarget + ", obscured="
+ (wallpaperTarget != null ? Boolean.toString(wallpaperTarget.mObscured) : "??")
@@ -383,6 +397,7 @@
boolean inFreeformSpace = false;
boolean replacing = false;
boolean keyguardGoingAwayWithWallpaper = false;
+ boolean needsShowWhenLockedWallpaper = false;
for (int i = windows.size() - 1; i >= 0; i--) {
w = windows.get(i);
@@ -413,7 +428,19 @@
replacing |= w.mWillReplaceWindow;
keyguardGoingAwayWithWallpaper |= (w.mAppToken != null
- && w.mWinAnimator.mKeyguardGoingAwayWithWallpaper);
+ && AppTransition.isKeyguardGoingAwayTransit(
+ w.mAppToken.mAppAnimator.getTransit())
+ && (w.mAppToken.mAppAnimator.getTransitFlags()
+ & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0);
+
+ if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
+ && mService.mPolicy.isKeyguardLocked()
+ && mService.mPolicy.isKeyguardOccluded()) {
+ // The lowest show when locked window decides whether we need to put the wallpaper
+ // behind.
+ needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
+ || (w.mAppToken != null && !w.mAppToken.fillsParent());
+ }
final boolean hasWallpaper = (w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0;
if (hasWallpaper && w.isOnScreen() && (mWallpaperTarget == w || w.isDrawFinishedLw())) {
@@ -447,14 +474,19 @@
// appear and can determine the visibility, to avoid flickering.
result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
- } else if (keyguardGoingAwayWithWallpaper) {
- // If the app is executing an animation because the keyguard is going away (and the
- // keyguard was showing the wallpaper) keep the wallpaper during the animation so it
- // doesn't flicker out by having it be its own target.
+ } else if (keyguardGoingAwayWithWallpaper || needsShowWhenLockedWallpaper) {
+ // Keep the wallpaper during Keyguard exit but also when it's needed for a
+ // non-fullscreen show when locked activity.
result.setWallpaperTarget(result.topWallpaper, result.topWallpaperIndex);
}
}
+ private boolean isFullscreen(WindowManager.LayoutParams attrs) {
+ return attrs.x == 0 && attrs.y == 0
+ && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
+ && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
+ }
+
/** Updates the target wallpaper if needed and returns true if an update happened. */
private boolean updateWallpaperWindowsTarget(
ReadOnlyWindowList windows, FindWallpaperTargetResult result) {
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 4c62245..993a918 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -17,11 +17,7 @@
package com.android.server.wm;
import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
-import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
@@ -39,7 +35,6 @@
import android.view.Choreographer;
import android.view.SurfaceControl;
import android.view.WindowManagerPolicy;
-import android.view.animation.Animation;
import java.io.PrintWriter;
@@ -50,9 +45,6 @@
public class WindowAnimator {
private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowAnimator" : TAG_WM;
- /** How long to give statusbar to clear the private keyguard flag when animating out */
- static final long KEYGUARD_ANIM_TIMEOUT_MS = 1000;
-
final WindowManagerService mService;
final Context mContext;
final WindowManagerPolicy mPolicy;
@@ -86,37 +78,10 @@
boolean mInitialized = false;
- boolean mKeyguardGoingAway;
- int mKeyguardGoingAwayFlags;
- boolean mKeyguardAnimatingIn;
-
- /** Use one animation for all entering activities after keyguard is dismissed. */
- Animation mPostKeyguardExitAnimation;
-
- // forceHiding states.
- static final int KEYGUARD_NOT_SHOWN = 0;
- static final int KEYGUARD_SHOWN = 1;
- static final int KEYGUARD_ANIMATING_OUT = 2;
- int mForceHiding = KEYGUARD_NOT_SHOWN;
-
// When set to true the animator will go over all windows after an animation frame is posted and
// check if some got replaced and can be removed.
private boolean mRemoveReplacedWindows = false;
- private final AppTokenList mTmpExitingAppTokens = new AppTokenList();
-
- /** The window that was previously hiding the Keyguard. */
- WindowState mLastShowWinWhenLocked;
-
- String forceHidingToString() {
- switch (mForceHiding) {
- case KEYGUARD_NOT_SHOWN: return "KEYGUARD_NOT_SHOWN";
- case KEYGUARD_SHOWN: return "KEYGUARD_SHOWN";
- case KEYGUARD_ANIMATING_OUT:return "KEYGUARD_ANIMATING_OUT";
- default: return "KEYGUARD STATE UNKNOWN " + mForceHiding;
- }
- }
-
WindowAnimator(final WindowManagerService service) {
mService = service;
mContext = service.mContext;
@@ -153,63 +118,6 @@
mDisplayContentsAnimators.delete(displayId);
}
- /**
- * @return The window that is currently hiding the Keyguard, or if it was hiding the Keyguard,
- * and it's still animating.
- */
- private WindowState getWinShowWhenLockedOrAnimating() {
- final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
- if (winShowWhenLocked != null) {
- return winShowWhenLocked;
- }
- if (mLastShowWinWhenLocked != null && mLastShowWinWhenLocked.isOnScreen()
- && mLastShowWinWhenLocked.isAnimatingLw()
- && (mLastShowWinWhenLocked.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
- return mLastShowWinWhenLocked;
- }
- return null;
- }
-
- boolean shouldForceHide(WindowState win) {
- final WindowState imeTarget = mService.mInputMethodTarget;
- final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() &&
- ((imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0
- || !mPolicy.canBeForceHidden(imeTarget, imeTarget.mAttrs));
-
- final WindowState winShowWhenLocked = getWinShowWhenLockedOrAnimating();
- final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
- null : winShowWhenLocked.mAppToken;
-
- boolean allowWhenLocked = false;
- // Show IME over the keyguard if the target allows it
- allowWhenLocked |= (win.mIsImWindow || imeTarget == win) && showImeOverKeyguard;
- // Show SHOW_WHEN_LOCKED windows that turn on the screen
- allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.mTurnOnScreen;
-
- if (appShowWhenLocked != null) {
- allowWhenLocked |= appShowWhenLocked == win.mAppToken
- // Show all SHOW_WHEN_LOCKED windows if some apps are shown over lockscreen
- || (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
- // Show error dialogs over apps that are shown on lockscreen
- || (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
- }
-
- // Allow showing a window that dismisses Keyguard if the policy allows it. This is used for
- // when the policy knows that the Keyguard can be dismissed without user interaction to
- // provide a smooth transition in that case.
- allowWhenLocked |= (win.mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0
- && mPolicy.canShowDismissingWindowWhileLockedLw();
-
- // Only hide windows if the keyguard is active and not animating away.
- boolean keyguardOn = mPolicy.isKeyguardShowingOrOccluded()
- && mForceHiding != KEYGUARD_ANIMATING_OUT
- && !mKeyguardAnimatingIn;
- boolean hideDockDivider = win.mAttrs.type == TYPE_DOCK_DIVIDER
- && win.getDisplayContent().getDockedStackLocked() == null;
- return keyguardOn && !allowWhenLocked && (win.getDisplayId() == DEFAULT_DISPLAY)
- || hideDockDivider;
- }
-
/** Locked on mService.mWindowMap. */
private void animateLocked(long frameTimeNs) {
if (!mInitialized) {
@@ -388,7 +296,6 @@
if (dumpAll) {
pw.print(prefix); pw.print("mAnimTransactionSequence=");
pw.print(mAnimTransactionSequence);
- pw.print(" mForceHiding="); pw.println(forceHidingToString());
pw.print(prefix); pw.print("mCurrentTime=");
pw.println(TimeUtils.formatUptime(mCurrentTime));
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index db61c3e..e30ebcb 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -413,12 +413,6 @@
}
}
- void overridePlayingAppAnimations(Animation a) {
- for (int i = mChildren.size() - 1; i >= 0; i--) {
- mChildren.get(i).overridePlayingAppAnimations(a);
- }
- }
-
void setOrientation(int orientation) {
mOrientation = orientation;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 7759705..2fef928 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -178,10 +178,12 @@
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
@@ -218,7 +220,6 @@
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -518,8 +519,6 @@
int mLastOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
boolean mAltOrientation = false;
- private boolean mKeyguardWaitingForActivityDrawn;
-
int mDockedStackCreateMode = DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
Rect mDockedStackCreateBounds;
@@ -584,6 +583,9 @@
final ArraySet<AppWindowToken> mOpeningApps = new ArraySet<>();
final ArraySet<AppWindowToken> mClosingApps = new ArraySet<>();
+ final UnknownAppVisibilityController mUnknownAppVisibilityController =
+ new UnknownAppVisibilityController(this);
+
boolean mIsTouchDevice;
final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
@@ -889,7 +891,7 @@
= new WindowManagerInternal.AppTransitionListener() {
@Override
- public void onAppTransitionCancelledLocked() {
+ public void onAppTransitionCancelledLocked(int transit) {
mH.sendEmptyMessage(H.NOTIFY_APP_TRANSITION_CANCELLED);
}
@@ -1033,7 +1035,10 @@
mWindowAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
Settings.Global.WINDOW_ANIMATION_SCALE, mWindowAnimationScaleSetting);
mTransitionAnimationScaleSetting = Settings.Global.getFloat(context.getContentResolver(),
- Settings.Global.TRANSITION_ANIMATION_SCALE, mTransitionAnimationScaleSetting);
+ Settings.Global.TRANSITION_ANIMATION_SCALE,
+ context.getResources().getFloat(
+ R.dimen.config_appTransitionAnimationDurationScaleDefault));
+
setAnimatorDurationScale(Settings.Global.getFloat(context.getContentResolver(),
Settings.Global.ANIMATOR_DURATION_SCALE, mAnimatorDurationScaleSetting));
@@ -1923,6 +1928,10 @@
| WindowManager.LayoutParams.SYSTEM_UI_VISIBILITY_CHANGED)) != 0) {
win.mLayoutNeeded = true;
}
+ if (win.mAppToken != null && ((flagChanges & FLAG_SHOW_WHEN_LOCKED) != 0
+ || (flagChanges & FLAG_DISMISS_KEYGUARD) != 0)) {
+ win.mAppToken.checkKeyguardFlagsChanged();
+ }
}
if (DEBUG_LAYOUT) Slog.v(TAG_WM, "Relayout " + win + ": viewVisibility=" + viewVisibility
@@ -2066,6 +2075,10 @@
WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
}
+ if (win.mAppToken != null) {
+ mUnknownAppVisibilityController.notifyRelayouted(win.mAppToken);
+ }
+
win.setDisplayLayoutNeeded();
win.mGivenInsetsPending = (flags&WindowManagerGlobal.RELAYOUT_INSETS_PENDING) != 0;
configChanged = updateOrientationFromAppTokensLocked(false, displayId);
@@ -2348,8 +2361,10 @@
if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + atoken);
final int containingWidth = frame.width();
final int containingHeight = frame.height();
- atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight,
- mAppTransition.canSkipFirstFrame(), mAppTransition.getAppStackClipMode());
+ atoken.mAppAnimator.setAnimation(a, containingWidth, containingHeight, width,
+ height, mAppTransition.canSkipFirstFrame(),
+ mAppTransition.getAppStackClipMode(),
+ transit, mAppTransition.getTransitFlags());
}
} else {
atoken.mAppAnimator.clearAnimation();
@@ -2735,20 +2750,28 @@
}
}
+ @Override
+ public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
+ prepareAppTransition(transit, alwaysKeepCurrent, 0 /* flags */, false /* forceOverride */);
+ }
+
/**
* @param transit What kind of transition is happening. Use one of the constants
* AppTransition.TRANSIT_*.
* @param alwaysKeepCurrent If true and a transition is already set, new transition will NOT
* be set.
+ * @param flags Additional flags for the app transition, Use a combination of the constants
+ * AppTransition.TRANSIT_FLAG_*.
+ * @param forceOverride Always override the transit, not matter what was set previously.
*/
- @Override
- public void prepareAppTransition(int transit, boolean alwaysKeepCurrent) {
+ public void prepareAppTransition(int transit, boolean alwaysKeepCurrent, int flags,
+ boolean forceOverride) {
if (!checkCallingPermission(MANAGE_APP_TOKENS, "prepareAppTransition()")) {
throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
}
synchronized(mWindowMap) {
- boolean prepared = mAppTransition.prepareAppTransitionLocked(
- transit, alwaysKeepCurrent);
+ boolean prepared = mAppTransition.prepareAppTransitionLocked(transit, alwaysKeepCurrent,
+ flags, forceOverride);
if (prepared && okToDisplay()) {
mSkipAppTransitionAnimation = false;
}
@@ -3183,6 +3206,19 @@
}
}
+ /**
+ * Notifies that we launched an app that might be visible or not visible depending on what kind
+ * of Keyguard flags it's going to set on its windows.
+ */
+ public void notifyUnknownAppVisibilityLaunched(IBinder token) {
+ synchronized(mWindowMap) {
+ AppWindowToken appWindow = mRoot.getAppWindowToken(token);
+ if (appWindow != null) {
+ mUnknownAppVisibilityController.notifyLaunched(appWindow);
+ }
+ }
+ }
+
@Override
public void startAppFreezingScreen(IBinder token, int configChanges) {
if (!checkCallingPermission(MANAGE_APP_TOKENS, "setAppFreezingScreen()")) {
@@ -3472,8 +3508,8 @@
}
@Override
- public void overridePlayingAppAnimationsLw(Animation a) {
- getDefaultDisplayContentLocked().overridePlayingAppAnimations(a);
+ public void notifyShowingDreamChanged() {
+ notifyKeyguardFlagsChanged(null /* callback */);
}
/**
@@ -3613,6 +3649,46 @@
}
}
+ /**
+ * @return true if the activity contains windows that have
+ * {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set
+ */
+ public boolean containsShowWhenLockedWindow(IBinder token) {
+ synchronized (mWindowMap) {
+ final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
+ return wtoken != null && wtoken.containsShowWhenLockedWindow();
+ }
+ }
+
+ /**
+ * @return true if the activity contains windows that have
+ * {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set
+ */
+ public boolean containsDismissKeyguardWindow(IBinder token) {
+ synchronized (mWindowMap) {
+ final AppWindowToken wtoken = mRoot.getAppWindowToken(token);
+ return wtoken != null && wtoken.containsDismissKeyguardWindow();
+ }
+ }
+
+ /**
+ * Notifies activity manager that some Keyguard flags have changed and that it needs to
+ * reevaluate the visibilities of the activities.
+ * @param callback Runnable to be called when activity manager is done reevaluating visibilities
+ */
+ void notifyKeyguardFlagsChanged(@Nullable Runnable callback) {
+ final Runnable wrappedCallback = callback != null
+ ? () -> { synchronized (mWindowMap) { callback.run(); } }
+ : null;
+ mH.obtainMessage(H.NOTIFY_KEYGUARD_FLAGS_CHANGED, wrappedCallback).sendToTarget();
+ }
+
+ public boolean isKeyguardTrusted() {
+ synchronized (mWindowMap) {
+ return mPolicy.isKeyguardTrustedLw();
+ }
+ }
+
// -------------------------------------------------------------
// Misc IWindowSession methods
// -------------------------------------------------------------
@@ -3749,6 +3825,12 @@
}
}
+ public boolean isShowingDream() {
+ synchronized (mWindowMap) {
+ return mPolicy.isShowingDreamLw();
+ }
+ }
+
@Override
public void dismissKeyguard() {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
@@ -3762,51 +3844,11 @@
@Override
public void keyguardGoingAway(int flags) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Requires DISABLE_KEYGUARD permission");
- }
- if (DEBUG_KEYGUARD) Slog.d(TAG_WM,
- "keyguardGoingAway: flags=0x" + Integer.toHexString(flags));
- synchronized (mWindowMap) {
- mAnimator.mKeyguardGoingAway = true;
- mAnimator.mKeyguardGoingAwayFlags = flags;
- mWindowPlacerLocked.requestTraversal();
- }
}
- public void keyguardWaitingForActivityDrawn() {
- if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "keyguardWaitingForActivityDrawn");
+ public void onKeyguardOccludedChanged(boolean occluded) {
synchronized (mWindowMap) {
- mKeyguardWaitingForActivityDrawn = true;
- }
- }
-
- public void notifyActivityDrawnForKeyguard() {
- if (DEBUG_KEYGUARD) Slog.d(TAG_WM, "notifyActivityDrawnForKeyguard: waiting="
- + mKeyguardWaitingForActivityDrawn + " Callers=" + Debug.getCallers(5));
- synchronized (mWindowMap) {
- if (mKeyguardWaitingForActivityDrawn) {
- mPolicy.notifyActivityDrawnForKeyguardLw();
- mKeyguardWaitingForActivityDrawn = false;
- }
- }
- }
-
- @Override
- public void setKeyguardAnimatingIn(boolean animating) {
- if (!checkCallingPermission(Manifest.permission.CONTROL_KEYGUARD,
- "keyguardAnimatingIn()")) {
- throw new SecurityException("Requires CONTROL_KEYGUARD permission");
- }
- synchronized (mWindowMap) {
- mAnimator.mKeyguardAnimatingIn = animating;
- }
- }
-
- public boolean isKeyguardAnimatingIn() {
- synchronized (mWindowMap) {
- return mAnimator.mKeyguardAnimatingIn;
+ mPolicy.onKeyguardOccludedChangedLw(occluded);
}
}
@@ -6011,7 +6053,7 @@
public static final int NOTIFY_DOCKED_STACK_MINIMIZED_CHANGED = 53;
public static final int SEAMLESS_ROTATION_TIMEOUT = 54;
public static final int RESTORE_POINTER_ICON = 55;
-
+ public static final int NOTIFY_KEYGUARD_FLAGS_CHANGED = 56;
/**
* Used to denote that an integer field in a message will not be used.
@@ -6647,6 +6689,9 @@
}
}
break;
+ case NOTIFY_KEYGUARD_FLAGS_CHANGED: {
+ mAmInternal.notifyKeyguardFlagsChanged((Runnable) msg.obj);
+ }
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG_WM, "handleMessage: exit");
@@ -7685,6 +7730,15 @@
}
}
+ public void notifyAppResumedFinished(IBinder token) {
+ synchronized (mWindowMap) {
+ final AppWindowToken appWindow = mRoot.getAppWindowToken(token);
+ if (appWindow != null) {
+ mUnknownAppVisibilityController.notifyAppResumedFinished(appWindow);
+ }
+ }
+ }
+
@Override
public int getDockedDividerInsetsLw() {
return getDefaultDisplayContentLocked().getDockedDividerController().getContentInsets();
@@ -7875,6 +7929,7 @@
pw.println();
mInputMonitor.dump(pw, " ");
+ mUnknownAppVisibilityController.dump(pw, " ");
if (dumpAll) {
pw.print(" mSystemDecorLayer="); pw.print(mSystemDecorLayer);
@@ -8313,7 +8368,7 @@
public int getDockedStackSide() {
synchronized (mWindowMap) {
final TaskStack dockedStack = getDefaultDisplayContentLocked()
- .getDockedStackVisibleForUserLocked();
+ .getDockedStackIgnoringVisibility();
return dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide();
}
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 59caa14..534a3d2 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -87,6 +87,7 @@
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
@@ -1030,6 +1031,10 @@
return mVisibleFrame;
}
+ Rect getStableFrameLw() {
+ return mStableFrame;
+ }
+
@Override
public boolean getGivenInsetsPendingLw() {
return mGivenInsetsPending;
@@ -1207,7 +1212,8 @@
return displayContent != null ? displayContent.getDisplayInfo() : null;
}
- int getDisplayId() {
+ @Override
+ public int getDisplayId() {
final DisplayContent displayContent = getDisplayContent();
if (displayContent == null) {
return -1;
@@ -2707,13 +2713,7 @@
return false;
}
- Task task = getTask();
- if (task == null || task.inHomeStack()) {
- // Don't save surfaces for home stack apps. These usually resume and draw
- // first frame very fast. Saving surfaces are mostly a waste of memory.
- return false;
- }
-
+ final Task task = getTask();
final AppWindowToken taskTop = task.getTopVisibleAppToken();
if (taskTop != null && taskTop != mAppToken) {
// Don't save if the window is not the topmost window.
@@ -3747,6 +3747,7 @@
return null;
}
+ @Override
public int getRotationAnimationHint() {
if (mAppToken != null) {
return mAppToken.mRotationAnimationHint;
@@ -3755,6 +3756,11 @@
}
}
+ @Override
+ public boolean isInputMethodWindow() {
+ return mIsImWindow;
+ }
+
// This must be called while inside a transaction.
boolean performShowLocked() {
if (isHiddenFromUserLocked()) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 2aeb50b..a428cce 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -187,9 +187,6 @@
private boolean mAnimationStartDelayed;
- boolean mKeyguardGoingAwayAnimation;
- boolean mKeyguardGoingAwayWithWallpaper;
-
/** The pixel format of the underlying SurfaceControl */
int mSurfaceFormat;
@@ -294,8 +291,6 @@
mLocalAnimating = false;
mAnimation.cancel();
mAnimation = null;
- mKeyguardGoingAwayAnimation = false;
- mKeyguardGoingAwayWithWallpaper = false;
mStackClip = STACK_CLIP_BEFORE_ANIM;
}
}
@@ -451,8 +446,6 @@
+ (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false));
mAnimating = false;
- mKeyguardGoingAwayAnimation = false;
- mKeyguardGoingAwayWithWallpaper = false;
mLocalAnimating = false;
if (mAnimation != null) {
mAnimation.cancel();
@@ -1268,11 +1261,6 @@
return;
}
- final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
- if (w == winShowWhenLocked && mPolicy.isKeyguardShowingOrOccluded()) {
- return;
- }
-
final TaskStack stack = task.mStack;
stack.getDimBounds(mTmpStackBounds);
final Rect surfaceInsets = w.getAttrs().surfaceInsets;
@@ -1688,17 +1676,9 @@
* @return true if an animation has been loaded.
*/
boolean applyAnimationLocked(int transit, boolean isEntrance) {
- if ((mLocalAnimating && mAnimationIsEntrance == isEntrance)
- || mKeyguardGoingAwayAnimation) {
+ if (mLocalAnimating && mAnimationIsEntrance == isEntrance) {
// If we are trying to apply an animation, but already running
// an animation of the same type, then just leave that one alone.
-
- // If we are in a keyguard exit animation, and the window should animate away, modify
- // keyguard exit animation such that it also fades out.
- if (mAnimation != null && mKeyguardGoingAwayAnimation
- && transit == WindowManagerPolicy.TRANSIT_PREVIEW_DONE) {
- applyFadeoutDuringKeyguardExitAnimation();
- }
return true;
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 63820e5..f2682ba 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -11,6 +11,11 @@
import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_CLOSE;
import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
+import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION;
+import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE;
+import static com.android.server.wm.AppTransition.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER;
+import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_GOING_AWAY;
+import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_CLOSE;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_IN_PLACE;
import static com.android.server.wm.AppTransition.TRANSIT_TASK_OPEN;
@@ -347,13 +352,16 @@
final AppWindowAnimator closingAppAnimator = (topClosingApp == null) ? null :
topClosingApp.mAppAnimator;
- mService.mAppTransition.goodToGo(openingAppAnimator, closingAppAnimator,
- mService.mOpeningApps, mService.mClosingApps);
+ final int flags = mService.mAppTransition.getTransitFlags();
+ int layoutRedo = mService.mAppTransition.goodToGo(transit, openingAppAnimator,
+ closingAppAnimator, mService.mOpeningApps, mService.mClosingApps);
+ handleNonAppWindowsInTransition(transit, flags);
mService.mAppTransition.postAnimationCallback();
mService.mAppTransition.clear();
mService.mOpeningApps.clear();
mService.mClosingApps.clear();
+ mService.mUnknownAppVisibilityController.clear();
// This has changed the visibility of windows, so perform
// a new layout to get them all up-to-date.
@@ -369,11 +377,10 @@
mService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
true /*updateInputWindows*/);
mService.mFocusMayChange = false;
- mService.notifyActivityDrawnForKeyguard();
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
- return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;
+ return layoutRedo | FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;
}
private AppWindowToken handleOpeningApps(int transit, LayoutParams animLp,
@@ -472,6 +479,26 @@
}
}
+ private void handleNonAppWindowsInTransition(int transit, int flags) {
+ if (transit == TRANSIT_KEYGUARD_GOING_AWAY) {
+ if ((flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_WITH_WALLPAPER) != 0
+ && (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0) {
+ Animation anim = mService.mPolicy.createKeyguardWallpaperExit(
+ (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0);
+ if (anim != null) {
+ mService.getDefaultDisplayContentLocked().mWallpaperController
+ .startWallpaperAnimation(anim);
+ }
+ }
+ }
+ if (transit == TRANSIT_KEYGUARD_GOING_AWAY
+ || transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER) {
+ mService.getDefaultDisplayContentLocked().startKeyguardExitOnNonAppWindows(
+ transit == TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER,
+ (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY_TO_SHADE) != 0);
+ }
+ }
+
private boolean transitionGoodToGo(int appsCount) {
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
"Checking " + appsCount + " opening apps (frozen="
@@ -529,6 +556,14 @@
return false;
}
+ if (!mService.mUnknownAppVisibilityController.allResolved()) {
+ if (DEBUG_APP_TRANSITIONS) {
+ Slog.v(TAG, "unknownApps is not empty: "
+ + mService.mUnknownAppVisibilityController.getDebugMessage());
+ }
+ return false;
+ }
+
// If the wallpaper is visible, we need to check it's ready too.
boolean wallpaperReady = !mWallpaperControllerLocked.isWallpaperVisible() ||
mWallpaperControllerLocked.wallpaperTransitionReady();
@@ -551,6 +586,7 @@
? null : wallpaperTarget;
final ArraySet<AppWindowToken> openingApps = mService.mOpeningApps;
final ArraySet<AppWindowToken> closingApps = mService.mClosingApps;
+ boolean openingCanBeWallpaperTarget = canBeWallpaperTarget(openingApps);
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
"New wallpaper target=" + wallpaperTarget
+ ", oldWallpaper=" + oldWallpaper
@@ -575,6 +611,10 @@
}
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
"New transit: " + AppTransition.appTransitionToString(transit));
+ } else if (openingCanBeWallpaperTarget && transit == TRANSIT_KEYGUARD_GOING_AWAY) {
+ transit = TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+ if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
+ "New transit: " + AppTransition.appTransitionToString(transit));
} else if (oldWallpaper != null && !mService.mOpeningApps.isEmpty()
&& !openingApps.contains(oldWallpaper.mAppToken)
&& closingApps.contains(oldWallpaper.mAppToken)) {
@@ -595,6 +635,15 @@
return transit;
}
+ private boolean canBeWallpaperTarget(ArraySet<AppWindowToken> apps) {
+ for (int i = apps.size() - 1; i >= 0; i--) {
+ if (apps.valueAt(i).windowsCanBeWallpaperTarget()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void processApplicationsAnimatingInPlace(int transit) {
if (transit == TRANSIT_TASK_IN_PLACE) {
// Find the focused window
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 38f25e0..cf1a98a 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -16,20 +16,11 @@
package com.android.server.wm;
-import android.os.Bundle;
-import android.os.Debug;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
-import android.view.DisplayInfo;
-
-import java.io.PrintWriter;
import java.util.Comparator;
-
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
+
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
@@ -39,6 +30,16 @@
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
+import android.os.Bundle;
+import android.os.Debug;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Slog;
+import android.view.DisplayInfo;
+import android.view.animation.Animation;
+
+import java.io.PrintWriter;
+
/**
* Container of a set of related windows in the window manager. Often this is an AppWindowToken,
* which is the handle for an Activity that it uses to display windows. For nested windows, there is
@@ -337,6 +338,16 @@
}
}
+ /**
+ * Starts {@param anim} on all children.
+ */
+ void startAnimation(Animation anim) {
+ for (int ndx = mChildren.size() - 1; ndx >= 0; ndx--) {
+ final WindowState windowState = mChildren.get(ndx);
+ windowState.mWinAnimator.setAnimation(anim);
+ }
+ }
+
boolean updateWallpaperWindowsPlacement(ReadOnlyWindowList windowList,
WindowState wallpaperTarget, int wallpaperTargetIndex, boolean visible, int dw, int dh,
int wallpaperAnimLayerAdj) {
@@ -390,10 +401,8 @@
// is currently on screen, i.e. not hidden by policy.
int insertionIndex = 0;
if (visible && wallpaperTarget != null) {
- final int type = wallpaperTarget.mAttrs.type;
final int privateFlags = wallpaperTarget.mAttrs.privateFlags;
- if (((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 || type == TYPE_KEYGUARD_SCRIM)
- && !mService.isKeyguardAnimatingIn()) {
+ if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
insertionIndex = Math.min(windowList.indexOf(wallpaperTarget),
findLowestWindowOnScreen(windowList));
}
diff --git a/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 5fe000a..4570a4b 100644
--- a/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -229,7 +229,8 @@
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, id, mTag, mUid, mPid,
mScore, n, mUser, System.currentTimeMillis());
NotificationRecord r = new NotificationRecord(getContext(), sbn,
- new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "misc"));
+ new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "misc",
+ NotificationManager.IMPORTANCE_DEFAULT));
mService.addNotification(r);
return r;
}
@@ -334,7 +335,7 @@
@Test
public void testBeepFromChannel() throws Exception {
NotificationRecord r = getQuietNotification();
- r.getChannel().setDefaultRingtone(Settings.System.DEFAULT_NOTIFICATION_URI);
+ r.getChannel().setRingtone(Settings.System.DEFAULT_NOTIFICATION_URI);
r.setImportance(NotificationManager.IMPORTANCE_DEFAULT, "for testing");
mService.buzzBeepBlinkLocked(r);
@@ -388,7 +389,7 @@
@Test
public void testChannelNoOverwriteCustomBeep() throws Exception {
NotificationRecord r = getCustomBeepyNotification();
- r.getChannel().setDefaultRingtone(Settings.System.DEFAULT_RINGTONE_URI);
+ r.getChannel().setRingtone(Settings.System.DEFAULT_RINGTONE_URI);
mService.buzzBeepBlinkLocked(r);
@@ -408,7 +409,7 @@
@Test
public void testNoInterruptionForMin() throws Exception {
NotificationRecord r = getBeepyNotification();
- r.setImportance(Ranking.IMPORTANCE_MIN, "foo");
+ r.setImportance(NotificationManager.IMPORTANCE_MIN, "foo");
mService.buzzBeepBlinkLocked(r);
diff --git a/services/tests/servicestests/src/com/android/server/notification/ImportanceExtractorTest.java b/services/tests/servicestests/src/com/android/server/notification/ImportanceExtractorTest.java
index 3cbde1d..305b5e0 100644
--- a/services/tests/servicestests/src/com/android/server/notification/ImportanceExtractorTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/ImportanceExtractorTest.java
@@ -90,8 +90,8 @@
when(mConfig.getImportance(anyString(), anyInt())).thenReturn(
NotificationManager.IMPORTANCE_MIN);
- NotificationChannel channel = new NotificationChannel("a", "a");
- channel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
+ NotificationChannel channel =
+ new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
NotificationRecord r = getNotificationRecord(channel);
@@ -107,8 +107,8 @@
when(mConfig.getImportance(anyString(), anyInt())).thenReturn(
NotificationManager.IMPORTANCE_MIN);
- NotificationChannel channel = new NotificationChannel("a", "a");
- channel.setImportance(NotificationManager.IMPORTANCE_HIGH);
+ NotificationChannel channel =
+ new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_HIGH);
NotificationRecord r = getNotificationRecord(channel);
@@ -124,8 +124,8 @@
when(mConfig.getImportance(anyString(), anyInt())).thenReturn(
NotificationManager.IMPORTANCE_HIGH);
- NotificationChannel channel = new NotificationChannel("a", "a");
- channel.setImportance(NotificationManager.IMPORTANCE_MIN);
+ NotificationChannel channel =
+ new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_MIN);
NotificationRecord r = getNotificationRecord(channel);
@@ -141,8 +141,8 @@
when(mConfig.getImportance(anyString(), anyInt())).thenReturn(
NotificationManager.IMPORTANCE_UNSPECIFIED);
- NotificationChannel channel = new NotificationChannel("a", "a");
- channel.setImportance(NotificationManager.IMPORTANCE_MIN);
+ NotificationChannel channel =
+ new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_MIN);
NotificationRecord r = getNotificationRecord(channel);
@@ -158,8 +158,8 @@
when(mConfig.getImportance(anyString(), anyInt())).thenReturn(
NotificationManager.IMPORTANCE_UNSPECIFIED);
- NotificationChannel channel = new NotificationChannel("a", "a");
- channel.setImportance(NotificationManager.IMPORTANCE_UNSPECIFIED);
+ NotificationChannel channel =
+ new NotificationChannel("a", "a", NotificationManager.IMPORTANCE_UNSPECIFIED);
NotificationRecord r = getNotificationRecord(channel);
diff --git a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
index ee33dcc..ad432d1 100644
--- a/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/RankingHelperTest.java
@@ -29,7 +29,10 @@
import android.content.Context;
import android.app.NotificationChannel;
import android.app.NotificationManager;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.net.Uri;
+import android.os.Build;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.support.test.InstrumentationRegistry;
@@ -44,14 +47,19 @@
import java.util.ArrayList;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.when;
@SmallTest
@RunWith(AndroidJUnit4.class)
public class RankingHelperTest {
@Mock NotificationUsageStats mUsageStats;
@Mock RankingHandler handler;
+ @Mock PackageManager mPm;
private Notification mNotiGroupGSortA;
private Notification mNotiGroupGSortB;
@@ -64,6 +72,8 @@
private NotificationRecord mRecordNoGroup2;
private NotificationRecord mRecordNoGroupSortA;
private RankingHelper mHelper;
+ private final String pkg = "com.android.server.notification";
+ private final int uid = 0;
private Context getContext() {
return InstrumentationRegistry.getTargetContext();
@@ -74,7 +84,7 @@
MockitoAnnotations.initMocks(this);
UserHandle user = UserHandle.ALL;
- mHelper = new RankingHelper(getContext(), handler, mUsageStats,
+ mHelper = new RankingHelper(getContext(), mPm, handler, mUsageStats,
new String[] {ImportanceExtractor.class.getName()});
mNotiGroupGSortA = new Notification.Builder(getContext())
@@ -121,11 +131,36 @@
mRecordNoGroupSortA = new NotificationRecord(getContext(), new StatusBarNotification(
"package", "package", 1, null, 0, 0, 0, mNotiNoGroupSortA, user),
getDefaultChannel());
+
+ final ApplicationInfo legacy = new ApplicationInfo();
+ legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
+ try {
+ when(mPm.getApplicationInfo(anyString(), anyInt())).thenReturn(legacy);
+ } catch (PackageManager.NameNotFoundException e) {}
}
private NotificationChannel getDefaultChannel() {
- return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name");
- }
+ return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
+ NotificationManager.IMPORTANCE_LOW);
+ }
+
+ private ByteArrayOutputStream writeXmlAndPurge(String pkg, int uid, String... channelIds)
+ throws Exception {
+ XmlSerializer serializer = new FastXmlSerializer();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+ serializer.startDocument(null, true);
+ serializer.startTag(null, "ranking");
+ mHelper.writeXml(serializer, false);
+ serializer.endTag(null, "ranking");
+ serializer.endDocument();
+ serializer.flush();
+
+ for (String channelId : channelIds) {
+ mHelper.deleteNotificationChannel(pkg, uid, channelId);
+ }
+ return baos;
+ }
@Test
public void testFindAfterRankingWithASplitGroup() throws Exception {
@@ -179,12 +214,11 @@
@Test
public void testChannelXml() throws Exception {
- String pkg = "com.android.server.notification";
- int uid = 0;
- NotificationChannel channel1 = new NotificationChannel("id1", "name1");
- NotificationChannel channel2 = new NotificationChannel("id2", "name2");
- channel2.setImportance(NotificationManager.IMPORTANCE_LOW);
- channel2.setDefaultRingtone(new Uri.Builder().scheme("test").build());
+ NotificationChannel channel1 =
+ new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
+ NotificationChannel channel2 =
+ new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ channel2.setRingtone(new Uri.Builder().scheme("test").build());
channel2.setLights(true);
channel2.setBypassDnd(true);
channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
@@ -192,23 +226,16 @@
mHelper.createNotificationChannel(pkg, uid, channel1);
mHelper.createNotificationChannel(pkg, uid, channel2);
- byte[] data;
- XmlSerializer serializer = new FastXmlSerializer();
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
- serializer.startDocument(null, true);
- serializer.startTag(null, "ranking");
- mHelper.writeXml(serializer, false);
- serializer.endTag(null, "ranking");
- serializer.endDocument();
- serializer.flush();
+ ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(), channel2.getId(),
+ NotificationChannel.DEFAULT_CHANNEL_ID);
mHelper.deleteNotificationChannel(pkg, uid, channel1.getId());
mHelper.deleteNotificationChannel(pkg, uid, channel2.getId());
mHelper.deleteNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
XmlPullParser parser = Xml.newPullParser();
- parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())), null);
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
+ null);
parser.nextTag();
mHelper.readXml(parser, false);
@@ -217,4 +244,146 @@
assertNotNull(
mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID));
}
+
+ @Test
+ public void testChannelXml_defaultChannelLegacyApp_noUserSettings() throws Exception {
+ NotificationChannel channel1 =
+ new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_DEFAULT);
+
+ mHelper.createNotificationChannel(pkg, uid, channel1);
+
+ ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(),
+ NotificationChannel.DEFAULT_CHANNEL_ID);
+
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
+ null);
+ parser.nextTag();
+ mHelper.readXml(parser, false);
+
+ final NotificationChannel updated =
+ mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+ assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance());
+ assertFalse(updated.canBypassDnd());
+ assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,updated.getLockscreenVisibility());
+ assertEquals(0, updated.getUserLockedFields());
+ }
+
+ @Test
+ public void testChannelXml_defaultChannelUpdatedApp() throws Exception {
+ final ApplicationInfo updated = new ApplicationInfo();
+ updated.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
+ when(mPm.getApplicationInfo(anyString(), anyInt())).thenReturn(updated);
+
+ NotificationChannel channel1 =
+ new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_MIN);
+
+ mHelper.createNotificationChannel(pkg, uid, channel1);
+
+ ByteArrayOutputStream baos = writeXmlAndPurge(pkg, uid, channel1.getId(),
+ NotificationChannel.DEFAULT_CHANNEL_ID);
+
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
+ null);
+ parser.nextTag();
+ mHelper.readXml(parser, false);
+
+ assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel(
+ pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID).getImportance());
+ }
+
+ // TODO: test with hardcoded N xml.
+ @Test
+ public void testChannelXml_upgradeCreateDefaultChannel() throws Exception {
+ mHelper.setImportance(pkg, uid, NotificationManager.IMPORTANCE_HIGH);
+ mHelper.setPriority(pkg, uid, Notification.PRIORITY_MAX);
+ mHelper.setVisibilityOverride(pkg, uid, Notification.VISIBILITY_SECRET);
+ // pre-O xml won't have channels.
+ mHelper.deleteNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+
+ ByteArrayOutputStream baos =
+ writeXmlAndPurge(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
+ null);
+ parser.nextTag();
+ mHelper.readXml(parser, false);
+
+ final NotificationChannel updated =
+ mHelper.getNotificationChannel(pkg, uid, NotificationChannel.DEFAULT_CHANNEL_ID);
+ assertEquals(NotificationManager.IMPORTANCE_HIGH, updated.getImportance());
+ assertTrue(updated.canBypassDnd());
+ assertEquals(Notification.VISIBILITY_SECRET, updated.getLockscreenVisibility());
+ assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE
+ | NotificationChannel.USER_LOCKED_PRIORITY
+ | NotificationChannel.USER_LOCKED_VISIBILITY, updated.getUserLockedFields());
+ }
+
+ // TODO: test lock individually.
+ @Test
+ public void testUpdate_userLockedChannelFields() throws Exception {
+ // all fields locked by user
+ final NotificationChannel channel =
+ new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ channel.setRingtone(new Uri.Builder().scheme("test").build());
+ channel.setLights(true);
+ channel.setBypassDnd(true);
+ channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+ channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE
+ | NotificationChannel.USER_LOCKED_VISIBILITY
+ | NotificationChannel.USER_LOCKED_VIBRATION
+ | NotificationChannel.USER_LOCKED_LIGHTS
+ | NotificationChannel.USER_LOCKED_PRIORITY
+ | NotificationChannel.USER_LOCKED_RINGTONE);
+
+ mHelper.createNotificationChannel(pkg, uid, channel);
+
+ // same id, try to update all fields
+ final NotificationChannel channel2 =
+ new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+ channel2.setRingtone(new Uri.Builder().scheme("test2").build());
+ channel2.setLights(false);
+ channel2.setBypassDnd(false);
+ channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
+
+ mHelper.updateNotificationChannelFromRanker(pkg, uid, channel2);
+
+ // no fields should be changed
+ assertEquals(channel, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+ }
+
+ @Test
+ public void testUpdate() throws Exception {
+ // no fields locked by user
+ final NotificationChannel channel =
+ new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_LOW);
+ channel.setRingtone(new Uri.Builder().scheme("test").build());
+ channel.setLights(true);
+ channel.setBypassDnd(true);
+ channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
+
+ mHelper.createNotificationChannel(pkg, uid, channel);
+
+ // same id, try to update all fields
+ final NotificationChannel channel2 =
+ new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
+ channel2.setRingtone(new Uri.Builder().scheme("test2").build());
+ channel2.setLights(false);
+ channel2.setBypassDnd(false);
+ channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
+
+ mHelper.updateNotificationChannel(pkg, uid, channel2);
+
+ // all fields should be changed
+ assertEquals(channel2, mHelper.getNotificationChannel(pkg, uid, channel.getId()));
+ }
+
+ @Test
+ public void testGetChannelWithFallback() throws Exception {
+ NotificationChannel channel =
+ mHelper.getNotificationChannelWithFallback(pkg, uid, "garbage");
+ assertEquals(NotificationChannel.DEFAULT_CHANNEL_ID, channel.getId());
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/servicestests/src/com/android/server/notification/SnoozeHelperTest.java
index ec1fdad..ffc45ea 100644
--- a/services/tests/servicestests/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -24,6 +24,7 @@
import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationChannel;
+import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.os.UserHandle;
@@ -178,7 +179,8 @@
.build();
return new NotificationRecord(getContext(), new StatusBarNotification(
pkg, pkg, id, tag, 0, 0, 0, n, user),
- new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name"));
+ new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
+ NotificationManager.IMPORTANCE_HIGH));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
new file mode 100644
index 0000000..77f96ca
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/AppTransitionTests.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static com.android.server.wm.AppTransition.TRANSIT_ACTIVITY_OPEN;
+import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_GOING_AWAY;
+import static com.android.server.wm.AppTransition.TRANSIT_KEYGUARD_UNOCCLUDE;
+import static org.junit.Assert.assertEquals;
+
+import android.content.Context;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Test class for {@link AppTransition}.
+ *
+ * runtest frameworks-services -c com.android.server.wm.AppTransitionTests
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class AppTransitionTests {
+
+ private WindowManagerService mWm;
+
+ @Before
+ public void setUp() throws Exception {
+ final Context context = InstrumentationRegistry.getTargetContext();
+ mWm = TestWindowManagerPolicy.getWindowManagerService(context);
+ }
+
+ @Test
+ public void testKeyguardOverride() throws Exception {
+ mWm.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false /* alwaysKeepCurrent */);
+ mWm.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY, false /* alwaysKeepCurrent */);
+ assertEquals(TRANSIT_KEYGUARD_GOING_AWAY, mWm.mAppTransition.getAppTransition());
+ }
+
+ @Test
+ public void testForceOverride() throws Exception {
+ mWm.prepareAppTransition(TRANSIT_KEYGUARD_UNOCCLUDE, false /* alwaysKeepCurrent */);
+ mWm.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false /* alwaysKeepCurrent */,
+ 0 /* flags */, true /* forceOverride */);
+ assertEquals(TRANSIT_ACTIVITY_OPEN, mWm.mAppTransition.getAppTransition());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 03cbb43..3e7d272 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -55,7 +55,6 @@
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM;
import static android.view.WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
@@ -115,11 +114,6 @@
}
@Override
- public boolean canShowDismissingWindowWhileLockedLw() {
- return false;
- }
-
- @Override
public void setInitialDisplaySize(Display display, int width, int height, int density) {
}
@@ -196,9 +190,6 @@
case TYPE_INPUT_METHOD_DIALOG:
// on-screen keyboards and other such input method user interfaces go here.
return 13;
- case TYPE_KEYGUARD_SCRIM:
- // the safety window that shows behind keyguard while keyguard is starting
- return 14;
case TYPE_STATUS_BAR_SUB_PANEL:
return 15;
case TYPE_STATUS_BAR:
@@ -299,27 +290,16 @@
}
@Override
- public boolean isForceHiding(WindowManager.LayoutParams attrs) {
- return false;
- }
-
- @Override
public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs) {
return false;
}
@Override
- public boolean canBeForceHidden(WindowState win,
- WindowManager.LayoutParams attrs) {
+ public boolean canBeHiddenByKeyguardLw(WindowState win) {
return false;
}
@Override
- public WindowState getWinShowWhenLockedLw() {
- return null;
- }
-
- @Override
public View addStartingWindow(IBinder appToken, String packageName, int theme,
CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon,
int logo, int windowFlags, Configuration overrideConfig) {
@@ -359,13 +339,13 @@
}
@Override
- public Animation createForceHideEnterAnimation(boolean onWallpaper,
+ public Animation createHiddenByKeyguardExit(boolean onWallpaper,
boolean goingToNotificationShade) {
return null;
}
@Override
- public Animation createForceHideWallpaperExitAnimation(boolean goingToNotificationShade) {
+ public Animation createKeyguardWallpaperExit(boolean goingToNotificationShade) {
return null;
}
@@ -432,8 +412,7 @@
@Override
public void applyPostLayoutPolicyLw(WindowState win,
- WindowManager.LayoutParams attrs, WindowState attached) {
-
+ WindowManager.LayoutParams attrs, WindowState attached, WindowState imeTarget) {
}
@Override
@@ -523,7 +502,12 @@
}
@Override
- public boolean isKeyguardShowingOrOccluded() {
+ public boolean isKeyguardOccluded() {
+ return false;
+ }
+
+ @Override
+ public boolean isKeyguardTrustedLw() {
return false;
}
@@ -543,16 +527,20 @@
}
@Override
- public void notifyActivityDrawnForKeyguardLw() {
-
+ public boolean isKeyguardDrawnLw() {
+ return false;
}
@Override
- public boolean isKeyguardDrawnLw() {
+ public boolean isShowingDreamLw() {
return false;
}
@Override
+ public void onKeyguardOccludedChangedLw(boolean occluded) {
+ }
+
+ @Override
public int rotationForOrientationLw(int orientation,
int lastRotation) {
return 0;
diff --git a/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
new file mode 100644
index 0000000..36bd13a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server.wm;
+
+import static junit.framework.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+
+import android.app.ActivityManagerInternal;
+import android.content.Context;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.view.IApplicationToken;
+
+import com.android.server.LocalServices;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+
+/**
+ * Test class for {@link AppTransition}.
+ *
+ * runtest frameworks-services -c com.android.server.wm.UnknownVisibilityControllerTest
+ */
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class UnknownAppVisibilityControllerTest {
+
+ private WindowManagerService mWm;
+ private @Mock ActivityManagerInternal mAm;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ final Context context = InstrumentationRegistry.getTargetContext();
+ LocalServices.addService(ActivityManagerInternal.class, mAm);
+ doAnswer((InvocationOnMock invocationOnMock) -> {
+ invocationOnMock.getArgumentAt(0, Runnable.class).run();
+ return null;
+ }).when(mAm).notifyKeyguardFlagsChanged(any());
+ mWm = TestWindowManagerPolicy.getWindowManagerService(context);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ LocalServices.removeServiceForTest(ActivityManagerInternal.class);
+ }
+
+ @Test
+ public void testFlow() throws Exception {
+ AppWindowToken token = createAppToken();
+ mWm.mUnknownAppVisibilityController.notifyLaunched(token);
+ mWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token);
+ mWm.mUnknownAppVisibilityController.notifyRelayouted(token);
+
+ // Make sure our handler processed the message.
+ Thread.sleep(100);
+ assertTrue(mWm.mUnknownAppVisibilityController.allResolved());
+ }
+
+ @Test
+ public void testMultiple() throws Exception {
+ AppWindowToken token1 = createAppToken();
+ AppWindowToken token2 = createAppToken();
+ mWm.mUnknownAppVisibilityController.notifyLaunched(token1);
+ mWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token1);
+ mWm.mUnknownAppVisibilityController.notifyLaunched(token2);
+ mWm.mUnknownAppVisibilityController.notifyRelayouted(token1);
+ mWm.mUnknownAppVisibilityController.notifyAppResumedFinished(token2);
+ mWm.mUnknownAppVisibilityController.notifyRelayouted(token2);
+
+ // Make sure our handler processed the message.
+ Thread.sleep(100);
+ assertTrue(mWm.mUnknownAppVisibilityController.allResolved());
+ }
+
+ @Test
+ public void testClear() throws Exception {
+ AppWindowToken token = createAppToken();
+ mWm.mUnknownAppVisibilityController.notifyLaunched(token);
+ mWm.mUnknownAppVisibilityController.clear();;
+ assertTrue(mWm.mUnknownAppVisibilityController.allResolved());
+ }
+
+ @Test
+ public void testAppRemoved() throws Exception {
+ AppWindowToken token = createAppToken();
+ mWm.mUnknownAppVisibilityController.notifyLaunched(token);
+ mWm.mUnknownAppVisibilityController.appRemoved(token);
+ assertTrue(mWm.mUnknownAppVisibilityController.allResolved());
+ }
+
+ private AppWindowToken createAppToken() {
+ return new AppWindowToken(mWm, mock(IApplicationToken.class), false,
+ mWm.getDefaultDisplayContentLocked());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
index 15cd55f..19b4186 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowFrameTests.java
@@ -35,6 +35,7 @@
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
import static android.view.WindowManager.LayoutParams.FILL_PARENT;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
/**
* Tests for the {@link WindowState#computeFrameLw} method and other window frame machinery.
@@ -102,6 +103,63 @@
}
@Test
+ public void testLayoutInFullscreenTaskInsets() throws Exception {
+ Task task = new TaskWithBounds(null); // fullscreen task doesn't use bounds for computeFrame
+ WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT);
+ w.mAttrs.gravity = Gravity.LEFT | Gravity.TOP;
+
+ final int bottomContentInset = 100;
+ final int topContentInset = 50;
+ final int bottomVisibleInset = 30;
+ final int topVisibleInset = 70;
+ final int leftStableInset = 20;
+ final int rightStableInset = 90;
+
+ // With no insets or system decor all the frames incoming from PhoneWindowManager
+ // are identical.
+ final Rect pf = new Rect(0, 0, 1000, 1000);
+ final Rect df = pf;
+ final Rect of = df;
+ final Rect cf = new Rect(pf);
+ // Produce some insets
+ cf.top += 50;
+ cf.bottom -= 100;
+ final Rect vf = new Rect(pf);
+ vf.top += topVisibleInset;
+ vf.bottom -= bottomVisibleInset;
+ final Rect sf = new Rect(pf);
+ sf.left += leftStableInset;
+ sf.right -= rightStableInset;
+
+ final Rect dcf = pf;
+ // When mFrame extends past cf, the content insets are
+ // the difference between mFrame and ContentFrame. Visible
+ // and stable frames work the same way.
+ w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null);
+ assertRect(w.mFrame,0, 0, 1000, 1000);
+ assertRect(w.mContentInsets, 0, topContentInset, 0, bottomContentInset);
+ assertRect(w.mVisibleInsets, 0, topVisibleInset, 0, bottomVisibleInset);
+ assertRect(w.mStableInsets, leftStableInset, 0, rightStableInset, 0);
+ // The frames remain as passed in shrunk to the window frame
+ assertTrue(cf.equals(w.getContentFrameLw()));
+ assertTrue(vf.equals(w.getVisibleFrameLw()));
+ assertTrue(sf.equals(w.getStableFrameLw()));
+ // On the other hand mFrame doesn't extend past cf we won't get any insets
+ w.mAttrs.x = 100;
+ w.mAttrs.y = 100;
+ w.mAttrs.width = 100; w.mAttrs.height = 100; //have to clear MATCH_PARENT
+ w.mRequestedWidth = 100;
+ w.mRequestedHeight = 100;
+ w.computeFrameLw(pf, df, of, cf, vf, dcf, sf, null);
+ assertRect(w.mFrame, 100, 100, 200, 200);
+ assertRect(w.mContentInsets, 0, 0, 0, 0);
+ // In this case the frames are shrunk to the window frame.
+ assertTrue(w.mFrame.equals(w.getContentFrameLw()));
+ assertTrue(w.mFrame.equals(w.getVisibleFrameLw()));
+ assertTrue(w.mFrame.equals(w.getStableFrameLw()));
+ }
+
+ @Test
public void testLayoutInFullscreenTaskNoInsets() throws Exception {
Task task = new TaskWithBounds(null); // fullscreen task doesn't use bounds for computeFrame
WindowState w = createWindow(task, FILL_PARENT, FILL_PARENT);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index af8c314..3daa87c 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -597,7 +597,6 @@
mAccessoryModeRequestTime + ACCESSORY_REQUEST_TIMEOUT;
if (mConfigured && enteringAccessoryMode) {
- mAccessoryModeRequestTime = 0;
// successfully entered accessory mode
if (mAccessoryStrings != null) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index fe9d41a..987b1d1 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -16,7 +16,10 @@
package android.telephony;
+import static com.android.internal.util.Preconditions.checkNotNull;
+
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
@@ -27,11 +30,12 @@
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.BatteryStats;
-import android.os.ResultReceiver;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.os.Bundle;
+import android.os.Handler;
import android.os.RemoteException;
+import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.SystemProperties;
import android.service.carrier.CarrierIdentifier;
@@ -792,6 +796,29 @@
*/
public static final String VVM_TYPE_CVVM = "vvm_type_cvvm";
+ /**
+ * @hide
+ */
+ public static final String USSD_RESPONSE = "USSD_RESPONSE";
+
+ /**
+ * USSD return code success.
+ * @hide
+ */
+ public static final int USSD_RETURN_SUCCESS = 100;
+
+ /**
+ * USSD return code for failure case.
+ * @hide
+ */
+ public static final int USSD_RETURN_FAILURE = -1;
+
+ /**
+ * USSD return code for failure case.
+ * @hide
+ */
+ public static final int USSD_ERROR_SERVICE_UNAVAIL = -2;
+
//
//
// Device Info
@@ -4609,6 +4636,56 @@
return new int[0];
}
+ public static abstract class OnReceiveUssdResponseCallback {
+ /**
+ ** Called when USSD has succeeded.
+ **/
+ public void onReceiveUssdResponse(String request, CharSequence response) {};
+
+ /**
+ ** Called when USSD has failed.
+ **/
+ public void onReceiveUssdResponseFailed(String request, int failureCode) {};
+ }
+
+ /* <p>Requires permission:
+ * @link android.Manifest.permission#CALL_PHONE}
+ */
+ @RequiresPermission(android.Manifest.permission.CALL_PHONE)
+ public void sendUssdRequest(String ussdRequest,
+ final OnReceiveUssdResponseCallback callback, Handler handler) {
+ checkNotNull(callback, "OnReceiveUssdResponseCallback cannot be null.");
+
+ ResultReceiver wrappedCallback = new ResultReceiver(handler) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle ussdResponse) {
+ Rlog.d(TAG, "USSD:" + resultCode);
+ checkNotNull(ussdResponse, "ussdResponse cannot be null.");
+ UssdResponse response = ussdResponse.getParcelable(USSD_RESPONSE);
+
+ if (resultCode == USSD_RETURN_SUCCESS) {
+ callback.onReceiveUssdResponse(response.getUssdRequest(),
+ response.getReturnMessage());
+ } else {
+ callback.onReceiveUssdResponseFailed(response.getUssdRequest(), resultCode);
+ }
+ }
+ };
+
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ telephony.handleUssdRequest(ussdRequest, wrappedCallback);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#sendUSSDCode", e);
+ UssdResponse response = new UssdResponse(ussdRequest, "");
+ Bundle returnData = new Bundle();
+ returnData.putParcelable(USSD_RESPONSE, response);
+ wrappedCallback.send(USSD_ERROR_SERVICE_UNAVAIL, returnData);
+ }
+ }
+
/** @hide */
@SystemApi
public boolean handlePinMmi(String dialString) {
diff --git a/telephony/java/android/telephony/UssdResponse.aidl b/telephony/java/android/telephony/UssdResponse.aidl
new file mode 100644
index 0000000..add28a0
--- /dev/null
+++ b/telephony/java/android/telephony/UssdResponse.aidl
@@ -0,0 +1,20 @@
+/*
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.telephony;
+
+parcelable UssdResponse;
diff --git a/telephony/java/android/telephony/UssdResponse.java b/telephony/java/android/telephony/UssdResponse.java
new file mode 100644
index 0000000..5df681d
--- /dev/null
+++ b/telephony/java/android/telephony/UssdResponse.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+/**
+ * Represents the Ussd response, including
+ * the message and the return code.
+ * @hide
+ */
+public final class UssdResponse implements Parcelable {
+ private CharSequence mReturnMessage;
+ private String mUssdRequest;
+
+
+ /**
+ * Implement the Parcelable interface
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(mUssdRequest);
+ TextUtils.writeToParcel(mReturnMessage, dest, 0);
+ }
+
+ public String getUssdRequest() {
+ return mUssdRequest;
+ }
+
+ public CharSequence getReturnMessage() {
+ return mReturnMessage;
+ }
+
+ /**
+ * Implement the Parcelable interface
+ */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * * Initialize the object from the request and return message.
+ */
+ public UssdResponse(String ussdRequest, CharSequence returnMessage) {
+ mUssdRequest = ussdRequest;
+ mReturnMessage = returnMessage;
+ }
+
+ public static final Parcelable.Creator<UssdResponse> CREATOR = new Creator<UssdResponse>() {
+
+ @Override
+ public UssdResponse createFromParcel(Parcel in) {
+ String request = in.readString();
+ CharSequence message = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+ return new UssdResponse(request, message);
+ }
+
+ @Override
+ public UssdResponse[] newArray(int size) {
+ return new UssdResponse[size];
+ }
+ };
+}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index c72b32a..4c66be1 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -271,6 +271,15 @@
*/
boolean handlePinMmi(String dialString);
+
+ /**
+ * Handles USSD commands.
+ *
+ * @param ussdRequest the USSD command to be executed.
+ * @param wrappedCallback receives a callback result.
+ */
+ void handleUssdRequest(String ussdRequest, in ResultReceiver wrappedCallback);
+
/**
* Handles PIN MMI commands (PIN/PIN2/PUK/PUK2), which are initiated
* without SEND (so <code>dial</code> is not appropriate) for
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index fa880f0..4a4c6c8 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -123,7 +123,7 @@
/*package*/ static long initRaster(@Nullable Bitmap bitmap) {
long nativeBitmapOrZero = 0;
if (bitmap != null) {
- nativeBitmapOrZero = bitmap.refSkPixelRef();
+ nativeBitmapOrZero = bitmap.getNativeInstance();
}
if (nativeBitmapOrZero > 0) {
// get the Bitmap from the int
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 9ec546e..c86f5c3 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -524,10 +524,6 @@
}
@Override
- public void setKeyguardAnimatingIn(boolean animating) throws RemoteException {
- }
-
- @Override
public void setSwitchingUser(boolean switching) throws RemoteException {
}