Merge "Fix issue #30013670: Phone AP crash when testing VT call" into nyc-mr1-dev
diff --git a/media/java/android/media/soundtrigger/SoundTriggerDetector.java b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
index df0961b..d5296ae 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerDetector.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerDetector.java
@@ -15,6 +15,7 @@
  */
 
 package android.media.soundtrigger;
+import static android.hardware.soundtrigger.SoundTrigger.STATUS_OK;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -243,27 +244,29 @@
 
         boolean allowMultipleTriggers =
                 (recognitionFlags & RECOGNITION_FLAG_ALLOW_MULTIPLE_TRIGGERS) != 0;
+        int status = STATUS_OK;
         try {
-            mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId),
+            status = mSoundTriggerService.startRecognition(new ParcelUuid(mSoundModelId),
                     mRecognitionCallback, new RecognitionConfig(captureTriggerAudio,
                         allowMultipleTriggers, null, null));
         } catch (RemoteException e) {
             return false;
         }
-        return true;
+        return status == STATUS_OK;
     }
 
     /**
      * Stops recognition for the associated model.
      */
     public boolean stopRecognition() {
+        int status = STATUS_OK;
         try {
-            mSoundTriggerService.stopRecognition(new ParcelUuid(mSoundModelId),
+            status = mSoundTriggerService.stopRecognition(new ParcelUuid(mSoundModelId),
                     mRecognitionCallback);
         } catch (RemoteException e) {
             return false;
         }
-        return true;
+        return status == STATUS_OK;
     }
 
     /**
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 8e0ec52..5ce8c9e 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -797,7 +797,7 @@
                                 queue, oldJournal, null, null, false);
                         Message pbtMessage = obtainMessage(MSG_BACKUP_RESTORE_STEP, pbt);
                         sendMessage(pbtMessage);
-                    } catch (RemoteException e) {
+                    } catch (Exception e) {
                         // unable to ask the transport its dir name -- transient failure, since
                         // the above check succeeded.  Try again next time.
                         Slog.e(TAG, "Transport became unavailable attempting backup");
@@ -940,7 +940,7 @@
                     }
                     if (sets == null) EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
                 } catch (Exception e) {
-                    Slog.e(TAG, "Error from transport getting set list");
+                    Slog.e(TAG, "Error from transport getting set list: " + e.getMessage());
                 } finally {
                     if (params.observer != null) {
                         try {
@@ -948,7 +948,7 @@
                         } catch (RemoteException re) {
                             Slog.e(TAG, "Unable to report listing to observer");
                         } catch (Exception e) {
-                            Slog.e(TAG, "Restore observer threw", e);
+                            Slog.e(TAG, "Restore observer threw: " + e.getMessage());
                         }
                     }
 
@@ -1770,8 +1770,10 @@
                 }
                 return; // done; don't fall through to the error case
             }
-        } catch (RemoteException e) {
+        } catch (Exception e) {
             // transport threw when asked its name; fall through to the lookup-failed case
+            Slog.e(TAG, "Transport " + transportName + " failed to report name: "
+                    + e.getMessage());
         }
 
         // The named transport doesn't exist or threw.  This operation is
@@ -1859,7 +1861,7 @@
                             System.currentTimeMillis() + delay, mRunInitIntent);
                 }
             }
-        } catch (RemoteException e) {
+        } catch (Exception e) {
             // the transport threw when asked its file naming prefs; declare it invalid
             Slog.e(TAG, "Unable to register transport as " + name);
             mTransportNames.remove(component);
@@ -2065,8 +2067,9 @@
                 IBackupTransport transport = IBackupTransport.Stub.asInterface(service);
                 registerTransport(transport.name(), name, transport);
                 EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, name, 1);
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Unable to register transport " + component);
+            } catch (Exception e) {
+                Slog.e(TAG, "Unable to register transport " + component
+                        + ": " + e.getMessage());
                 EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_LIFECYCLE, name, 0);
             }
         }
@@ -2529,8 +2532,8 @@
         String dirName;
         try {
             dirName = transport.transportDirName();
-        } catch (RemoteException e) {
-            Slog.e(TAG, "Transport became unavailable while attempting backup");
+        } catch (Exception e) {
+            Slog.e(TAG, "Transport unavailable while attempting backup: " + e.getMessage());
             sendBackupFinished(observer, BackupManager.ERROR_TRANSPORT_ABORTED);
             return BackupManager.ERROR_TRANSPORT_ABORTED;
         }
@@ -2974,9 +2977,10 @@
                 try {
                     mCurrentToken = mTransport.getCurrentRestoreSet();
                     writeRestoreTokens();
-                } catch (RemoteException e) {
+                } catch (Exception e) {
                     // nothing for it at this point, unfortunately, but this will be
                     // recorded the next time we fully succeed.
+                    Slog.e(TAG, "Transport threw reporting restore set: " + e.getMessage());
                     addBackupTrace("transport threw returning token");
                 }
             }
@@ -3001,7 +3005,7 @@
                             }
                         }
                     } catch (Exception e) {
-                        Slog.w(TAG, "Failed to query transport name heading for init", e);
+                        Slog.w(TAG, "Failed to query transport name for init: " + e.getMessage());
                         // swallow it and proceed; we don't rely on this
                     }
                     clearMetadata();
@@ -3367,8 +3371,8 @@
                     try {
                         long quota = mTransport.getBackupQuota(mCurrentPackage.packageName, false);
                         mAgentBinder.doQuotaExceeded(size, quota);
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Unable to contact backup agent for quota exceeded");
+                    } catch (Exception e) {
+                        Slog.e(TAG, "Unable to notify about quota exceeded: " + e.getMessage());
                     }
                 }
                 nextState = (mQueue.isEmpty()) ? BackupState.FINAL : BackupState.RUNNING_QUEUE;
@@ -3406,7 +3410,7 @@
             try {
                 delay = mTransport.requestBackupTime();
             } catch (Exception e) {
-                Slog.w(TAG, "Unable to contact transport for recommended backoff");
+                Slog.w(TAG, "Unable to contact transport for recommended backoff: " + e.getMessage());
                 delay = 0;  // use the scheduler's default
             }
             KeyValueBackupJob.schedule(mContext, delay);
@@ -4324,7 +4328,10 @@
                 Slog.e(TAG, "Internal exception during full backup", e);
             } finally {
                 try {
-                    if (out != null) out.close();
+                    if (out != null) {
+                        out.flush();
+                        out.close();
+                    }
                     mOutputFile.close();
                 } catch (IOException e) {
                     /* nothing we can do about this */
@@ -5004,7 +5011,7 @@
                 return false;
             }
         } catch (Exception e) {
-            Slog.w(TAG, "Unable to contact transport");
+            Slog.w(TAG, "Unable to get transport name: " + e.getMessage());
             return false;
         }
 
@@ -8228,9 +8235,9 @@
                 // Success; cache the metadata and continue as expected with the
                 // next state already enqueued
 
-            } catch (RemoteException e) {
+            } catch (Exception e) {
                 // If we lost the transport at any time, halt
-                Slog.e(TAG, "Unable to contact transport for restore");
+                Slog.e(TAG, "Unable to contact transport for restore: " + e.getMessage());
                 mStatus = BackupTransport.TRANSPORT_ERROR;
                 mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
                 executeNextState(UnifiedRestoreState.FINAL);
@@ -8327,8 +8334,9 @@
                     nextState = UnifiedRestoreState.RUNNING_QUEUE;
                     return;
                 }
-            } catch (RemoteException e) {
-                Slog.e(TAG, "Can't get next target from transport; ending restore");
+            } catch (Exception e) {
+                Slog.e(TAG, "Can't get next restore target from transport; halting: "
+                        + e.getMessage());
                 EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
                 nextState = UnifiedRestoreState.FINAL;
                 return;
@@ -8638,11 +8646,11 @@
                     EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE,
                             mCurrentPackage.packageName, "I/O error on pipes");
                     status = BackupTransport.AGENT_ERROR;
-                } catch (RemoteException e) {
-                    // The transport went away; terminate the whole operation.  Closing
+                } catch (Exception e) {
+                    // The transport threw; terminate the whole operation.  Closing
                     // the sockets will wake up the engine and it will then tidy up the
                     // remote end.
-                    Slog.e(TAG, "Transport failed during restore");
+                    Slog.e(TAG, "Transport failed during restore: " + e.getMessage());
                     EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
                     status = BackupTransport.TRANSPORT_ERROR;
                 } finally {
@@ -8680,9 +8688,10 @@
                         // level is immaterial; we need to tell the transport to bail
                         try {
                             mTransport.abortFullRestore();
-                        } catch (RemoteException e) {
+                        } catch (Exception e) {
                             // transport itself is dead; make sure we handle this as a
                             // fatal error
+                            Slog.e(TAG, "Transport threw from abortFullRestore: " + e.getMessage());
                             status = BackupTransport.TRANSPORT_ERROR;
                         }
 
@@ -9030,16 +9039,15 @@
                 // Tell the transport to remove all the persistent storage for the app
                 // TODO - need to handle failures
                 mTransport.clearBackupData(mPackage);
-            } catch (RemoteException e) {
-                // can't happen; the transport is local
             } catch (Exception e) {
-                Slog.e(TAG, "Transport threw attempting to clear data for " + mPackage);
+                Slog.e(TAG, "Transport threw clearing data for " + mPackage + ": " + e.getMessage());
             } finally {
                 try {
                     // TODO - need to handle failures
                     mTransport.finishBackup();
-                } catch (RemoteException e) {
-                    // can't happen; the transport is local
+                } catch (Exception e) {
+                    // Nothing we can do here, alas
+                    Slog.e(TAG, "Unable to mark clear operation finished: " + e.getMessage());
                 }
 
                 // Last but not least, release the cpu
@@ -9098,8 +9106,6 @@
                                 System.currentTimeMillis() + delay, mRunInitIntent);
                     }
                 }
-            } catch (RemoteException e) {
-                // can't happen; the transports are local
             } catch (Exception e) {
                 Slog.e(TAG, "Unexpected error performing init", e);
             } finally {
@@ -9787,8 +9793,9 @@
                     if (MORE_DEBUG) Slog.d(TAG, "getConfigurationIntent() returning config intent "
                             + intent);
                     return intent;
-                } catch (RemoteException e) {
+                } catch (Exception e) {
                     /* fall through to return null */
+                    Slog.e(TAG, "Unable to get configuration intent from transport: " + e.getMessage());
                 }
             }
         }
@@ -9812,8 +9819,9 @@
                     final String text = transport.currentDestinationString();
                     if (MORE_DEBUG) Slog.d(TAG, "getDestinationString() returning " + text);
                     return text;
-                } catch (RemoteException e) {
+                } catch (Exception e) {
                     /* fall through to return null */
+                    Slog.e(TAG, "Unable to get string from transport: " + e.getMessage());
                 }
             }
         }
@@ -9834,8 +9842,9 @@
                     if (MORE_DEBUG) Slog.d(TAG, "getDataManagementIntent() returning intent "
                             + intent);
                     return intent;
-                } catch (RemoteException e) {
+                } catch (Exception e) {
                     /* fall through to return null */
+                    Slog.e(TAG, "Unable to get management intent from transport: " + e.getMessage());
                 }
             }
         }
@@ -9856,8 +9865,9 @@
                     final String text = transport.dataManagementLabel();
                     if (MORE_DEBUG) Slog.d(TAG, "getDataManagementLabel() returning " + text);
                     return text;
-                } catch (RemoteException e) {
+                } catch (Exception e) {
                     /* fall through to return null */
+                    Slog.e(TAG, "Unable to get management label from transport: " + e.getMessage());
                 }
             }
         }
@@ -9950,9 +9960,9 @@
                 msg.obj = new RestoreParams(transport, dirName, null,
                         restoreSet, packageName, token);
                 mBackupHandler.sendMessage(msg);
-            } catch (RemoteException e) {
-                // Binding to the transport broke; back off and proceed with the installation.
-                Slog.e(TAG, "Unable to contact transport");
+            } catch (Exception e) {
+                // Calling into the transport broke; back off and proceed with the installation.
+                Slog.e(TAG, "Unable to contact transport: " + e.getMessage());
                 skip = true;
             }
         }
@@ -10073,8 +10083,8 @@
                 try {
                     return transport.isAppEligibleForBackup(packageInfo,
                         appGetsFullBackup(packageInfo));
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to contact transport");
+                } catch (Exception e) {
+                    Slog.e(TAG, "Unable to ask about eligibility: " + e.getMessage());
                 }
             }
             // If transport is not present we couldn't tell that the package is not eligible.
@@ -10176,9 +10186,9 @@
             String dirName;
             try {
                 dirName = mRestoreTransport.transportDirName();
-            } catch (RemoteException e) {
+            } catch (Exception e) {
                 // Transport went AWOL; fail.
-                Slog.e(TAG, "Unable to contact transport for restore");
+                Slog.e(TAG, "Unable to get transport dir for restore: " + e.getMessage());
                 return -1;
             }
 
@@ -10258,9 +10268,9 @@
             String dirName;
             try {
                 dirName = mRestoreTransport.transportDirName();
-            } catch (RemoteException e) {
+            } catch (Exception e) {
                 // Transport went AWOL; fail.
-                Slog.e(TAG, "Unable to contact transport for restore");
+                Slog.e(TAG, "Unable to get transport name for restoreSome: " + e.getMessage());
                 return -1;
             }
 
@@ -10348,9 +10358,9 @@
                 String dirName;
                 try {
                     dirName = mRestoreTransport.transportDirName();
-                } catch (RemoteException e) {
+                } catch (Exception e) {
                     // Transport went AWOL; fail.
-                    Slog.e(TAG, "Unable to contact transport for restore");
+                    Slog.e(TAG, "Unable to get transport dir for restorePackage: " + e.getMessage());
                     return -1;
                 }
 
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index a102664..eb02dc3 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2051,6 +2051,14 @@
         // We don't want to clear starting window for activities that aren't behind fullscreen
         // activities as we need to display their starting window until they are done initializing.
         boolean behindFullscreenActivity = false;
+
+        if (getStackVisibilityLocked(null) == STACK_INVISIBLE) {
+            // The stack is not visible, so no activity in it should be displaying a starting
+            // window. Mark all activities below top and behind fullscreen.
+            aboveTop = false;
+            behindFullscreenActivity = true;
+        }
+
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 83af017..a3cf9c8 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -666,23 +666,26 @@
                         "Too many historical sessions for UID " + callingUid);
             }
 
-            final long createdMillis = System.currentTimeMillis();
             sessionId = allocateSessionIdLocked();
+        }
 
-            // We're staging to exactly one location
-            File stageDir = null;
-            String stageCid = null;
-            if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
-                final boolean isEphemeral =
-                        (params.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
-                stageDir = buildStageDir(params.volumeUuid, sessionId, isEphemeral);
-            } else {
-                stageCid = buildExternalStageCid(sessionId);
-            }
+        final long createdMillis = System.currentTimeMillis();
+        // We're staging to exactly one location
+        File stageDir = null;
+        String stageCid = null;
+        if ((params.installFlags & PackageManager.INSTALL_INTERNAL) != 0) {
+            final boolean isEphemeral =
+                    (params.installFlags & PackageManager.INSTALL_EPHEMERAL) != 0;
+            stageDir = buildStageDir(params.volumeUuid, sessionId, isEphemeral);
+        } else {
+            stageCid = buildExternalStageCid(sessionId);
+        }
 
-            session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
-                    mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
-                    params, createdMillis, stageDir, stageCid, false, false);
+        session = new PackageInstallerSession(mInternalCallback, mContext, mPm,
+                mInstallThread.getLooper(), sessionId, userId, installerPackageName, callingUid,
+                params, createdMillis, stageDir, stageCid, false, false);
+
+        synchronized (mSessions) {
             mSessions.put(sessionId, session);
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 455e1fa..1ca6148 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -20443,12 +20443,7 @@
         }
     }
 
-    void onBeforeUserStartUninitialized(final int userId) {
-        synchronized (mPackages) {
-            if (mSettings.areDefaultRuntimePermissionsGrantedLPr(userId)) {
-                return;
-            }
-        }
+    void onNewUserCreated(final int userId) {
         mDefaultPermissionPolicy.grantDefaultPermissions(userId);
         // If permission review for legacy apps is required, we represent
         // dagerous permissions for such apps as always granted runtime
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index 1a4e4e0..b94d0f0 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -1185,8 +1185,8 @@
     private static void saveShortcut(XmlSerializer out, ShortcutInfo si, boolean forBackup)
             throws IOException, XmlPullParserException {
         if (forBackup) {
-            if (!si.isPinned()) {
-                return; // Backup only pinned icons.
+            if (!(si.isPinned() && si.isEnabled())) {
+                return; // We only backup pinned shortcuts that are enabled.
             }
         }
         out.startTag(null, TAG_SHORTCUT);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d750cbf..5c7e87f 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2304,6 +2304,7 @@
             synchronized (mRestrictionsLock) {
                 mBaseUserRestrictions.append(userId, restrictions);
             }
+            mPm.onNewUserCreated(userId);
             Intent addedIntent = new Intent(Intent.ACTION_USER_ADDED);
             addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
             mContext.sendBroadcastAsUser(addedIntent, UserHandle.ALL,
@@ -2874,10 +2875,6 @@
             synchronized (mRestrictionsLock) {
                 applyUserRestrictionsLR(userId);
             }
-            UserInfo userInfo = getUserInfoNoChecks(userId);
-            if (userInfo != null && !userInfo.isInitialized()) {
-                mPm.onBeforeUserStartUninitialized(userId);
-            }
         }
 
         maybeInitializeDemoMode(userId);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 446c75c..3f71ba4 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -216,6 +216,8 @@
     static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP = 0;
     static final int SHORT_PRESS_SLEEP_GO_TO_SLEEP_AND_GO_HOME = 1;
 
+    static final int PENDING_KEY_NULL = -1;
+
     // Controls navigation bar opacity depending on which workspace stacks are currently
     // visible.
     // Nav bar is always opaque when either the freeform stack or docked stack is visible.
@@ -410,6 +412,10 @@
     volatile boolean mRecentsVisible;
     volatile boolean mTvPictureInPictureVisible;
 
+    // Used to hold the last user key used to wake the device.  This helps us prevent up events
+    // from being passed to the foregrounded app without a corresponding down event
+    volatile int mPendingWakeKey = PENDING_KEY_NULL;
+
     int mRecentAppsHeldModifiers;
     boolean mLanguageSwitchKeyPressed;
 
@@ -5560,12 +5566,24 @@
             // key to the application.
             result = ACTION_PASS_TO_USER;
             isWakeKey = false;
-        } else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
+
+            if (interactive) {
+                // If the screen is awake, but the button pressed was the one that woke the device
+                // then don't pass it to the application
+                if (keyCode == mPendingWakeKey && !down) {
+                    result = 0;
+                }
+                // Reset the pending key
+                mPendingWakeKey = PENDING_KEY_NULL;
+            }
+        } else if (!interactive && shouldDispatchInputWhenNonInteractive(event)) {
             // If we're currently dozing with the screen on and the keyguard showing, pass the key
             // to the application but preserve its wake key status to make sure we still move
             // from dozing to fully interactive if we would normally go from off to fully
             // interactive.
             result = ACTION_PASS_TO_USER;
+            // Since we're dispatching the input, reset the pending key
+            mPendingWakeKey = PENDING_KEY_NULL;
         } else {
             // When the screen is off and the key is not injected, determine whether
             // to wake the device but don't pass the key to the application.
@@ -5573,6 +5591,10 @@
             if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
                 isWakeKey = false;
             }
+            // Cache the wake key on down event so we can also avoid sending the up event to the app
+            if (isWakeKey && down) {
+                mPendingWakeKey = keyCode;
+            }
         }
 
         // If the key would be handled globally, just return the result, don't worry about special
@@ -5949,7 +5971,7 @@
             }
         }
 
-        if (shouldDispatchInputWhenNonInteractive()) {
+        if (shouldDispatchInputWhenNonInteractive(null)) {
             return ACTION_PASS_TO_USER;
         }
 
@@ -5964,7 +5986,7 @@
         return 0;
     }
 
-    private boolean shouldDispatchInputWhenNonInteractive() {
+    private boolean shouldDispatchInputWhenNonInteractive(KeyEvent event) {
         final boolean displayOff = (mDisplay == null || mDisplay.getState() == Display.STATE_OFF);
 
         if (displayOff && !mHasFeatureWatch) {
@@ -5976,6 +5998,14 @@
             return true;
         }
 
+        // Watches handle BACK specially
+        if (mHasFeatureWatch
+                && event != null
+                && (event.getKeyCode() == KeyEvent.KEYCODE_BACK
+                        || event.getKeyCode() == KeyEvent.KEYCODE_STEM_PRIMARY)) {
+            return false;
+        }
+
         // Send events to a dozing dream even if the screen is off since the dream
         // is in control of the state of the screen.
         IDreamManager dreamManager = getDreamManager();
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index 3d68b59..01c19d0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -1480,12 +1480,30 @@
         return new File(si.getBitmapPath()).getName();
     }
 
+    /**
+     * @return all shortcuts stored internally for the caller.  This reflects the *internal* view
+     * of shortcuts, which may be different from what {@link #getCallerVisibleShortcuts} would
+     * return, because getCallerVisibleShortcuts() will get shortcuts from the proper "front door"
+     * which performs some extra checks, like {@link ShortcutPackage#onRestored}.
+     */
     protected List<ShortcutInfo> getCallerShortcuts() {
         final ShortcutPackage p = mService.getPackageShortcutForTest(
                 getCallingPackage(), getCallingUserId());
         return p == null ? null : p.getAllShortcutsForTest();
     }
 
+    /**
+     * @return all shortcuts owned by caller that are actually visible via ShortcutManager.
+     * See also {@link #getCallerShortcuts}.
+     */
+    protected List<ShortcutInfo> getCallerVisibleShortcuts() {
+        final ArrayList<ShortcutInfo> ret = new ArrayList<>();
+        ret.addAll(mManager.getDynamicShortcuts());
+        ret.addAll(mManager.getPinnedShortcuts());
+        ret.addAll(mManager.getManifestShortcuts());
+        return ret;
+    }
+
     protected ShortcutInfo getCallerShortcut(String shortcutId) {
         return getPackageShortcut(getCallingPackage(), shortcutId, getCallingUserId());
     }
@@ -1696,6 +1714,8 @@
 
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s2", "s5"), HANDLE_USER_P0);
         });
+
+        // Note LAUNCHER_3 has allowBackup=false.
         runWithCaller(LAUNCHER_3, USER_0, () -> {
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("s3"), HANDLE_USER_0);
             mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, list("s3", "s4"), HANDLE_USER_0);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index aa1072e..c7673d1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -4635,8 +4635,10 @@
         final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_0);
         assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_1));
         assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_2));
-        assertExistsAndShadow(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_1)));
-        assertExistsAndShadow(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_2)));
+        assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+                PackageWithUser.of(USER_0, LAUNCHER_1)));
+        assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+                PackageWithUser.of(USER_0, LAUNCHER_2)));
 
         assertNull(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
         assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_3)));
@@ -4644,90 +4646,98 @@
 
         installPackage(USER_0, CALLING_PACKAGE_1);
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertEquals(0, mManager.getDynamicShortcuts().size());
-            assertShortcutIds(assertAllPinned(
-                    mManager.getPinnedShortcuts()),
-                    "s1", "s2");
+            assertWith(getCallerVisibleShortcuts())
+                    .selectDynamic()
+                    .isEmpty()
+
+                    .revertToOriginalList()
+                    .selectPinned()
+                    .haveIds("s1", "s2");
         });
 
         installPackage(USER_0, LAUNCHER_1);
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
-                    "s1");
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
-                    /* empty, not restored */ );
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
-                    /* empty, not restored */ );
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    .areAllPinned()
+                    .haveIds("s1");
 
-            assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    .isEmpty();
+
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    .isEmpty();
+
+            assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+                    .isEmpty();
         });
 
         installPackage(USER_0, CALLING_PACKAGE_2);
         runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            assertEquals(0, mManager.getDynamicShortcuts().size());
-            assertShortcutIds(assertAllPinned(
-                    mManager.getPinnedShortcuts()),
-                    "s1", "s2", "s3");
+            assertWith(getCallerVisibleShortcuts())
+                    .selectDynamic()
+                    .isEmpty()
+
+                    .revertToOriginalList()
+                    .selectPinned()
+                    .haveIds("s1", "s2", "s3");
         });
 
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
-                    "s1");
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
-                    "s1", "s2");
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
-                    /* empty, not restored */ );
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    .areAllPinned()
+                    .haveIds("s1");
 
-            assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    .areAllPinned()
+                    .haveIds("s1", "s2");
+
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    .isEmpty();
+
+            assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+                    .isEmpty();
         });
 
         // 3 shouldn't be backed up, so no pinned shortcuts.
         installPackage(USER_0, CALLING_PACKAGE_3);
         runWithCaller(CALLING_PACKAGE_3, USER_0, () -> {
-            assertEquals(0, mManager.getDynamicShortcuts().size());
-            assertEquals(0, mManager.getPinnedShortcuts().size());
+            assertWith(getCallerVisibleShortcuts())
+                    .isEmpty();
         });
 
         // Launcher on a different profile shouldn't be restored.
         runWithCaller(LAUNCHER_1, USER_P0, () -> {
-            assertEquals(0,
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)
-                            .size());
-            assertEquals(0,
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)
-                            .size());
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
-                    /* wasn't restored, so still empty */ );
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    .isEmpty();
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    .isEmpty();
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    .isEmpty();
         });
 
         // Package on a different profile, no restore.
         installPackage(USER_P0, CALLING_PACKAGE_1);
         runWithCaller(CALLING_PACKAGE_1, USER_P0, () -> {
-            assertEquals(0, mManager.getDynamicShortcuts().size());
-            assertEquals(0, mManager.getPinnedShortcuts().size());
+            assertWith(getCallerVisibleShortcuts())
+                    .isEmpty();
         });
 
         // Restore launcher 2 on user 0.
         installPackage(USER_0, LAUNCHER_2);
         runWithCaller(LAUNCHER_2, USER_0, () -> {
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
-                    "s2");
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
-                    "s2", "s3");
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
-                    /* wasn't restored, so still empty */ );
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    .areAllPinned()
+                    .haveIds("s2");
 
-            assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    .areAllPinned()
+                    .haveIds("s2", "s3");
+
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    .isEmpty();
+
+            assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+                    .isEmpty();
         });
 
 
@@ -4735,33 +4745,33 @@
         // make sure they still have the same result.
         installPackage(USER_0, CALLING_PACKAGE_1);
         runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
-            assertEquals(0, mManager.getDynamicShortcuts().size());
-            assertShortcutIds(assertAllPinned(
-                    mManager.getPinnedShortcuts()),
-                    "s1", "s2");
+            assertWith(getCallerVisibleShortcuts())
+                    .areAllPinned()
+                    .haveIds("s1", "s2");
         });
 
         installPackage(USER_0, LAUNCHER_1);
         runWithCaller(LAUNCHER_1, USER_0, () -> {
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0)),
-                    "s1");
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0)),
-                    "s1", "s2");
-            assertShortcutIds(assertAllPinned(
-                    mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
-                    /* wasn't restored, so still empty */ );
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    .areAllPinned()
+                    .haveIds("s1");
 
-            assertEquals(0, mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0).size());
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    .areAllPinned()
+                    .haveIds("s1", "s2");
+
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    .isEmpty();
+
+            assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+                    .isEmpty();
         });
 
         installPackage(USER_0, CALLING_PACKAGE_2);
         runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
-            assertEquals(0, mManager.getDynamicShortcuts().size());
-            assertShortcutIds(assertAllPinned(
-                    mManager.getPinnedShortcuts()),
-                    "s1", "s2", "s3");
+            assertWith(getCallerVisibleShortcuts())
+                    .areAllPinned()
+                    .haveIds("s1", "s2", "s3");
         });
     }
 
@@ -5082,6 +5092,112 @@
         });
     }
 
+    public void testBackupAndRestore_disabled() {
+        prepareCrossProfileDataSet();
+
+        // Before doing backup & restore, disable s1.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            mManager.disableShortcuts(list("s1"));
+        });
+
+        backupAndRestore();
+
+        // Below is copied from checkBackupAndRestore_success.
+
+        // Make sure non-system user is not restored.
+        final ShortcutUser userP0 = mService.getUserShortcutsLocked(USER_P0);
+        assertEquals(0, userP0.getAllPackagesForTest().size());
+        assertEquals(0, userP0.getAllLaunchersForTest().size());
+
+        // Make sure only "allowBackup" apps are restored, and are shadow.
+        final ShortcutUser user0 = mService.getUserShortcutsLocked(USER_0);
+        assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_1));
+        assertExistsAndShadow(user0.getAllPackagesForTest().get(CALLING_PACKAGE_2));
+        assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+                PackageWithUser.of(USER_0, LAUNCHER_1)));
+        assertExistsAndShadow(user0.getAllLaunchersForTest().get(
+                PackageWithUser.of(USER_0, LAUNCHER_2)));
+
+        assertNull(user0.getAllPackagesForTest().get(CALLING_PACKAGE_3));
+        assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_0, LAUNCHER_3)));
+        assertNull(user0.getAllLaunchersForTest().get(PackageWithUser.of(USER_P0, LAUNCHER_1)));
+
+        installPackage(USER_0, CALLING_PACKAGE_1);
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertWith(getCallerVisibleShortcuts())
+                    .areAllEnabled() // disabled shortcuts shouldn't be restored.
+
+                    .selectDynamic()
+                    .isEmpty()
+
+                    .revertToOriginalList()
+                    .selectPinned()
+                    // s1 is not restored.
+                    .haveIds("s2");
+        });
+
+        installPackage(USER_0, LAUNCHER_1);
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            // Note, s1 was pinned by launcher 1, but was disabled, so isn't restored.
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_1), HANDLE_USER_0))
+                    .isEmpty();
+
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_2), HANDLE_USER_0))
+                    .isEmpty();
+
+            assertWith(mLauncherApps.getShortcuts(buildAllQuery(CALLING_PACKAGE_3), HANDLE_USER_0))
+                    .isEmpty();
+
+            assertWith(mLauncherApps.getShortcuts(QUERY_ALL, HANDLE_USER_P0))
+                    .isEmpty();
+        });
+    }
+
+
+    public void testBackupAndRestore_manifestNotRestored() {
+        // Publish two manifest shortcuts.
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+                R.xml.shortcut_2);
+        updatePackageVersion(CALLING_PACKAGE_1, 1);
+        mInternal.onPackageBroadcast(
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+        // Pin from launcher 1.
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, list("ms1", "ms2"), HANDLE_USER_0);
+        });
+
+        // Update and now ms2 is gone -> disabled.
+        addManifestShortcutResource(
+                new ComponentName(CALLING_PACKAGE_1, ShortcutActivity.class.getName()),
+                R.xml.shortcut_1);
+        updatePackageVersion(CALLING_PACKAGE_1, 1);
+        mInternal.onPackageBroadcast(
+                genPackageAddIntent(CALLING_PACKAGE_1, USER_0));
+
+        // Make sure the manifest shortcuts have been published.
+        runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+            assertWith(getCallerShortcuts())
+                    .areAllPinned()
+                    .haveIds("ms1", "ms2")
+
+                    .selectByIds("ms1")
+                    .areAllManifest()
+                    .areAllEnabled()
+
+                    .revertToOriginalList()
+                    .selectByIds("ms2")
+                    .areAllNotManifest()
+                    .areAllDisabled();
+        });
+
+        // Now do the regular backup & restore test.
+        // The existence of the manifest shortcuts shouldn't affect the result.
+        prepareCrossProfileDataSet();
+        backupAndRestore();
+    }
+
     public void testSaveAndLoad_crossProfile() {
         prepareCrossProfileDataSet();