Merge "Hide notifications when occluded and disabled on keyguard" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index dca7481..e75cc90 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5875,7 +5875,7 @@
     field public static final int RESIZE_VERTICAL = 2; // 0x2
     field public static final int WIDGET_CATEGORY_HOME_SCREEN = 1; // 0x1
     field public static final int WIDGET_CATEGORY_KEYGUARD = 2; // 0x2
-    field public static final int WIDGET_CATEGORY_RECENTS = 4; // 0x4
+    field public static final int WIDGET_CATEGORY_SEARCHBOX = 4; // 0x4
     field public int autoAdvanceViewId;
     field public android.content.ComponentName configure;
     field public int icon;
@@ -36827,7 +36827,7 @@
     method public void setWebViewClient(android.webkit.WebViewClient);
     method public deprecated boolean showFindDialog(java.lang.String, boolean);
     method public void stopLoading();
-    method public boolean zoomBy(float);
+    method public void zoomBy(float);
     method public boolean zoomIn();
     method public boolean zoomOut();
     field public static final java.lang.String SCHEME_GEO = "geo:0,0?q=";
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 5921477..f8dfdd9 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -824,13 +825,6 @@
     public static final String EXTRA_COMPACT_ACTIONS = "android.compactActions";
 
     /**
-     * {@link #extras} key: the user that built the notification.
-     *
-     * @hide
-     */
-    public static final String EXTRA_ORIGINATING_USERID = "android.originatingUserId";
-
-    /**
      * Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be
      * displayed in the heads up space.
      *
@@ -1813,10 +1807,12 @@
                 = "android.rebuild.hudViewActionCount";
 
         /**
-         * The package name of the context used to create the notification via a Builder.
+         * The ApplicationInfo of the package that created the notification, used to create
+         * a context to rebuild the notification via a Builder.
+         * @hide
          */
-        private static final String EXTRA_REBUILD_CONTEXT_PACKAGE =
-                "android.rebuild.contextPackage";
+        private static final String EXTRA_REBUILD_CONTEXT_APPLICATION_INFO =
+                "android.rebuild.applicationInfo";
 
         // Whether to enable stripping (at post time) & rebuilding (at listener receive time) of
         // memory intensive resources.
@@ -1867,11 +1863,6 @@
         private int mColor = COLOR_DEFAULT;
 
         /**
-         * The user that built the notification originally.
-         */
-        private int mOriginatingUserId;
-
-        /**
          * Contains extras related to rebuilding during the build phase.
          */
         private Bundle mRebuildBundle = new Bundle();
@@ -2591,7 +2582,7 @@
             // Note: This assumes that the current user can read the profile badge of the
             // originating user.
             UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
-            return userManager.getBadgeForUser(new UserHandle(mOriginatingUserId), 0);
+            return userManager.getBadgeForUser(new UserHandle(mContext.getUserId()), 0);
         }
 
         private Bitmap getProfileBadge() {
@@ -2670,8 +2661,7 @@
          * @param hasProgress whether the progress bar should be shown and set
          */
         private RemoteViews applyStandardTemplate(int resId, boolean hasProgress) {
-            RemoteViews contentView = new BuilderRemoteViews(mContext.getPackageName(),
-                    mOriginatingUserId, resId);
+            RemoteViews contentView = new BuilderRemoteViews(mContext.getApplicationInfo(), resId);
 
             resetStandardTemplate(contentView);
 
@@ -3063,8 +3053,8 @@
          */
         public void populateExtras(Bundle extras) {
             // Store original information used in the construction of this object
-            extras.putInt(EXTRA_ORIGINATING_USERID, mOriginatingUserId);
-            extras.putString(EXTRA_REBUILD_CONTEXT_PACKAGE, mContext.getPackageName());
+            extras.putParcelable(EXTRA_REBUILD_CONTEXT_APPLICATION_INFO,
+                    mContext.getApplicationInfo());
             extras.putCharSequence(EXTRA_TITLE, mContentTitle);
             extras.putCharSequence(EXTRA_TEXT, mContentText);
             extras.putCharSequence(EXTRA_SUB_TEXT, mSubText);
@@ -3152,13 +3142,14 @@
             extras.remove(EXTRA_NEEDS_REBUILD);
 
             // Re-create notification context so we can access app resources.
-            String packageName = extras.getString(EXTRA_REBUILD_CONTEXT_PACKAGE);
+            ApplicationInfo applicationInfo = extras.getParcelable(
+                    EXTRA_REBUILD_CONTEXT_APPLICATION_INFO);
             Context builderContext;
             try {
-                builderContext = context.createPackageContext(packageName,
+                builderContext = context.createApplicationContext(applicationInfo,
                         Context.CONTEXT_RESTRICTED);
             } catch (NameNotFoundException e) {
-                Log.e(TAG, "Package name " + packageName + " not found");
+                Log.e(TAG, "ApplicationInfo " + applicationInfo + " not found");
                 builderContext = context;  // try with our context
             }
 
@@ -3293,7 +3284,6 @@
 
             // Extras.
             Bundle extras = n.extras;
-            mOriginatingUserId = extras.getInt(EXTRA_ORIGINATING_USERID);
             mContentTitle = extras.getCharSequence(EXTRA_TITLE);
             mContentText = extras.getCharSequence(EXTRA_TEXT);
             mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
@@ -3326,7 +3316,6 @@
          * object.
          */
         public Notification build() {
-            mOriginatingUserId = mContext.getUserId();
             mHasThreeLines = hasThreeLines();
 
             Notification n = buildUnstyled();
@@ -4826,8 +4815,8 @@
             super(parcel);
         }
 
-        public BuilderRemoteViews(String packageName, int userId, int layoutId) {
-            super(packageName, userId, layoutId);
+        public BuilderRemoteViews(ApplicationInfo appInfo, int layoutId) {
+            super(appInfo, layoutId);
         }
 
         @Override
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index bd45c7e..00248cc 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -188,7 +188,7 @@
      * this widget. Can have the value {@link
      * AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link
      * AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD} or {@link
-     * AppWidgetProviderInfo#WIDGET_CATEGORY_RECENTS}.
+     * AppWidgetProviderInfo#WIDGET_CATEGORY_SEARCHBOX}.
      */
     public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
 
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index 02f70c8..b4d79b4 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -61,9 +61,9 @@
     public static final int WIDGET_CATEGORY_KEYGUARD = 2;
 
     /**
-     * Indicates that the widget can be displayed within recents.
+     * Indicates that the widget can be displayed within a space reserved for the search box.
      */
-    public static final int WIDGET_CATEGORY_RECENTS = 4;
+    public static final int WIDGET_CATEGORY_SEARCHBOX = 4;
 
     /**
      * Identity of this AppWidget component.  This component should be a {@link
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index edfa7af..081bfdf 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1939,16 +1939,14 @@
      *
      * @param zoomFactor the zoom factor to apply. The zoom factor will be clamped to the Webview's
      * zoom limits. This value must be in the range 0.01 to 100.0 inclusive.
-     *
-     * @return false if no zoom changes, true otherwise.
      */
-    public boolean zoomBy(float zoomFactor) {
+    public void zoomBy(float zoomFactor) {
         checkThread();
         if (zoomFactor < 0.01)
             throw new IllegalArgumentException("zoomFactor must be greater than 0.01.");
         if (zoomFactor > 100.0)
             throw new IllegalArgumentException("zoomFactor must be less than 100.");
-        return mProvider.zoomBy(zoomFactor);
+        mProvider.zoomBy(zoomFactor);
     }
 
     /**
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 69d5f40..90e9c69 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -22,11 +22,13 @@
 import android.app.PendingIntent;
 import android.appwidget.AppWidgetHostView;
 import android.content.Context;
+import android.content.ContextWrapper;
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
@@ -1653,8 +1655,10 @@
      *
      * @param application The application whose content is shown by the views.
      * @param layoutId The id of the layout resource.
+     *
+     * @hide
      */
-    private RemoteViews(ApplicationInfo application, int layoutId) {
+    protected RemoteViews(ApplicationInfo application, int layoutId) {
         mApplication = application;
         mLayoutId = layoutId;
         mBitmapCache = new BitmapCache();
@@ -2515,15 +2519,29 @@
         RemoteViews rvToApply = getRemoteViewsToApply(context);
 
         View result;
-
-        Context c = prepareContext(context);
+        // RemoteViews may be built by an application installed in another
+        // user. So build a context that loads resources from that user but
+        // still returns the current users userId so settings like data / time formats
+        // are loaded without requiring cross user persmissions.
+        final Context contextForResources = getContextForResources(context);
+        Context inflationContext = new ContextWrapper(context) {
+            @Override
+            public Resources getResources() {
+                return contextForResources.getResources();
+            }
+            @Override
+            public Resources.Theme getTheme() {
+                return contextForResources.getTheme();
+            }
+        };
 
         LayoutInflater inflater = (LayoutInflater)
-                c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
 
-        inflater = inflater.cloneInContext(c);
+        // Clone inflater so we load resources from correct context and
+        // we don't add a filter to the static version returned by getSystemService.
+        inflater = inflater.cloneInContext(inflationContext);
         inflater.setFilter(this);
-
         result = inflater.inflate(rvToApply.getLayoutId(), parent, false);
 
         rvToApply.performApply(result, parent, handler);
@@ -2557,7 +2575,6 @@
             }
         }
 
-        prepareContext(context);
         rvToApply.performApply(v, (ViewGroup) v.getParent(), handler);
     }
 
@@ -2572,7 +2589,7 @@
         }
     }
 
-    private Context prepareContext(Context context) {
+    private Context getContextForResources(Context context) {
         if (mApplication != null) {
             if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
                     && context.getPackageName().equals(mApplication.packageName)) {
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 603fcde..3629cbb 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -6600,12 +6600,12 @@
             <flag name="vertical" value="0x2" />
         </attr>
         <!-- Optional parameter which indicates where this widget can be shown,
-             ie. home screen, keyguard, recents or any combination thereof.
+             ie. home screen, keyguard, search bar or any combination thereof.
              Supports combined values using | operator. -->
         <attr name="widgetCategory" format="integer">
             <flag name="home_screen" value="0x1" />
             <flag name="keyguard" value="0x2" />
-            <flag name="recents" value="0x4" />
+            <flag name="searchbox" value="0x4" />
         </attr>
     </declare-styleable>
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d68d12a..b63b91d 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -374,7 +374,7 @@
     <bool name="config_useAttentionLight">false</bool>
 
     <!-- If this is true, the screen will fade off. -->
-    <bool name="config_animateScreenLights">true</bool>
+    <bool name="config_animateScreenLights">false</bool>
 
     <!-- If this is true, key chords can be used to take a screenshot on the device. -->
     <bool name="config_enableScreenshotChord">true</bool>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index c7a91af..23d9748 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -756,6 +756,9 @@
     <!-- Accessibility label for the button that opens the user switcher. -->
     <string name="accessibility_multi_user_switch_switcher">Switch user</string>
 
+    <!-- Accessibility label for the button that opens the user switcher and announces the current user. -->
+    <string name="accessibility_multi_user_switch_switcher_with_current">Switch user, current user <xliff:g id="current_user_name" example="John Doe">%s</xliff:g></string>
+
     <!-- Accessibility label for the button that opens the quick contact of the user. -->
     <string name="accessibility_multi_user_switch_quick_contact">Show profile</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 082dde6..ec7799a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -296,7 +296,7 @@
                         mSearchAppWidgetInfo);
                 Bundle opts = new Bundle();
                 opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
-                        AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+                        AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
                 mSearchAppWidgetHostView.updateAppWidgetOptions(opts);
                 // Set the padding to 0 for this search widget
                 mSearchAppWidgetHostView.setPadding(0, 0, 0, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index e27c0ac..78fc4fb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -392,7 +392,7 @@
 
         // Find the first Recents widget from the same package as the global assist activity
         List<AppWidgetProviderInfo> widgets = mAwm.getInstalledProviders(
-                AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+                AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
         for (AppWidgetProviderInfo info : widgets) {
             if (info.provider.getPackageName().equals(mAssistComponent.getPackageName())) {
                 return info;
@@ -418,7 +418,7 @@
         int searchWidgetId = host.allocateAppWidgetId();
         Bundle opts = new Bundle();
         opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
-                AppWidgetProviderInfo.WIDGET_CATEGORY_RECENTS);
+                AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
         if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, searchWidgetInfo.provider, opts)) {
             return null;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index e44f515..e5ca488 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -558,6 +558,8 @@
             // disable lockscreen notifications until user acts on the banner.
             Settings.Secure.putInt(mContext.getContentResolver(),
                     Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0);
+            Settings.Secure.putInt(mContext.getContentResolver(),
+                    Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0);
 
             final String packageName = mContext.getPackageName();
             PendingIntent cancelIntent = PendingIntent.getBroadcast(mContext, 0,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index e3a0b18..c13593a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -147,6 +147,7 @@
         mMaxExpandHeight = 0;
         mWasReset = true;
         onHeightReset();
+        requestLayout();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index d7144da..dc49118 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -30,6 +30,7 @@
 import com.android.systemui.R;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
 
 /**
  * Container for image of the multi user switcher (tappable).
@@ -90,9 +91,21 @@
 
         if (isClickable()) {
             final UserManager um = UserManager.get(getContext());
-            String text = mContext.getString(um.isUserSwitcherEnabled()
-                    ? R.string.accessibility_multi_user_switch_switcher
-                    : R.string.accessibility_multi_user_switch_quick_contact);
+            String text;
+            if (um.isUserSwitcherEnabled()) {
+                UserSwitcherController controller = mQsPanel.getHost()
+                        .getUserSwitcherController();
+                String currentUser = controller.getCurrentUserName(mContext);
+                if (TextUtils.isEmpty(currentUser)) {
+                    text = mContext.getString(R.string.accessibility_multi_user_switch_switcher);
+                } else {
+                    text = mContext.getString(
+                            R.string.accessibility_multi_user_switch_switcher_with_current,
+                            currentUser);
+                }
+            } else {
+                text = mContext.getString(R.string.accessibility_multi_user_switch_quick_contact);
+            }
             if (!TextUtils.isEmpty(text)) {
                 event.getText().add(text);
             }
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 ddd03d6..cbb5e8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3774,7 +3774,9 @@
             row = (ExpandableNotificationRow) expandView;
             row.setUserExpanded(true);
         }
-        if (isLockscreenPublicMode() && !userAllowsPrivateNotificationsInPublic(mCurrentUserId)) {
+        boolean fullShadeNeedsBouncer = !userAllowsPrivateNotificationsInPublic(mCurrentUserId)
+                || !mShowLockscreenNotifications;
+        if (isLockscreenPublicMode() && fullShadeNeedsBouncer) {
             mLeaveOpenOnKeyguardHide = true;
             showBouncer();
             mDraggedDownRow = row;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index e4b1945..52fa621 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -334,6 +334,14 @@
         }
     }
 
+    public String getCurrentUserName(Context context) {
+        if (mUsers.isEmpty()) return null;
+        UserRecord item = mUsers.get(0);
+        if (item == null || item.info == null) return null;
+        if (item.isGuest) return context.getString(R.string.guest_nickname);
+        return item.info.name;
+    }
+
     public static abstract class BaseUserAdapter extends BaseAdapter {
 
         final UserSwitcherController mController;
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index 189131c..05ad1fe 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -545,8 +545,9 @@
                 setZenModeCondition(condition, "downtime");
             }
             // exit downtime
-            if (!inDowntime && mode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
-                    && mDowntime.isDowntimeCondition(mExitCondition)) {
+            if (!inDowntime && mDowntime.isDowntimeCondition(mExitCondition)
+                    && (mode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
+                                || mode == Global.ZEN_MODE_NO_INTERRUPTIONS)) {
                 mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF, "downtimeExit");
             }
         }