Merge "Set up view state before attaching, jump drawables if needed" into nyc-dev
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 31ab26f..831c646 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -26,6 +26,7 @@
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewParent;
+import android.util.DisplayMetrics;
 
 import com.android.internal.R;
 import com.android.internal.util.Preconditions;
@@ -209,11 +210,9 @@
     }
 
     private boolean isContentRectWithinBounds() {
-        mScreenRect.set(
-            0,
-            0,
-            mContext.getResources().getDisplayMetrics().widthPixels,
-            mContext.getResources().getDisplayMetrics().heightPixels);
+        DisplayMetrics metrics = mContext.getApplicationContext()
+                .getResources().getDisplayMetrics();
+        mScreenRect.set(0, 0, metrics.widthPixels, metrics.heightPixels);
 
         return intersectsClosed(mContentRectOnScreen, mScreenRect)
             && intersectsClosed(mContentRectOnScreen, mViewRectOnScreen);
diff --git a/core/res/res/layout/alert_dialog_material.xml b/core/res/res/layout/alert_dialog_material.xml
index 6d33de6..178505c 100644
--- a/core/res/res/layout/alert_dialog_material.xml
+++ b/core/res/res/layout/alert_dialog_material.xml
@@ -20,6 +20,7 @@
     android:id="@+id/parentPanel"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:gravity="start|top"
     android:orientation="vertical">
 
     <include layout="@layout/alert_dialog_title_material" />
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 8530d66..e224141 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -40,7 +40,6 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -959,18 +958,15 @@
         }
     }
 
-    protected View bindVetoButtonClickListener(View row, final StatusBarNotification n) {
-        View vetoButton = row.findViewById(R.id.veto);
-        vetoButton.setOnClickListener(new View.OnClickListener() {
+    protected void bindDismissListener(final ExpandableNotificationRow row) {
+        row.setOnDismissListener(new View.OnClickListener() {
             public void onClick(View v) {
                 // Accessibility feedback
                 v.announceForAccessibility(
                         mContext.getString(R.string.accessibility_notification_dismissed));
-                performRemoveNotification(n, false /* removeView */);
+                performRemoveNotification(row.getStatusBarNotification(), false /* removeView */);
             }
         });
-        vetoButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
-        return vetoButton;
     }
 
     protected void performRemoveNotification(StatusBarNotification n, boolean removeView) {
@@ -1647,9 +1643,7 @@
         }
 
         workAroundBadLayerDrawableOpacity(row);
-        View vetoButton = bindVetoButtonClickListener(row, sbn);
-        vetoButton.setContentDescription(mContext.getString(
-                R.string.accessibility_remove_notification));
+        bindDismissListener(row);
 
         // NB: the large icon is now handled entirely by the template
 
@@ -2409,10 +2403,6 @@
         updateHeadsUp(key, entry, shouldPeek, alertAgain);
         updateNotifications();
 
-        // Update the veto button accordingly (and as a result, whether this row is
-        // swipe-dismissable)
-        bindVetoButtonClickListener(entry.row, notification);
-
         if (!notification.isClearable()) {
             // The user may have performed a dismiss action on the notification, since it's
             // not clearable we should snap it back.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index f09eae8..e400506 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -109,7 +109,6 @@
     private int mHeadsUpHeight;
     private View mVetoButton;
     private int mNotificationColor;
-    private boolean mClearable;
     private ExpansionLogger mLogger;
     private String mLoggingKey;
     private NotificationSettingsIconRow mSettingsIconRow;
@@ -280,7 +279,6 @@
         mPublicLayout.onNotificationUpdated(entry);
         mShowingPublicInitialized = false;
         updateNotificationColor();
-        updateClearability();
         if (mIsSummaryWithChildren) {
             mChildrenContainer.recreateNotificationHeader(mExpandClickListener, mEntry.notification);
             mChildrenContainer.onNotificationUpdated();
@@ -779,6 +777,14 @@
         return mGroupParentWhenDismissed;
     }
 
+    public void performDismiss() {
+        mVetoButton.performClick();
+    }
+
+    public void setOnDismissListener(OnClickListener listener) {
+        mVetoButton.setOnClickListener(listener);
+    }
+
     public interface ExpansionLogger {
         public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
     }
@@ -880,6 +886,9 @@
             }
         });
         mVetoButton = findViewById(R.id.veto);
+        mVetoButton.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
+        mVetoButton.setContentDescription(mContext.getString(
+                R.string.accessibility_remove_notification));
 
         // Add the views that we translate to reveal the gear
         mTranslateableViews = new ArrayList<View>();
@@ -893,6 +902,10 @@
         mTranslateableViews.remove(mGutsStub);
     }
 
+    public View getVetoButton() {
+        return mVetoButton;
+    }
+
     public void resetTranslation() {
         if (mTranslateableViews != null) {
             for (int i = 0; i < mTranslateableViews.size(); i++) {
@@ -1157,7 +1170,9 @@
     }
 
     /**
-     * @return Can the underlying notification be cleared?
+     * @return Can the underlying notification be cleared? This can be different from whether the
+     *         notification can be dismissed in case notifications are sensitive on the lockscreen.
+     * @see #canViewBeDismissed()
      */
     public boolean isClearable() {
         return mStatusBarNotification != null && mStatusBarNotification.isClearable();
@@ -1317,7 +1332,6 @@
         NotificationContentView showingLayout = getShowingLayout();
         showingLayout.updateBackgroundColor(animated);
         mPrivateLayout.updateExpandButtons(isExpandable());
-        updateClearability();
         mShowingPublicInitialized = true;
     }
 
@@ -1357,12 +1371,12 @@
         return mIsHeadsUp;
     }
 
-    private void updateClearability() {
-        // public versions cannot be dismissed
-        mVetoButton.setVisibility(canViewBeDismissed() ? View.VISIBLE : View.GONE);
-    }
-
-    private boolean canViewBeDismissed() {
+    /**
+     * @return Whether this view is allowed to be dismissed. Only valid for visible notifications as
+     *         otherwise some state might not be updated. To request about the general clearability
+     *         see {@link #isClearable()}.
+     */
+    public boolean canViewBeDismissed() {
         return isClearable() && (!mShowingPublic || !mSensitiveHiddenInGeneral);
     }
 
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 f7b258f..323a2a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3442,7 +3442,6 @@
 
         repositionNavigationBar();
         updateRowStates();
-        mIconController.defineSlots();
         mScreenPinningRequest.onConfigurationChanged();
         mNetworkController.onConfigurationChanged();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index f415ae5..716a44e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -112,6 +112,8 @@
 
     public StatusBarIconController(Context context, View statusBar, View keyguardStatusBar,
             PhoneStatusBar phoneStatusBar) {
+        super(context.getResources().getStringArray(
+                com.android.internal.R.array.config_statusBarIcons));
         mContext = context;
         mPhoneStatusBar = phoneStatusBar;
         mSystemIconArea = (LinearLayout) statusBar.findViewById(R.id.system_icon_area);
@@ -137,7 +139,6 @@
         mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
         mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
         mHandler = new Handler();
-        defineSlots();
         loadDimens();
 
         TunerService.get(mContext).addTunable(this, ICON_BLACKLIST);
@@ -197,11 +198,6 @@
                 R.dimen.status_bar_icon_padding);
     }
 
-    public void defineSlots() {
-        defineSlots(mContext.getResources().getStringArray(
-                com.android.internal.R.array.config_statusBarIcons));
-    }
-
     private void addSystemIcon(int index, StatusBarIcon icon) {
         String slot = getSlot(index);
         int viewIndex = getViewIndex(index);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
index 97b31f2..94adea0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconList.java
@@ -25,14 +25,11 @@
     private ArrayList<String> mSlots = new ArrayList<>();
     private ArrayList<StatusBarIcon> mIcons = new ArrayList<>();
 
-    public void defineSlots(String[] slots) {
-        mSlots.clear();
+    public StatusBarIconList(String[] slots) {
         final int N = slots.length;
         for (int i=0; i < N; i++) {
             mSlots.add(slots[i]);
-            if (mIcons.size() < mSlots.size()) {
-                mIcons.add(null);
-            }
+            mIcons.add(null);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 7de3879..1e5654e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -780,20 +780,20 @@
 
     public static void performDismiss(View v, NotificationGroupManager groupManager,
             boolean fromAccessibility) {
-        if (v instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-            if (groupManager.isOnlyChildInGroup(row.getStatusBarNotification())) {
-                ExpandableNotificationRow groupSummary =
-                        groupManager.getLogicalGroupSummary(row.getStatusBarNotification());
-                if (groupSummary.isClearable()) {
-                    performDismiss(groupSummary, groupManager, fromAccessibility);
-                }
-            }
-            row.setDismissed(true, fromAccessibility);
+        if (!(v instanceof ExpandableNotificationRow)) {
+            return;
         }
-        final View veto = v.findViewById(R.id.veto);
-        if (veto != null && veto.getVisibility() != View.GONE) {
-            veto.performClick();
+        ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+        if (groupManager.isOnlyChildInGroup(row.getStatusBarNotification())) {
+            ExpandableNotificationRow groupSummary =
+                    groupManager.getLogicalGroupSummary(row.getStatusBarNotification());
+            if (groupSummary.isClearable()) {
+                performDismiss(groupSummary, groupManager, fromAccessibility);
+            }
+        }
+        row.setDismissed(true, fromAccessibility);
+        if (row.isClearable()) {
+            row.performDismiss();
         }
         if (DEBUG) Log.v(TAG, "onChildDismissed: " + v);
     }
@@ -2347,6 +2347,7 @@
         if (hasAddEvent) {
             // This child was just added lets remove all events.
             mHeadsUpChangeAnimations.removeAll(mTmpList);
+            ((ExpandableNotificationRow ) child).setHeadsupDisappearRunning(false);
         }
         mTmpList.clear();
         return hasAddEvent;
@@ -2604,6 +2605,10 @@
                 type = row.wasJustClicked()
                         ? AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
                         : AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
+                if (row.isChildInGroup()) {
+                    // We can otherwise get stuck in there if it was just isolated
+                    row.setHeadsupDisappearRunning(false);
+                }
             } else {
                 StackViewState viewState = mCurrentStackScrollState.getViewStateForView(row);
                 if (viewState == null) {
@@ -3093,6 +3098,22 @@
         requestChildrenUpdate();
         runAnimationFinishedRunnables();
         clearViewOverlays();
+        clearHeadsUpDisappearRunning();
+    }
+
+    private void clearHeadsUpDisappearRunning() {
+        for (int i = 0; i < getChildCount(); i++) {
+            View view = getChildAt(i);
+            if (view instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+                row.setHeadsupDisappearRunning(false);
+                if (row.isSummaryWithChildren()) {
+                    for (ExpandableNotificationRow child : row.getNotificationChildren()) {
+                        child.setHeadsupDisappearRunning(false);
+                    }
+                }
+            }
+        }
     }
 
     private void clearViewOverlays() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 87e87c8..45647ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -173,14 +173,14 @@
     }
 
     public static boolean canChildBeDismissed(View v) {
-        if (v instanceof ExpandableNotificationRow) {
-            ExpandableNotificationRow row = (ExpandableNotificationRow) v;
-            if (row.areGutsExposed()) {
-                return false;
-            }
+        if (!(v instanceof ExpandableNotificationRow)) {
+            return false;
         }
-        final View veto = v.findViewById(R.id.veto);
-        return (veto != null && veto.getVisibility() != View.GONE);
+        ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+        if (row.areGutsExposed()) {
+            return false;
+        }
+        return row.canViewBeDismissed();
     }
 
     /**
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 312553a..3f59b02 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1732,9 +1732,10 @@
                 Alarm a = alarms.get(j);
                 if (a.alarmClock != null) {
                     final int userId = UserHandle.getUserId(a.uid);
+                    AlarmManager.AlarmClockInfo current = mNextAlarmClockForUser.get(userId);
 
                     if (DEBUG_ALARM_CLOCK) {
-                        Log.v(TAG, "Found AlarmClockInfo at " +
+                        Log.v(TAG, "Found AlarmClockInfo " + a.alarmClock + " at " +
                                 formatNextAlarm(getContext(), a.alarmClock, userId) +
                                 " for user " + userId);
                     }
@@ -1742,6 +1743,10 @@
                     // Alarms and batches are sorted by time, no need to compare times here.
                     if (nextForUser.get(userId) == null) {
                         nextForUser.put(userId, a.alarmClock);
+                    } else if (a.alarmClock.equals(current)
+                            && current.getTriggerTime() <= nextForUser.get(userId).getTriggerTime()) {
+                        // same/earlier time and it's the one we cited before, so stick with it
+                        nextForUser.put(userId, current);
                     }
                 }
             }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 4ead64b..5859d34 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3542,14 +3542,24 @@
         final ActivityState prevState = r.state;
         if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r);
         r.state = ActivityState.FINISHING;
+        final boolean finishingActivityInNonFocusedStack
+                = r.task.stack != mStackSupervisor.getFocusedStack()
+                && prevState == ActivityState.PAUSED && mode == FINISH_AFTER_VISIBLE;
 
         if (mode == FINISH_IMMEDIATELY
                 || (prevState == ActivityState.PAUSED
                     && (mode == FINISH_AFTER_PAUSE || mStackId == PINNED_STACK_ID))
+                || finishingActivityInNonFocusedStack
                 || prevState == ActivityState.STOPPED
                 || prevState == ActivityState.INITIALIZING) {
             r.makeFinishingLocked();
             boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
+
+            if (finishingActivityInNonFocusedStack) {
+                // Finishing activity that was in paused state and it was in not currently focused
+                // stack, need to make something visible in its place.
+                mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
+            }
             if (activityRemoved) {
                 mStackSupervisor.resumeFocusedStackTopActivityLocked();
             }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 36207c4..06e5ea2 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1049,7 +1049,7 @@
             return r;
         }
 
-        // Return to the home stack.
+        // Look in other non-focused and non-home stacks.
         final ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
         for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
             final ActivityStack stack = stacks.get(stackNdx);
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 5b9d139..27d1671 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -68,7 +68,7 @@
     private static final int MAX_BROADCAST_TIME = 10*1000;
     private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
     private static final int MAX_RADIO_WAIT_TIME = 12*1000;
-    private static final int MAX_UNCRYPT_WAIT_TIME = 15*60*1000;
+    private static final int MAX_UNCRYPT_WAIT_TIME = 30*60*1000;
     // constants for progress bar. the values are roughly estimated based on timeout.
     private static final int BROADCAST_STOP_PERCENT = 2;
     private static final int ACTIVITY_MANAGER_STOP_PERCENT = 4;