Merge "look for old intent values" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index 580cb24..c5f4816 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7044,6 +7044,7 @@
     method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
     method public android.os.Bundle getAppWidgetOptions(int);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+    method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
     method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
     method public boolean isRequestPinAppWidgetSupported();
@@ -38750,6 +38751,7 @@
     method public java.lang.String getCallerDisplayName();
     method public int getCallerDisplayNamePresentation();
     method public final long getConnectTimeMillis();
+    method public long getCreationTimeMillis();
     method public android.telecom.DisconnectCause getDisconnectCause();
     method public android.os.Bundle getExtras();
     method public android.telecom.GatewayInfo getGatewayInfo();
diff --git a/api/system-current.txt b/api/system-current.txt
index ed87cb3..9187c94 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -7504,6 +7504,7 @@
     method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
     method public android.os.Bundle getAppWidgetOptions(int);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+    method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
     method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
     method public boolean isRequestPinAppWidgetSupported();
@@ -41973,6 +41974,7 @@
     method public java.lang.String getCallerDisplayName();
     method public int getCallerDisplayNamePresentation();
     method public final long getConnectTimeMillis();
+    method public long getCreationTimeMillis();
     method public android.telecom.DisconnectCause getDisconnectCause();
     method public android.os.Bundle getExtras();
     method public android.telecom.GatewayInfo getGatewayInfo();
diff --git a/api/test-current.txt b/api/test-current.txt
index c7f2a9f..6db91be 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -7074,6 +7074,7 @@
     method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
     method public android.os.Bundle getAppWidgetOptions(int);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProviders();
+    method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForPackage(java.lang.String, android.os.UserHandle);
     method public java.util.List<android.appwidget.AppWidgetProviderInfo> getInstalledProvidersForProfile(android.os.UserHandle);
     method public static android.appwidget.AppWidgetManager getInstance(android.content.Context);
     method public boolean isRequestPinAppWidgetSupported();
@@ -38954,6 +38955,7 @@
     method public java.lang.String getCallerDisplayName();
     method public int getCallerDisplayNamePresentation();
     method public final long getConnectTimeMillis();
+    method public long getCreationTimeMillis();
     method public android.telecom.DisconnectCause getDisconnectCause();
     method public android.os.Bundle getExtras();
     method public android.telecom.GatewayInfo getGatewayInfo();
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 74a39e8..9f35e85 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -710,9 +710,9 @@
      * user may have a corporate profile. In this case the parent user profile has a
      * child profile, the corporate one.
      *
-     * @param profile The profile for which to get providers. Passing null is equivaled
-     *         to passing only the current user handle.
-     * @return The intalled providers.
+     * @param profile The profile for which to get providers. Passing null is equivalent
+     *        to querying for only the calling user.
+     * @return The installed providers.
      *
      * @see android.os.Process#myUserHandle()
      * @see android.os.UserManager#getUserProfiles()
@@ -722,7 +722,31 @@
             return Collections.emptyList();
         }
         return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
-                profile);
+                profile, null);
+    }
+
+    /**
+     * Gets the AppWidget providers for the given package and user profile. User
+     * profile can only be the current user or a profile of the current user. For
+     * example, the current user may have a corporate profile. In this case the
+     * parent user profile has a child profile, the corporate one.
+     *
+     * @param packageName The package for which to get providers. If null, this method is
+     *        equivalent to {@link #getInstalledProvidersForProfile(UserHandle)}.
+     * @param profile The profile for which to get providers. Passing null is equivalent
+     *        to querying for only the calling user.
+     * @return The installed providers.
+     *
+     * @see android.os.Process#myUserHandle()
+     * @see android.os.UserManager#getUserProfiles()
+     */
+    public List<AppWidgetProviderInfo> getInstalledProvidersForPackage(@Nullable String packageName,
+            @Nullable UserHandle profile) {
+        if (mService == null) {
+            return Collections.emptyList();
+        }
+        return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
+                profile, packageName);
     }
 
     /**
@@ -733,7 +757,7 @@
             return Collections.emptyList();
         }
         return getInstalledProvidersForProfile(AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
-                null);
+                null, null);
     }
 
     /**
@@ -752,7 +776,7 @@
         if (mService == null) {
             return Collections.emptyList();
         }
-        return getInstalledProvidersForProfile(categoryFilter, null);
+        return getInstalledProvidersForProfile(categoryFilter, null, null);
     }
 
     /**
@@ -766,6 +790,7 @@
      * @param profile A profile of the current user which to be queried. The user
      *        is itself also a profile. If null, the providers only for the current user
      *        are returned.
+     * @param packageName If specified, will only return providers from the given package.
      * @return The intalled providers.
      *
      * @see android.os.Process#myUserHandle()
@@ -774,7 +799,7 @@
      * @hide
      */
     public List<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
-            UserHandle profile) {
+            @Nullable UserHandle profile, @Nullable String packageName) {
         if (mService == null) {
             return Collections.emptyList();
         }
@@ -785,7 +810,7 @@
 
         try {
             ParceledListSlice<AppWidgetProviderInfo> providers = mService.getInstalledProvidersForProfile(
-                    categoryFilter, profile.getIdentifier());
+                    categoryFilter, profile.getIdentifier(), packageName);
             if (providers == null) {
                 return Collections.emptyList();
             }
diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
index f987a9f..caf35b3 100644
--- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
+++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl
@@ -55,8 +55,8 @@
             in RemoteViews views);
     void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views);
     void notifyAppWidgetViewDataChanged(String packageName, in int[] appWidgetIds, int viewId);
-    ParceledListSlice getInstalledProvidersForProfile(int categoryFilter,
-            int profileId);
+    ParceledListSlice getInstalledProvidersForProfile(int categoryFilter, int profileId,
+            String packageName);
     AppWidgetProviderInfo getAppWidgetInfo(String callingPackage, int appWidgetId);
     boolean hasBindAppWidgetPermission(in String packageName, int userId);
     void setBindAppWidgetPermission(in String packageName, int userId, in boolean permission);
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index a165621..5a2bf4e 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -17,27 +17,24 @@
 
 <NotificationHeaderView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:theme="@style/Theme.Material.Notification"
     android:id="@+id/notification_header"
     android:orientation="horizontal"
     android:layout_width="wrap_content"
     android:layout_height="@dimen/notification_header_height"
     android:clipChildren="false"
-    android:paddingTop="@dimen/notification_header_padding_top"
-    android:paddingBottom="@dimen/notification_header_padding_bottom"
-    android:layout_marginBottom="5dp"
-    android:paddingStart="@dimen/notification_content_margin_start"
-    android:paddingEnd="16dp">
+    style="?attr/notificationHeaderStyle">
     <com.android.internal.widget.CachingIconView
         android:id="@+id/icon"
-        android:layout_width="@dimen/notification_header_icon_size"
-        android:layout_height="@dimen/notification_header_icon_size"
+        android:layout_width="?attr/notificationHeaderIconSize"
+        android:layout_height="?attr/notificationHeaderIconSize"
         android:layout_marginEnd="3dp"
         />
     <TextView
         android:id="@+id/app_name_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+        android:textAppearance="?attr/notificationHeaderTextAppearance"
         android:layout_marginStart="3dp"
         android:layout_marginEnd="2dp"
         android:singleLine="true"
@@ -46,7 +43,7 @@
         android:id="@+id/header_text_divider"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+        android:textAppearance="?attr/notificationHeaderTextAppearance"
         android:layout_marginStart="2dp"
         android:layout_marginEnd="2dp"
         android:text="@string/notification_header_divider_symbol"
@@ -55,7 +52,7 @@
         android:id="@+id/header_text"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+        android:textAppearance="?attr/notificationHeaderTextAppearance"
         android:layout_marginStart="2dp"
         android:layout_marginEnd="2dp"
         android:visibility="gone"
@@ -64,7 +61,7 @@
         android:id="@+id/time_divider"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textAppearance="@style/TextAppearance.Material.Notification.Info"
+        android:textAppearance="?attr/notificationHeaderTextAppearance"
         android:layout_marginStart="2dp"
         android:layout_marginEnd="2dp"
         android:text="@string/notification_header_divider_symbol"
diff --git a/core/res/res/layout/notification_template_material_ambient.xml b/core/res/res/layout/notification_template_material_ambient.xml
index f3aa048..026bc6e 100644
--- a/core/res/res/layout/notification_template_material_ambient.xml
+++ b/core/res/res/layout/notification_template_material_ambient.xml
@@ -23,7 +23,8 @@
     android:paddingStart="@dimen/notification_extra_margin_ambient"
     android:paddingEnd="@dimen/notification_extra_margin_ambient"
     >
-    <include layout="@layout/notification_template_header" />
+    <include layout="@layout/notification_template_header"
+        android:theme="@style/Theme.Material.Notification.Ambient" />
 
     <LinearLayout
             android:id="@+id/notification_action_list_margin_target"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index ee73b69..0717c9d 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8635,5 +8635,12 @@
         <attr name="stackFromEnd" format="boolean" />
     </declare-styleable>
 
+    <!-- @hide -->
+    <declare-styleable name="NotificationTheme">
+        <attr name="notificationHeaderStyle" format="reference" />
+        <attr name="notificationHeaderTextAppearance" format="reference" />
+        <attr name="notificationHeaderIconSize" format="dimension" />
+    </declare-styleable>
+
     <attr name="lockPatternStyle" format="reference" />
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index b82542a..c5316c6 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -191,6 +191,9 @@
     <!-- size (width and height) of the icon in the notification header -->
     <dimen name="notification_header_icon_size">18dp</dimen>
 
+    <!-- size (width and height) of the icon in the notification header -->
+    <dimen name="notification_header_icon_size_ambient">20dp</dimen>
+
     <!-- Height of a small notification in the status bar -->
     <dimen name="notification_min_height">92dp</dimen>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 831cf89..11286f3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3172,7 +3172,7 @@
     <string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> displaying over other apps</string>
     <!-- Notification title when an application is displaying ui on-top of other apps
          [CHAR LIMIT=30] -->
-    <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps.</string>
+    <string name="alert_windows_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is displaying over other apps</string>
     <!-- Notification body when an application is displaying ui on-top of other apps
          [CHAR LIMIT=NONE] -->
     <string name="alert_windows_notification_message">If you don’t want <xliff:g id="name" example="Google Maps">%s</xliff:g> to use this feature, tap to open settings and turn it off.</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 8f061a3..ec16611 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -488,6 +488,10 @@
 
     <style name="TextAppearance.Material.Notification.Time" parent="TextAppearance.Material.Notification.Info" />
 
+    <style name="TextAppearance.Material.Notification.Info.Ambient">
+        <item name="textSize">@dimen/notification_text_size</item>
+    </style>
+
     <style name="TextAppearance.Material.Notification.Emphasis">
         <item name="textColor">#66000000</item>
     </style>
@@ -1283,4 +1287,12 @@
 
     <style name="DialogWindowTitle.Material.Light" />
 
+    <style name="Notification.Header" parent="">
+        <item name="paddingTop">@dimen/notification_header_padding_top</item>
+        <item name="paddingBottom">@dimen/notification_header_padding_bottom</item>
+        <item name="layout_marginBottom">5dp</item>
+        <item name="paddingStart">@dimen/notification_content_margin_start</item>
+        <item name="paddingEnd">16dp</item>
+    </style>
+
 </resources>
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 008c817..9dafa7a 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1321,6 +1321,19 @@
         <item name="windowNoTitle">true</item>
     </style>
 
+    <!-- Theme for inflating notifications -->
+    <style name="Theme.Material.Notification" parent="">
+        <item name="notificationHeaderStyle">@style/Notification.Header</item>
+        <item name="notificationHeaderTextAppearance">@style/TextAppearance.Material.Notification.Info</item>
+        <item name="notificationHeaderIconSize">@dimen/notification_header_icon_size</item>
+    </style>
+
+    <!-- Theme for inflating ambient notification -->
+    <style name="Theme.Material.Notification.Ambient">
+        <item name="notificationHeaderTextAppearance">@style/TextAppearance.Material.Notification.Info.Ambient</item>
+        <item name="notificationHeaderIconSize">@dimen/notification_header_icon_size_ambient</item>
+    </style>
+
     <!-- Default theme for Settings and activities launched from Settings. -->
     <style name="Theme.Material.Settings" parent="Theme.Material.Light.LightStatusBar">
         <item name="colorPrimary">@color/primary_material_settings_light</item>
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index f9342b7..fa5c3ff 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -6,6 +6,7 @@
     <string name="no_data_notification_id">Your mobile data has been deactivated</string>
     <string name="portal_notification_detail">Tap to visit the %s website</string>
     <string name="no_data_notification_detail">Please contact your service provider %s</string>
+    <string name="mobile_data_status_notification_channel_name">Mobile data status</string>
     <string name="action_bar_label">Sign in to mobile network</string>
     <string name="ssl_error_warning">The network you&#8217;re trying to join has security issues.</string>
     <string name="ssl_error_example">For example, the login page may not belong to the organization shown.</string>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index 73ff3a9..7fd1601 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -16,6 +16,7 @@
 package com.android.carrierdefaultapp;
 
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -35,6 +36,7 @@
 
     private static final String PORTAL_NOTIFICATION_TAG = "CarrierDefault.Portal.Notification";
     private static final String NO_DATA_NOTIFICATION_TAG = "CarrierDefault.NoData.Notification";
+    private static final String NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS = "mobile_data_status";
     private static final int PORTAL_NOTIFICATION_ID = 0;
     private static final int NO_DATA_NOTIFICATION_ID = 1;
     private static boolean ENABLE = true;
@@ -150,9 +152,18 @@
     private static Notification getNotification(Context context, int titleId, int textId,
                                          PendingIntent pendingIntent) {
         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+        final NotificationManager notificationManager = context.getSystemService(
+                NotificationManager.class);
         final Resources resources = context.getResources();
         final Bundle extras = Bundle.forPair(Notification.EXTRA_SUBSTITUTE_APP_NAME,
                 resources.getString(R.string.android_system_label));
+        /* Creates the notification channel and registers it with NotificationManager. If a channel
+         * with the same ID is already registered, NotificationManager will ignore this call.
+         */
+        notificationManager.createNotificationChannel(new NotificationChannel(
+                NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS,
+                resources.getString(R.string.mobile_data_status_notification_channel_name),
+                NotificationManager.IMPORTANCE_DEFAULT));
         Notification.Builder builder = new Notification.Builder(context)
                 .setContentTitle(resources.getString(titleId))
                 .setContentText(String.format(resources.getString(textId),
@@ -167,7 +178,8 @@
                 .setLocalOnly(true)
                 .setWhen(System.currentTimeMillis())
                 .setShowWhen(false)
-                .setExtras(extras);
+                .setExtras(extras)
+                .setChannel(NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS);
 
         if (pendingIntent != null) {
             builder.setContentIntent(pendingIntent);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 9efe224..d2a2919 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -242,7 +242,7 @@
         mDetailSettingsButton.setVisibility(settingsIntent != null ? VISIBLE : GONE);
         mDetailSettingsButton.setOnClickListener(v -> {
             Dependency.get(MetricsLogger.class).action(ACTION_QS_MORE_SETTINGS,
-                    mDetailAdapter.getMetricsCategory());
+                    adapter.getMetricsCategory());
             Dependency.get(ActivityStarter.class)
                     .postStartActivityDismissingKeyguard(settingsIntent, 0);
         });
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
index 21a0dc9..8298f35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInfo.java
@@ -228,6 +228,7 @@
         // Settings button.
         final TextView settingsButton = (TextView) findViewById(R.id.more_settings);
         if (mAppUid >= 0 && onSettingsClick != null) {
+            settingsButton.setVisibility(View.VISIBLE);
             final int appUidF = mAppUid;
             settingsButton.setOnClickListener(
                     (View view) -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index 5055dda..bb82b60 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -120,6 +120,9 @@
     @Override
     public void createMenu(ViewGroup parent) {
         mParent = (ExpandableNotificationRow) parent;
+        if (mMenuContainer != null) {
+            mMenuContainer.removeAllViews();
+        }
         mMenuContainer = new FrameLayout(mContext);
         for (int i = 0; i < mMenuItems.size(); i++) {
             addMenuView(mMenuItems.get(i), mMenuContainer);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 9dc0ceb..472af65 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -5010,23 +5010,25 @@
                 @Override
                 public void onPulseStarted() {
                     callback.onPulseStarted();
-                    if (!mHeadsUpManager.getAllEntries().isEmpty()) {
+                    Collection<HeadsUpManager.HeadsUpEntry> pulsingEntries =
+                            mHeadsUpManager.getAllEntries();
+                    if (!pulsingEntries.isEmpty()) {
                         // Only pulse the stack scroller if there's actually something to show.
                         // Otherwise just show the always-on screen.
-                        setPulsing(true);
+                        setPulsing(pulsingEntries);
                     }
                 }
 
                 @Override
                 public void onPulseFinished() {
                     callback.onPulseFinished();
-                    setPulsing(false);
+                    setPulsing(null);
                 }
 
-                private void setPulsing(boolean pulsing) {
+                private void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
                     mStackScroller.setPulsing(pulsing);
-                    mNotificationPanel.setPulsing(pulsing);
-                    mVisualStabilityManager.setPulsing(pulsing);
+                    mNotificationPanel.setPulsing(pulsing != null);
+                    mVisualStabilityManager.setPulsing(pulsing != null);
                 }
             }, reason);
         }
@@ -5769,12 +5771,16 @@
                     ServiceManager.getService(Context.NOTIFICATION_SERVICE));
             final String pkg = sbn.getPackageName();
             NotificationInfo info = (NotificationInfo) gutsView;
-            final NotificationInfo.OnSettingsClickListener onSettingsClick = (View v,
-                    NotificationChannel channel, int appUid) -> {
-                mMetricsLogger.action(MetricsEvent.ACTION_NOTE_INFO);
-                guts.resetFalsingCheck();
-                startAppNotificationSettingsActivity(pkg, appUid, channel);
-            };
+            // Settings link is only valid for notifications that specify a user, unless this is the
+            // system user.
+            NotificationInfo.OnSettingsClickListener onSettingsClick = null;
+            if (!userHandle.equals(UserHandle.ALL) || mCurrentUserId == UserHandle.USER_SYSTEM) {
+                onSettingsClick = (View v, NotificationChannel channel, int appUid) -> {
+                    mMetricsLogger.action(MetricsEvent.ACTION_NOTE_INFO);
+                    guts.resetFalsingCheck();
+                    startAppNotificationSettingsActivity(pkg, appUid, channel);
+                };
+            }
             final View.OnClickListener onDoneClick = (View v) -> {
                 saveAndCloseNotificationMenu(info, row, guts, v);
             };
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 5bead73..15fcb38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -72,6 +72,7 @@
 import com.android.systemui.statusbar.EmptyShadeView;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationGuts;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StackScrollerDecorView;
@@ -86,6 +87,7 @@
 import com.android.systemui.statusbar.policy.ScrollAdapter;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashSet;
@@ -331,7 +333,7 @@
         }
     };
     private PorterDuffXfermode mSrcMode = new PorterDuffXfermode(PorterDuff.Mode.SRC);
-    private boolean mPulsing;
+    private Collection<HeadsUpManager.HeadsUpEntry> mPulsing;
     private boolean mDrawBackgroundAsSrc;
     private boolean mFadingOut;
     private boolean mParentNotFullyVisible;
@@ -1917,15 +1919,19 @@
         int numShownItems = 0;
         boolean finish = false;
         int maxDisplayedNotifications = mAmbientState.isDark()
-                ? (mPulsing ? 1 : 0)
+                ? (isPulsing() ? 1 : 0)
                 : mMaxDisplayedNotifications;
 
         for (int i = 0; i < getChildCount(); i++) {
             ExpandableView expandableView = (ExpandableView) getChildAt(i);
             if (expandableView.getVisibility() != View.GONE
                     && !expandableView.hasNoContentHeight()) {
-                if (maxDisplayedNotifications != -1
-                        && numShownItems >= maxDisplayedNotifications) {
+                boolean limitReached = maxDisplayedNotifications != -1
+                        && numShownItems >= maxDisplayedNotifications;
+                boolean notificationOnAmbientThatIsNotPulsing = isPulsing()
+                        && expandableView instanceof ExpandableNotificationRow
+                        && !isPulsing(((ExpandableNotificationRow) expandableView).getEntry());
+                if (limitReached || notificationOnAmbientThatIsNotPulsing) {
                     expandableView = mShelf;
                     finish = true;
                 }
@@ -1971,6 +1977,19 @@
         mAmbientState.setLayoutMaxHeight(mContentHeight);
     }
 
+    private boolean isPulsing(NotificationData.Entry entry) {
+        for (HeadsUpManager.HeadsUpEntry e : mPulsing) {
+            if (e.entry == entry) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isPulsing() {
+        return mPulsing != null;
+    }
+
     private void updateScrollability() {
         boolean scrollable = getScrollRange() > 0;
         if (scrollable != mScrollable) {
@@ -2784,7 +2803,7 @@
     }
 
     private void updateNotificationAnimationStates() {
-        boolean running = mAnimationsEnabled || mPulsing;
+        boolean running = mAnimationsEnabled || isPulsing();
         mShelf.setAnimationsEnabled(running);
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -2795,7 +2814,7 @@
     }
 
     private void updateAnimationState(View child) {
-        updateAnimationState((mAnimationsEnabled || mPulsing)
+        updateAnimationState((mAnimationsEnabled || isPulsing())
                 && (mIsExpanded || isPinnedHeadsUp(child)), child);
     }
 
@@ -4055,12 +4074,12 @@
         return mIsExpanded;
     }
 
-    public void setPulsing(boolean pulsing) {
-        if (mPulsing == pulsing) {
+    public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+        if (mPulsing == null && pulsing == null) {
             return;
         }
         mPulsing = pulsing;
-        mAmbientState.setPulsing(pulsing);
+        mAmbientState.setPulsing(isPulsing());
         updateNotificationAnimationStates();
         updateContentHeight();
         notifyHeightChangeListener(mShelf);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
index c67cccc..8609eeb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSDetailTest.java
@@ -100,4 +100,10 @@
         ViewUtils.detachView(mQsDetail);
         mTestableLooper.processAllMessages();
     }
+
+    @Test
+    public void testNullAdapterClick() {
+        mQsDetail.setupDetailFooter(mock(DetailAdapter.class));
+        mQsDetail.findViewById(android.R.id.button2).performClick();
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
index 21930a3..0621f4a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationInfoTest.java
@@ -206,6 +206,29 @@
     }
 
     @Test
+    public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+                null, null, null, null);
+        final TextView settingsButton =
+                (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+        assertTrue(settingsButton.getVisibility() != View.VISIBLE);
+    }
+
+    @Test
+    public void testBindNotification_SettingsButtonReappersAfterSecondBind() throws Exception {
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+                null, null, null, null);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, Arrays.asList(mNotificationChannel),
+                (View v, NotificationChannel c, int appUid) -> {}, null, null, null);
+        final TextView settingsButton =
+                (TextView) mNotificationInfo.findViewById(R.id.more_settings);
+        assertEquals(View.VISIBLE, settingsButton.getVisibility());
+    }
+
+    @Test
     public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
index 31b9bae..efb9fea4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationMenuRowTest.java
@@ -44,4 +44,11 @@
         ViewUtils.detachView(row.getMenuView());
         TestableLooper.get(this).processAllMessages();
     }
+
+    @Test
+    public void testRecreateMenu() {
+        NotificationMenuRowPlugin row = new NotificationMenuRow(mContext);
+        row.createMenu(null);
+        row.createMenu(null);
+    }
 }
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 0482e73..ac81565 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -1631,7 +1631,7 @@
 
     @Override
     public ParceledListSlice<AppWidgetProviderInfo> getInstalledProvidersForProfile(int categoryFilter,
-            int profileId) {
+            int profileId, String packageName) {
         final int userId = UserHandle.getCallingUserId();
 
         if (DEBUG) {
@@ -1653,8 +1653,11 @@
                 Provider provider = mProviders.get(i);
                 AppWidgetProviderInfo info = provider.info;
 
-                // Ignore an invalid provider or one not matching the filter.
-                if (provider.zombie || (info.widgetCategory & categoryFilter) == 0) {
+                // Ignore an invalid provider, one not matching the filter,
+                // or one that isn't in the given package, if any.
+                boolean inPackage = packageName == null
+                        || provider.id.componentName.getPackageName().equals(packageName);
+                if (provider.zombie || (info.widgetCategory & categoryFilter) == 0 || !inPackage) {
                     continue;
                 }
 
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index b72cd73..3e3fee5 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -745,7 +745,7 @@
     }
 
     /**
-     * Returns a {@link TaskRecord} for the input id if available. Null otherwise.
+     * Returns a {@link TaskRecord} for the input id if available. {@code null} otherwise.
      * @param id Id of the task we would like returned.
      * @param matchMode The mode to match the given task id in.
      * @param stackId The stack to restore the task to (default launch stack will be used if
@@ -765,7 +765,7 @@
             ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
             for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                 ActivityStack stack = stacks.get(stackNdx);
-                TaskRecord task = stack.taskForIdLocked(id);
+                final TaskRecord task = stack.taskForIdLocked(id);
                 if (task != null) {
                     return task;
                 }
@@ -780,11 +780,17 @@
         // Otherwise, check the recent tasks and return if we find it there and we are not restoring
         // the task from recents
         if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents");
-        TaskRecord task = mRecentTasks.taskForIdLocked(id);
-        if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
-            if (DEBUG_RECENTS && task == null) {
+        final TaskRecord task = mRecentTasks.taskForIdLocked(id);
+
+        if (task == null) {
+            if (DEBUG_RECENTS) {
                 Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents");
             }
+
+            return null;
+        }
+
+        if (matchMode == MATCH_TASK_IN_STACKS_OR_RECENT_TASKS) {
             return task;
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
index af3201c..54ecab3 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityRecordTests.java
@@ -33,8 +33,7 @@
  *  bit FrameworksServicesTests:com.android.server.am.ActivityRecordTests
  */
 @MediumTest
-// TODO(b/36916522): Currently failing in CI.
-// @Presubmit
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ActivityRecordTests extends ActivityTestsBase {
     private final ComponentName testActivityComponent =
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
new file mode 100644
index 0000000..b59c2bc
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStackSupervisorTests.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2017 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 org.junit.Assert.assertNull;
+
+import android.os.Debug;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.runner.RunWith;
+import org.junit.Test;
+
+import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE;
+
+/**
+ * Tests for the {@link ActivityStackSupervisor} class.
+ *
+ * Build/Install/Run:
+ *  bit FrameworksServicesTests:com.android.server.am.ActivityStackSupervisorTests
+ */
+@MediumTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class ActivityStackSupervisorTests extends ActivityTestsBase {
+    /**
+     * This test ensures that we do not try to restore a task based off an invalid task id. The
+     * stack supervisor is a test version so there will be no tasks present. We should expect
+     * {@code null} to be returned in this case.
+     */
+    @Test
+    public void testRestoringInvalidTask() throws Exception {
+        Debug.waitForDebugger();
+        final ActivityManagerService service = createActivityManagerService();
+        TaskRecord task = service.mStackSupervisor.anyTaskForIdLocked(0 /*taskId*/,
+                MATCH_TASK_IN_STACKS_OR_RECENT_TASKS_AND_RESTORE, 0 /*stackId*/);
+        assertNull(task);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
index c5cc2ff..5240586 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
@@ -25,7 +25,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
-import android.os.Handler;
+import android.os.HandlerThread;
 import android.os.Looper;
 import android.support.test.InstrumentationRegistry;
 import com.android.server.AttributeCache;
@@ -34,6 +34,7 @@
 
 import com.android.server.wm.WindowManagerService;
 import com.android.server.wm.WindowTestUtils;
+import org.junit.After;
 import org.junit.Before;
 import org.mockito.MockitoAnnotations;
 
@@ -42,8 +43,7 @@
  */
 public class ActivityTestsBase {
     private final Context mContext = InstrumentationRegistry.getContext();
-    private static boolean sLooperPrepared;
-    private Handler mHandler;
+    private HandlerThread mHandlerThread;
 
     // Grabbing an instance of {@link WindowManagerService} creates it if not present so this must
     // be called at before any tests.
@@ -52,11 +52,13 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
+        mHandlerThread = new HandlerThread("ActivityTestsBaseThread");
+        mHandlerThread.start();
+    }
 
-        if (!sLooperPrepared) {
-            sLooperPrepared = true;
-            Looper.prepare();
-        }
+    @After
+    public void tearDown() {
+        mHandlerThread.quitSafely();
     }
 
     protected ActivityManagerService createActivityManagerService() {
@@ -126,7 +128,7 @@
 
         @Override
         protected ActivityStackSupervisor createStackSupervisor() {
-            return new TestActivityStackSupervisor(this, new Handler().getLooper());
+            return new TestActivityStackSupervisor(this, mHandlerThread.getLooper());
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
index f3f68ff..2663aaf 100644
--- a/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appwidget/AppWidgetServiceImplTest.java
@@ -50,6 +50,7 @@
 
 import org.mockito.ArgumentCaptor;
 
+import java.util.Iterator;
 import java.util.List;
 import java.util.Random;
 import java.util.concurrent.CountDownLatch;
@@ -249,6 +250,25 @@
         assertEquals(7, updates.size());
     }
 
+    public void testGetInstalledProvidersForPackage() {
+        List<AppWidgetProviderInfo> allProviders = mManager.getInstalledProviders();
+        assertTrue(!allProviders.isEmpty());
+        String packageName = allProviders.get(0).provider.getPackageName();
+        List<AppWidgetProviderInfo> providersForPackage = mManager.getInstalledProvidersForPackage(
+                packageName, null);
+        // Remove providers from allProviders that don't have the given package name.
+        Iterator<AppWidgetProviderInfo> iter = allProviders.iterator();
+        while (iter.hasNext()) {
+            if (!iter.next().provider.getPackageName().equals(packageName)) {
+                iter.remove();
+            }
+        }
+        assertEquals(allProviders.size(), providersForPackage.size());
+        for (int i = 0; i < allProviders.size(); i++) {
+            assertEquals(allProviders.get(i).provider, providersForPackage.get(i).provider);
+        }
+    }
+
     private int setupHostAndWidget() {
         List<PendingHostUpdate> updates = mService.startListening(
                 mMockHost, mPkgName, HOST_ID, new int[0]).getList();
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 92233b1..f80ee73 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -356,6 +356,7 @@
         private final StatusHints mStatusHints;
         private final Bundle mExtras;
         private final Bundle mIntentExtras;
+        private final long mCreationTimeMillis;
 
         /**
          * Whether the supplied capabilities  supports the specified capability.
@@ -578,9 +579,12 @@
         }
 
         /**
-         * @return The time the {@code Call} has been connected. This information is updated
-         * periodically, but user interfaces should not rely on this to display any "call time
-         * clock".
+         * Returns the time the {@link Call} connected (i.e. became active).  This information is
+         * updated periodically, but user interfaces should not rely on this to display the "call
+         * time clock".  For the time when the call was first added to Telecom, see
+         * {@link #getCreationTimeMillis()}.
+         *
+         * @return The time the {@link Call} connected in milliseconds since the epoch.
          */
         public final long getConnectTimeMillis() {
             return mConnectTimeMillis;
@@ -622,6 +626,18 @@
             return mIntentExtras;
         }
 
+        /**
+         * Returns the time when the call was first created and added to Telecom.  This is the same
+         * time that is logged as the start time in the Call Log (see
+         * {@link android.provider.CallLog.Calls#DATE}).  To determine when the call was connected
+         * (became active), see {@link #getConnectTimeMillis()}.
+         *
+         * @return The creation time of the call, in millis since the epoch.
+         */
+        public long getCreationTimeMillis() {
+            return mCreationTimeMillis;
+        }
+
         @Override
         public boolean equals(Object o) {
             if (o instanceof Details) {
@@ -641,28 +657,29 @@
                         Objects.equals(mVideoState, d.mVideoState) &&
                         Objects.equals(mStatusHints, d.mStatusHints) &&
                         areBundlesEqual(mExtras, d.mExtras) &&
-                        areBundlesEqual(mIntentExtras, d.mIntentExtras);
+                        areBundlesEqual(mIntentExtras, d.mIntentExtras) &&
+                        Objects.equals(mCreationTimeMillis, d.mCreationTimeMillis);
             }
             return false;
         }
 
         @Override
         public int hashCode() {
-            return
-                    Objects.hashCode(mHandle) +
-                    Objects.hashCode(mHandlePresentation) +
-                    Objects.hashCode(mCallerDisplayName) +
-                    Objects.hashCode(mCallerDisplayNamePresentation) +
-                    Objects.hashCode(mAccountHandle) +
-                    Objects.hashCode(mCallCapabilities) +
-                    Objects.hashCode(mCallProperties) +
-                    Objects.hashCode(mDisconnectCause) +
-                    Objects.hashCode(mConnectTimeMillis) +
-                    Objects.hashCode(mGatewayInfo) +
-                    Objects.hashCode(mVideoState) +
-                    Objects.hashCode(mStatusHints) +
-                    Objects.hashCode(mExtras) +
-                    Objects.hashCode(mIntentExtras);
+            return Objects.hash(mHandle,
+                            mHandlePresentation,
+                            mCallerDisplayName,
+                            mCallerDisplayNamePresentation,
+                            mAccountHandle,
+                            mCallCapabilities,
+                            mCallProperties,
+                            mDisconnectCause,
+                            mConnectTimeMillis,
+                            mGatewayInfo,
+                            mVideoState,
+                            mStatusHints,
+                            mExtras,
+                            mIntentExtras,
+                            mCreationTimeMillis);
         }
 
         /** {@hide} */
@@ -681,7 +698,8 @@
                 int videoState,
                 StatusHints statusHints,
                 Bundle extras,
-                Bundle intentExtras) {
+                Bundle intentExtras,
+                long creationTimeMillis) {
             mTelecomCallId = telecomCallId;
             mHandle = handle;
             mHandlePresentation = handlePresentation;
@@ -697,6 +715,7 @@
             mStatusHints = statusHints;
             mExtras = extras;
             mIntentExtras = intentExtras;
+            mCreationTimeMillis = creationTimeMillis;
         }
 
         /** {@hide} */
@@ -716,7 +735,8 @@
                     parcelableCall.getVideoState(),
                     parcelableCall.getStatusHints(),
                     parcelableCall.getExtras(),
-                    parcelableCall.getIntentExtras());
+                    parcelableCall.getIntentExtras(),
+                    parcelableCall.getCreationTimeMillis());
         }
 
         @Override
diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java
index 85a92d1..6212a77 100644
--- a/telecomm/java/android/telecom/ParcelableCall.java
+++ b/telecomm/java/android/telecom/ParcelableCall.java
@@ -59,6 +59,7 @@
     private final List<String> mConferenceableCallIds;
     private final Bundle mIntentExtras;
     private final Bundle mExtras;
+    private final long mCreationTimeMillis;
 
     public ParcelableCall(
             String id,
@@ -85,7 +86,8 @@
             int videoState,
             List<String> conferenceableCallIds,
             Bundle intentExtras,
-            Bundle extras) {
+            Bundle extras,
+            long creationTimeMillis) {
         mId = id;
         mState = state;
         mDisconnectCause = disconnectCause;
@@ -111,6 +113,7 @@
         mConferenceableCallIds = Collections.unmodifiableList(conferenceableCallIds);
         mIntentExtras = intentExtras;
         mExtras = extras;
+        mCreationTimeMillis = creationTimeMillis;
     }
 
     /** The unique ID of the call. */
@@ -289,6 +292,13 @@
         return mIsVideoCallProviderChanged;
     }
 
+    /**
+     * @return The time the call was created, in milliseconds since the epoch.
+     */
+    public long getCreationTimeMillis() {
+        return mCreationTimeMillis;
+    }
+
     /** Responsible for creating ParcelableCall objects for deserialized Parcels. */
     public static final Parcelable.Creator<ParcelableCall> CREATOR =
             new Parcelable.Creator<ParcelableCall> () {
@@ -324,6 +334,7 @@
             int supportedAudioRoutes = source.readInt();
             boolean isRttCallChanged = source.readByte() == 1;
             ParcelableRttCall rttCall = source.readParcelable(classLoader);
+            long creationTimeMillis = source.readLong();
             return new ParcelableCall(
                     id,
                     state,
@@ -349,7 +360,8 @@
                     videoState,
                     conferenceableCallIds,
                     intentExtras,
-                    extras);
+                    extras,
+                    creationTimeMillis);
         }
 
         @Override
@@ -393,6 +405,7 @@
         destination.writeInt(mSupportedAudioRoutes);
         destination.writeByte((byte) (mIsRttCallChanged ? 1 : 0));
         destination.writeParcelable(mRttCall, 0);
+        destination.writeLong(mCreationTimeMillis);
     }
 
     @Override