Merge "Ensuring builds compile for both 32 bit and 64 bit targets." into nyc-dev
diff --git a/api/system-current.txt b/api/system-current.txt
index 057f88d..3ccd7e0 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -24617,6 +24617,7 @@
     method public android.media.tv.TvInputInfo.Builder setHdmiDeviceInfo(android.hardware.hdmi.HdmiDeviceInfo);
     method public android.media.tv.TvInputInfo.Builder setIcon(android.graphics.drawable.Icon);
     method public android.media.tv.TvInputInfo.Builder setIcon(android.graphics.drawable.Icon, int);
+    method public android.media.tv.TvInputInfo.Builder setLabel(java.lang.CharSequence);
     method public android.media.tv.TvInputInfo.Builder setLabel(int);
     method public android.media.tv.TvInputInfo.Builder setParentId(java.lang.String);
     method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 3f22385..4c4f128 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -440,6 +440,11 @@
                 compatInfo);
         classLoader = classLoader != null ? classLoader : ClassLoader.getSystemClassLoader();
 
+        if (DEBUG) {
+            Slog.d(TAG, "createBaseActivityResources activity=" + activityToken
+                    + " with key=" + key);
+        }
+
         synchronized (this) {
             final ActivityResources activityResources = getOrCreateActivityResourcesStructLocked(
                     activityToken);
@@ -651,6 +656,16 @@
                 activityResources.overrideConfig.setToDefaults();
             }
 
+            if (DEBUG) {
+                Throwable here = new Throwable();
+                here.fillInStackTrace();
+                Slog.d(TAG, "updating resources override for activity=" + activityToken
+                        + " from oldConfig=" + Configuration.resourceQualifierString(oldConfig)
+                        + " to newConfig="
+                        + Configuration.resourceQualifierString(activityResources.overrideConfig),
+                        here);
+            }
+
             final boolean activityHasOverrideConfig =
                     !activityResources.overrideConfig.equals(Configuration.EMPTY);
 
@@ -692,9 +707,15 @@
                         oldKey.mOverlayDirs, oldKey.mLibDirs, oldKey.mDisplayId,
                         rebasedOverrideConfig, oldKey.mCompatInfo);
 
+                if (DEBUG) {
+                    Slog.d(TAG, "rebasing ref=" + resources + " from oldKey=" + oldKey
+                            + " to newKey=" + newKey);
+                }
+
                 ResourcesImpl resourcesImpl = findResourcesImplForKeyLocked(newKey);
                 if (resourcesImpl == null) {
                     resourcesImpl = createResourcesImpl(newKey);
+                    mResourceImpls.put(newKey, new WeakReference<>(resourcesImpl));
                 }
 
                 if (resourcesImpl != resources.getImpl()) {
diff --git a/core/java/android/print/PrinterCapabilitiesInfo.java b/core/java/android/print/PrinterCapabilitiesInfo.java
index af41654..01c23f6 100644
--- a/core/java/android/print/PrinterCapabilitiesInfo.java
+++ b/core/java/android/print/PrinterCapabilitiesInfo.java
@@ -233,7 +233,7 @@
 
         mDuplexModes = parcel.readInt();
         enforceValidMask(mDuplexModes,
-                (currentMode) -> PrintAttributes.enforceValidColorMode(currentMode));
+                (currentMode) -> PrintAttributes.enforceValidDuplexMode(currentMode));
 
         readDefaults(parcel);
         Preconditions.checkArgument(mMediaSizes.size() > mDefaults[PROPERTY_MEDIA_SIZE]);
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index acf94f4c..03dc699 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -116,10 +116,10 @@
     private final int mType;
     private final boolean mIsHardwareInput;
 
-    // TODO: Remove mLabel and mIconUri when createTvInputInfo() is removed.
-    private String mLabel;
+    // TODO: Remove mIconUri when createTvInputInfo() is removed.
     private Uri mIconUri;
 
+    private final CharSequence mLabel;
     private final int mLabelResId;
     private final Icon mIcon;
     private final Icon mIconStandby;
@@ -161,8 +161,8 @@
         TvInputInfo info = new TvInputInfo.Builder(context, service)
                 .setHdmiDeviceInfo(hdmiDeviceInfo)
                 .setParentId(parentId)
+                .setLabel(label)
                 .build();
-        info.mLabel = label;
         info.mIconUri = iconUri;
         return info;
     }
@@ -215,8 +215,8 @@
                     throws XmlPullParserException, IOException {
         TvInputInfo info = new TvInputInfo.Builder(context, service)
                 .setTvInputHardwareInfo(hardwareInfo)
+                .setLabel(label)
                 .build();
-        info.mLabel = label;
         info.mIconUri = iconUri;
         return info;
     }
@@ -247,7 +247,7 @@
     }
 
     private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput,
-            int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
+            CharSequence label, int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
             String setupActivity, String settingsActivity, boolean canRecord, int tunerCount,
             HdmiDeviceInfo hdmiDeviceInfo, boolean isConnectedToHdmiSwitch, String parentId,
             Bundle extras) {
@@ -255,6 +255,7 @@
         mId = id;
         mType = type;
         mIsHardwareInput = isHardwareInput;
+        mLabel = label;
         mLabelResId = labelResId;
         mIcon = icon;
         mIconStandby = iconStandby;
@@ -570,7 +571,7 @@
         dest.writeString(mId);
         dest.writeInt(mType);
         dest.writeByte(mIsHardwareInput ? (byte) 1 : 0);
-        dest.writeString(mLabel);
+        TextUtils.writeToParcel(mLabel, dest, flags);
         dest.writeParcelable(mIconUri, flags);
         dest.writeInt(mLabelResId);
         dest.writeParcelable(mIcon, flags);
@@ -612,7 +613,7 @@
         mId = in.readString();
         mType = in.readInt();
         mIsHardwareInput = in.readByte() == 1;
-        mLabel = in.readString();
+        mLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
         mIconUri = in.readParcelable(null);
         mLabelResId = in.readInt();
         mIcon = in.readParcelable(null);
@@ -660,6 +661,7 @@
 
         private final Context mContext;
         private final ResolveInfo mResolveInfo;
+        private CharSequence mLabel;
         private int mLabelResId;
         private Icon mIcon;
         private Icon mIconStandby;
@@ -746,12 +748,31 @@
         /**
          * Sets the label.
          *
+         * @param label The text to be used as label.
+         * @return This Builder object to allow for chaining of calls to builder methods.
+         * @hide
+         */
+        @SystemApi
+        public Builder setLabel(CharSequence label) {
+            if (mLabelResId != 0) {
+                throw new IllegalStateException("Resource ID for label is already set.");
+            }
+            this.mLabel = label;
+            return this;
+        }
+
+        /**
+         * Sets the label.
+         *
          * @param resId The resource ID of the text to use.
          * @return This Builder object to allow for chaining of calls to builder methods.
          * @hide
          */
         @SystemApi
         public Builder setLabel(int resId) {
+            if (mLabel != null) {
+                throw new IllegalStateException("Label text is already set.");
+            }
             this.mLabelResId = resId;
             return this;
         }
@@ -868,8 +889,8 @@
                 type = TYPE_TUNER;
             }
             parseServiceMetadata(type);
-            return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabelResId, mIcon,
-                    mIconStandby, mIconDisconnected, mSetupActivity, mSettingsActivity,
+            return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabel, mLabelResId,
+                    mIcon, mIconStandby, mIconDisconnected, mSetupActivity, mSettingsActivity,
                     mCanRecord == null ? false : mCanRecord, mTunerCount == null ? 0 : mTunerCount,
                     mHdmiDeviceInfo, isConnectedToHdmiSwitch, mParentId, mExtras);
         }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 70b478a..9606eab54 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -272,6 +272,7 @@
 
     @Override
     public boolean onOptionsItemSelected(MenuItem item) {
+        Metrics.logMenuAction(this, item.getItemId());
 
         switch (item.getItemId()) {
             case android.R.id.home:
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 68c0c2a..e7d7ec4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -212,19 +212,22 @@
             case R.id.menu_create_dir:
                 assert(canCreateDirectory());
                 showCreateDirectoryDialog();
-                return true;
+                break;
             case R.id.menu_new_window:
                 createNewWindow();
-                return true;
+                break;
             case R.id.menu_paste_from_clipboard:
                 DirectoryFragment dir = getDirectoryFragment();
                 if (dir != null) {
                     dir.pasteFromClipboard();
                 }
-                return true;
+                break;
+            default:
+                return super.onOptionsItemSelected(item);
         }
 
-        return super.onOptionsItemSelected(item);
+        Metrics.logMenuAction(this, item.getItemId());
+        return true;
     }
 
     private void createNewWindow() {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index 99663e3..1e01c22 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -69,6 +69,7 @@
     private static final String COUNT_DRAWER_OPENED = "docsui_drawer_opened";
     private static final String COUNT_DRAG_N_DROP = "docsui_drag_n_drop";
     private static final String COUNT_SEARCH = "docsui_search";
+    private static final String COUNT_MENU_ACTION = "docsui_menu_action";
 
     // Indices for bucketing roots in the roots histogram. "Other" is the catch-all index for any
     // root that is not explicitly recognized by the Metrics code (see {@link
@@ -198,8 +199,71 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface MetricsOpType {}
 
-    // Codes representing different launch actions. These are used for bucketing stats in the
-    // COUNT_LAUNCH_ACTION histogram.
+    // Codes representing different provider types.  Used for sorting file operations when logging.
+    private static final int PROVIDER_INTRA = 0;
+    private static final int PROVIDER_SYSTEM = 1;
+    private static final int PROVIDER_EXTERNAL = 2;
+
+    @IntDef(flag = false, value = {
+            PROVIDER_INTRA,
+            PROVIDER_SYSTEM,
+            PROVIDER_EXTERNAL
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Provider {}
+
+
+    // Codes representing different menu actions. These are used for bucketing stats in the
+    // COUNT_MENU_ACTION histogram.
+    // Both regular toolbar menu and action mode menu operations are included.
+    // Do not change or rearrange these values, that will break historical data. Only add to the
+    // list.
+    // Do not use negative numbers or zero; clearcut only handles positive integers.
+    private static final int ACTION_MENU_OTHER = 1;
+    private static final int ACTION_MENU_GRID = 2;
+    private static final int ACTION_MENU_LIST = 3;
+    private static final int ACTION_MENU_SORT = 4;
+    private static final int ACTION_MENU_SORT_NAME = 5;
+    private static final int ACTION_MENU_SORT_DATE = 6;
+    private static final int ACTION_MENU_SORT_SIZE = 7;
+    private static final int ACTION_MENU_SEARCH = 8;
+    private static final int ACTION_MENU_SHOW_SIZE = 9;
+    private static final int ACTION_MENU_SETTINGS = 10;
+    private static final int ACTION_MENU_COPY_TO = 11;
+    private static final int ACTION_MENU_MOVE_TO = 12;
+    private static final int ACTION_MENU_DELETE = 13;
+    private static final int ACTION_MENU_RENAME = 14;
+    private static final int ACTION_MENU_CREATE_DIR = 15;
+    private static final int ACTION_MENU_SELECT_ALL = 16;
+    private static final int ACTION_MENU_SHARE = 17;
+    private static final int ACTION_MENU_OPEN = 18;
+    private static final int ACTION_MENU_ADVANCED = 19;
+
+    @IntDef(flag = false, value = {
+            ACTION_MENU_OTHER,
+            ACTION_MENU_GRID,
+            ACTION_MENU_LIST,
+            ACTION_MENU_SORT,
+            ACTION_MENU_SORT_NAME,
+            ACTION_MENU_SORT_DATE,
+            ACTION_MENU_SORT_SIZE,
+            ACTION_MENU_SHOW_SIZE,
+            ACTION_MENU_SETTINGS,
+            ACTION_MENU_COPY_TO,
+            ACTION_MENU_MOVE_TO,
+            ACTION_MENU_DELETE,
+            ACTION_MENU_RENAME,
+            ACTION_MENU_CREATE_DIR,
+            ACTION_MENU_SELECT_ALL,
+            ACTION_MENU_SHARE,
+            ACTION_MENU_OPEN,
+            ACTION_MENU_ADVANCED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface MenuAction {}
+
+    // Codes representing different menu actions. These are used for bucketing stats in the
+    // COUNT_MENU_ACTION histogram.
     // Do not change or rearrange these values, that will break historical data. Only add to the
     // list.
     // Do not use negative numbers or zero; clearcut only handles positive integers.
@@ -225,19 +289,6 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface MetricsAction {}
 
-    // Codes representing different provider types.  Used for sorting file operations when logging.
-    private static final int PROVIDER_INTRA = 0;
-    private static final int PROVIDER_SYSTEM = 1;
-    private static final int PROVIDER_EXTERNAL = 2;
-
-    @IntDef(flag = true, value = {
-            PROVIDER_INTRA,
-            PROVIDER_SYSTEM,
-            PROVIDER_EXTERNAL
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface Provider {}
-
     // Codes representing different actions to open the drawer. They are used for bucketing stats in
     // the COUNT_DRAWER_OPENED histogram.
     // Do not change or rearrange these values, that will break historical data. Only add to the
@@ -589,6 +640,74 @@
     }
 
     /**
+     * Logs menu action that was selected by user.
+     * @param context
+     * @param id Resource id of the menu item.
+     */
+    public static void logMenuAction(Context context, int id) {
+        @MenuAction int menuAction = ACTION_MENU_OTHER;
+        switch (id) {
+            case R.id.menu_grid:
+                menuAction = ACTION_MENU_GRID;
+                break;
+            case R.id.menu_list:
+                menuAction = ACTION_MENU_LIST;
+                break;
+            case R.id.menu_sort:
+                menuAction = ACTION_MENU_SORT;
+                break;
+            case R.id.menu_sort_name:
+                menuAction = ACTION_MENU_SORT_NAME;
+                break;
+            case R.id.menu_sort_date:
+                menuAction = ACTION_MENU_SORT_DATE;
+                break;
+            case R.id.menu_sort_size:
+                menuAction = ACTION_MENU_SORT_SIZE;
+                break;
+            case R.id.menu_search:
+                menuAction = ACTION_MENU_SEARCH;
+                break;
+            case R.id.menu_file_size:
+                menuAction = ACTION_MENU_SHOW_SIZE;
+                break;
+            case R.id.menu_settings:
+                menuAction = ACTION_MENU_SETTINGS;
+                break;
+            case R.id.menu_copy_to:
+                menuAction = ACTION_MENU_COPY_TO;
+                break;
+            case R.id.menu_move_to:
+                menuAction = ACTION_MENU_MOVE_TO;
+                break;
+            case R.id.menu_delete:
+                menuAction = ACTION_MENU_DELETE;
+                break;
+            case R.id.menu_rename:
+                menuAction = ACTION_MENU_RENAME;
+                break;
+            case R.id.menu_create_dir:
+                menuAction = ACTION_MENU_CREATE_DIR;
+                break;
+            case R.id.menu_select_all:
+                menuAction = ACTION_MENU_SELECT_ALL;
+                break;
+            case R.id.menu_share:
+                menuAction = ACTION_MENU_SHARE;
+                break;
+            case R.id.menu_open:
+                menuAction = ACTION_MENU_OPEN;
+                break;
+            case R.id.menu_advanced:
+                menuAction = ACTION_MENU_ADVANCED;
+                break;
+            default:
+                break;
+        }
+        logHistogram(context, COUNT_MENU_ACTION, menuAction);
+    }
+
+    /**
      * Internal method for making a MetricsLogger.count call. Increments the given counter by 1.
      *
      * @param context
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
index 11b8891..945ed34 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
@@ -185,6 +185,9 @@
         if(mFullBar) {
             Menu menu = mActionBar.getMenu();
             menu.setGroupVisible(R.id.group_hide_when_searching, false);
+        } else {
+            // If search in full-bar mode it will be logged in FilesActivity#onOptionsItemSelected
+            Metrics.logMenuAction(mActionBar.getContext(), R.id.menu_search);
         }
     }
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 02f72b4..d70a899 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -595,6 +595,7 @@
 
         @Override
         public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+            Metrics.logMenuAction(getContext(), item.getItemId());
 
             Selection selection = mSelectionManager.getSelection(new Selection());
 
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 0d70e99..811b48f 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -2738,12 +2738,21 @@
 
     // Called when WindowManager has finished animating the launchingBehind activity to the back.
     void handleLaunchTaskBehindCompleteLocked(ActivityRecord r) {
-        r.mLaunchTaskBehind = false;
         final TaskRecord task = r.task;
-        task.setLastThumbnailLocked(task.stack.screenshotActivitiesLocked(r));
+        final ActivityStack stack = task.stack;
+
+        r.mLaunchTaskBehind = false;
+        task.setLastThumbnailLocked(stack.screenshotActivitiesLocked(r));
         mRecentTasks.addLocked(task);
         mService.notifyTaskStackChangedLocked();
         mWindowManager.setAppVisibility(r.appToken, false);
+
+        // When launching tasks behind, update the last active time of the top task after the new
+        // task has been shown briefly
+        final ActivityRecord top = stack.topActivity();
+        if (top != null) {
+            top.task.touchActiveTime();
+        }
     }
 
     void scheduleLaunchTaskBehindComplete(IBinder token) {
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index b157070..e32d1d1 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -285,6 +285,7 @@
         mCallingPackage = info.packageName;
         setIntent(_intent, info);
         setMinDimensions(info);
+        touchActiveTime();
     }
 
     TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
@@ -315,6 +316,7 @@
         taskType = APPLICATION_ACTIVITY_TYPE;
         mTaskToReturnTo = HOME_ACTIVITY_TYPE;
         lastTaskDescription = _taskDescription;
+        touchActiveTime();
     }
 
     private TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
diff --git a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
index ed7351f8..033312b 100644
--- a/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
+++ b/tests/AppLaunch/src/com/android/tests/applaunch/AppLaunch.java
@@ -62,7 +62,7 @@
     private static final String KEY_REQUIRED_ACCOUNTS = "required_accounts";
     private static final String WEARABLE_ACTION_GOOGLE =
             "com.google.android.wearable.action.GOOGLE";
-    private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 7500; //7.5s to allow app to idle
+    private static final int INITIAL_LAUNCH_IDLE_TIMEOUT = 60000; //60s to allow app to idle
     private static final int POST_LAUNCH_IDLE_TIMEOUT = 750; //750ms idle for non initial launches
     private static final int BETWEEN_LAUNCH_SLEEP_TIMEOUT = 2000; //2s between launching apps