Merge "Changed the overscroll and expanding behaviour." into lmp-preview-dev
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index 98f70f40..a6cddae 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -33,6 +33,8 @@
  * A service that notifies the system about whether it believes the environment of the device
  * to be trusted.
  *
+ * <p>Trust agents may only be provided by the platform.</p>
+ *
  * <p>To extend this class, you must declare the service in your manifest file with
  * the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission
  * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 55f52da..1f1ee1c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2602,6 +2602,13 @@
                 android:label="@string/permlab_trust_listener"
                 android:description="@string/permdesc_trust_listener" />
 
+    <!-- Allows an application to provide a trust agent.
+         @hide For security reasons, this is a platform-only permission. -->
+    <permission android:name="android.permission.PROVIDE_TRUST_AGENT"
+                android:protectionLevel="signatureOrSystem"
+                android:label="@string/permlab_provide_trust_agent"
+                android:description="@string/permdesc_provide_trust_agent" />
+
     <!-- Must be required by an {@link
          android.service.trust.TrustAgentService},
          to ensure that only the system can bind to it. -->
diff --git a/core/res/res/transition/fade.xml b/core/res/res/transition/fade.xml
new file mode 100644
index 0000000..22397d4
--- /dev/null
+++ b/core/res/res/transition/fade.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+<fade xmlns:android="http://schemas.android.com/apk/res/android"/>
diff --git a/core/res/res/transition/move.xml b/core/res/res/transition/move.xml
new file mode 100644
index 0000000..d4863ee
--- /dev/null
+++ b/core/res/res/transition/move.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 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.
+-->
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
+    <transitionSet>
+        <changeBounds/>
+        <changeTransform/>
+        <changeClipBounds/>
+        <targets>
+            <target android:excludeClass="android.widget.ImageView"/>
+        </targets>
+    </transitionSet>
+    <moveImage>
+        <targets>
+            <target android:targetClass="android.widget.ImageView"/>
+        </targets>
+    </moveImage>
+</transitionSet>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 5d6987c..d4465e6 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3774,6 +3774,11 @@
     <!-- Description of an application permission that lets it listen to trust state changes. -->
     <string name="permdesc_trust_listener">Allows an application to listen for changes in trust state.</string>
 
+    <!-- Title of an application permission that lets it provide a trust agent. -->
+    <string name="permlab_provide_trust_agent">Provide a trust agent.</string>
+    <!-- Description of an application permission that lets it provide a trust agent. -->
+    <string name="permdesc_provide_trust_agent">Allows an application to provide a trust agent.</string>
+
     <!-- Title of an application permission that lets it bind to a trust agent service. -->
     <string name="permlab_bind_trust_agent_service">Bind to a trust agent service</string>
     <!-- Description of an application permission that lets it bind to a trust agent service. -->
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index f47ea7a..eda7174 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -165,6 +165,9 @@
         <item name="windowActionBarFullscreenDecorLayout">@layout/screen_toolbar</item>
         <item name="statusBarColor">?attr/colorPrimaryDark</item>
         <item name="navigationBarColor">@color/black</item>
+        <item name="windowEnterTransition">@transition/fade</item>
+        <item name="windowSharedElementEnterTransition">@transition/move</item>
+        <item name="windowSharedElementExitTransition">@transition/move</item>
 
         <!-- Dialog attributes -->
         <item name="dialogTheme">@style/Theme.Quantum.Dialog</item>
diff --git a/packages/Keyguard/test/SampleTrustAgent/Android.mk b/packages/Keyguard/test/SampleTrustAgent/Android.mk
index 7551fdf..2a18ee1 100644
--- a/packages/Keyguard/test/SampleTrustAgent/Android.mk
+++ b/packages/Keyguard/test/SampleTrustAgent/Android.mk
@@ -20,9 +20,8 @@
 
 LOCAL_PACKAGE_NAME := SampleTrustAgent
 
-# Remove these to verify permission checks are working correctly
-#LOCAL_CERTIFICATE := platform
-#LOCAL_PRIVILEGED_MODULE := true
+# Remove this to verify permission checks are working correctly
+LOCAL_CERTIFICATE := platform
 
 LOCAL_MODULE_TAGS := tests
 
diff --git a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
index 7904927..f3125f1 100644
--- a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
@@ -18,6 +18,7 @@
     package="com.android.trustagent.test">
     <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17"/>
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+    <uses-permission android:name="android.permission.PROVIDE_TRUST_AGENT" />
     <application android:label="@string/app_name">
       <service
           android:name=".SampleTrustAgent"
diff --git a/packages/SystemUI/res/drawable/keyguard_overflow_number_background.xml b/packages/SystemUI/res/drawable/keyguard_overflow_number_background.xml
new file mode 100644
index 0000000..b812d43
--- /dev/null
+++ b/packages/SystemUI/res/drawable/keyguard_overflow_number_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2014 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
+  -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <solid android:color="#1a000000" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
index f867068..e13dd91 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -32,20 +32,20 @@
         />
     <TextView
         android:id="@+id/more_text"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_width="32dp"
+        android:layout_height="32dp"
+        android:layout_marginStart="18dp"
         android:layout_gravity="center_vertical"
-        android:gravity="center_horizontal"
-        android:textColor="@color/keyguard_overflow_content_color"
-        android:textAllCaps="true"
-        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:background="@drawable/keyguard_overflow_number_background"
+        android:gravity="center"
+        android:textColor="#ff686868"
+        android:textStyle="bold"
+        android:textSize="14dp"
         />
     <com.android.systemui.statusbar.NotificationOverflowIconsView
         android:id="@+id/overflow_icons_view"
-        android:layout_gravity="end|center_vertical"
-        android:gravity="end"
-        android:paddingLeft="8dp"
-        android:paddingRight="8dp"
+        android:layout_gravity="center_vertical"
+        android:layout_marginStart="64dp"
         android:layout_width="120dp"
         android:layout_height="wrap_content"
         />
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 757d4ad..34cfbe8e 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -46,7 +46,7 @@
     <drawable name="notification_item_background_color_pressed">#ff454545</drawable>
 
     <!-- Tint color for the content on the notification overflow card. -->
-    <color name="keyguard_overflow_content_color">#ff666666</color>
+    <color name="keyguard_overflow_content_color">#ff686868</color>
 
     <!-- The color of the red speed bump dot -->
     <color name="speed_bump_dot_red">#ffd50000</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b6c04f7..35bc7e3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -83,7 +83,7 @@
     <dimen name="notification_mid_height">128dp</dimen>
 
     <!-- Height of a the summary ("more card") notification on keyguard. -->
-    <dimen name="notification_summary_height">40dp</dimen>
+    <dimen name="notification_summary_height">44dp</dimen>
 
     <!-- size at which Notification icons will be drawn in the status bar -->
     <dimen name="status_bar_icon_drawing_size">18dip</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 79c7031..3ec1d4d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -558,10 +558,8 @@
     <!-- Zen mode: Short title. [CHAR LIMIT=40] -->
     <string name="zen_mode_title">Do not disturb</string>
 
-    <!-- Text for overflow card on Keyguard when there is not enough space for all notifications on Keyguard. [CHAR LIMIT=12] -->
-    <plurals name="keyguard_more_overflow_text">
-        <item quantity="other">%d more</item>
-    </plurals>
+    <!-- Text for overflow card on Keyguard when there is not enough space for all notifications on Keyguard. [CHAR LIMIT=1] -->
+    <string name="keyguard_more_overflow_text">+<xliff:g id="number_of_notifications" example="5">%d</xliff:g></string>
 
     <!-- An explanation for the visual speed bump in the notifications, which will appear when you click on it. [CHAR LIMIT=50] -->
     <string name="speed_bump_explanation">Less urgent notifications below</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 088f076..ac2537c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -69,7 +69,9 @@
                         ? MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.EXACTLY)
                         : MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
                 }
-                child.measure(widthMeasureSpec, childHeightSpec);
+                child.measure(
+                        getChildMeasureSpec(widthMeasureSpec, 0 /* padding */, layoutParams.width),
+                        childHeightSpec);
                 int childHeight = child.getMeasuredHeight();
                 maxChildHeight = Math.max(maxChildHeight, childHeight);
             } else {
@@ -79,7 +81,9 @@
         int ownHeight = hasFixedHeight ? ownMaxHeight : maxChildHeight;
         newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
         for (View child : mMatchParentViews) {
-            child.measure(widthMeasureSpec, newHeightSpec);
+            child.measure(getChildMeasureSpec(
+                    widthMeasureSpec, 0 /* padding */, child.getLayoutParams().width),
+                    newHeightSpec);
         }
         mMatchParentViews.clear();
         int width = MeasureSpec.getSize(widthMeasureSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
index ce31894..6819d9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
@@ -18,15 +18,13 @@
 
 import android.app.Notification;
 import android.content.Context;
-import android.graphics.Color;
+import android.content.res.Configuration;
 import android.graphics.PorterDuff;
 import android.util.AttributeSet;
-import android.view.View;
 import android.widget.ImageView;
-import android.widget.LinearLayout;
 import android.widget.TextView;
 
-import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.NotificationColorUtil;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.IconMerger;
 
@@ -37,6 +35,8 @@
 
     private TextView mMoreText;
     private int mTintColor;
+    private int mIconSize;
+    private NotificationColorUtil mNotificationColorUtil = new NotificationColorUtil();
 
     public NotificationOverflowIconsView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -46,6 +46,8 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mTintColor = getResources().getColor(R.color.keyguard_overflow_content_color);
+        mIconSize = getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.status_bar_icon_size);
     }
 
     public void setMoreText(TextView moreText) {
@@ -56,14 +58,24 @@
         StatusBarIconView v = new StatusBarIconView(getContext(), "",
                 notification.notification.getNotification());
         v.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
-        v.setColorFilter(mTintColor, PorterDuff.Mode.MULTIPLY);
-        addView(v);
+        addView(v, mIconSize, mIconSize);
         v.set(notification.icon.getStatusBarIcon());
+        applyColor(notification.notification.getNotification(), v);
         updateMoreText();
     }
 
+    private void applyColor(Notification notification, StatusBarIconView view) {
+        if (notification.color != Notification.COLOR_DEFAULT) {
+            if (mNotificationColorUtil.isGrayscale(view.getDrawable())) {
+                view.setColorFilter(mTintColor, PorterDuff.Mode.MULTIPLY);
+            }
+        } else {
+            view.setColorFilter(notification.color, PorterDuff.Mode.SRC_ATOP);
+        }
+    }
+
     private void updateMoreText() {
-        mMoreText.setText(getResources().getQuantityString(
-                R.plurals.keyguard_more_overflow_text, getChildCount(), getChildCount()));
+        mMoreText.setText(
+                getResources().getString(R.string.keyguard_more_overflow_text, getChildCount()));
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index e4133db..5442bc9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -638,10 +638,12 @@
         if (mHintAnimationRunning) {
             return true;
         }
-        if (x < mEdgeTapAreaWidth) {
+        if (x < mEdgeTapAreaWidth
+                && mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
             onEdgeClicked(false /* right */);
             return true;
-        } else if (x > getWidth() - mEdgeTapAreaWidth) {
+        } else if (x > getWidth() - mEdgeTapAreaWidth
+                && mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
             onEdgeClicked(true /* right */);
             return true;
         } else {
@@ -655,7 +657,7 @@
                 startUnlockHintAnimation();
                 return true;
             case StatusBarState.SHADE_LOCKED:
-                // TODO: Go to Keyguard again.
+                mStatusBar.goToKeyguard();
                 return true;
             case StatusBarState.SHADE:
                 collapse();
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 93b5ee5..c143148 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -3063,6 +3063,16 @@
     }
 
     /**
+     * Goes back to the keyguard after hanging around in {@link StatusBarState#SHADE_LOCKED}.
+     */
+    public void goToKeyguard() {
+        if (mState == StatusBarState.SHADE_LOCKED) {
+            setBarState(StatusBarState.KEYGUARD);
+            updateKeyguardState();
+        }
+    }
+
+    /**
      * @return a ViewGroup that spans the entire panel which contains the quick settings
      */
     public ViewGroup getQuickSettingsOverlayParent() {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 986cdc1..462b234 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -49,6 +49,7 @@
 import android.service.trust.TrustAgentService;
 import android.util.ArraySet;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
 import android.util.Xml;
@@ -80,6 +81,7 @@
 
     private static final Intent TRUST_AGENT_INTENT =
             new Intent(TrustAgentService.SERVICE_INTERFACE);
+    private static final String PERMISSION_PROVIDE_AGENT = Manifest.permission.PROVIDE_TRUST_AGENT;
 
     private static final int MSG_REGISTER_LISTENER = 1;
     private static final int MSG_UNREGISTER_LISTENER = 2;
@@ -181,6 +183,15 @@
                     PackageManager.GET_META_DATA, userInfo.id);
             for (ResolveInfo resolveInfo : resolveInfos) {
                 if (resolveInfo.serviceInfo == null) continue;
+
+                String packageName = resolveInfo.serviceInfo.packageName;
+                if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
+                        != PackageManager.PERMISSION_GRANTED) {
+                    Log.w(TAG, "Skipping agent because package " + packageName
+                            + " does not have permission " + PERMISSION_PROVIDE_AGENT + ".");
+                    continue;
+                }
+
                 ComponentName name = getComponentName(resolveInfo);
                 if (!enabledAgents.contains(name)) continue;