Merge ""I tried to think of the most harmless thing."" into mnc-dev
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index b39376c..9f385fe 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
 
 import android.app.ActivityManager;
@@ -840,7 +841,7 @@
         return Integer.toString(result);
     }
 
-    // pm set-app-link [--user USER_ID] PACKAGE {always|ask|never|undefined}
+    // pm set-app-link [--user USER_ID] PACKAGE {always|ask|always-ask|never|undefined}
     private int runSetAppLink() {
         int userId = UserHandle.USER_OWNER;
 
@@ -889,6 +890,10 @@
                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
                 break;
 
+            case "always-ask":
+                newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
+                break;
+
             case "never":
                 newMode = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
                 break;
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index 474154b..2caec369 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -43,6 +43,8 @@
     void clearWindowAnimationFrameStats();
     WindowAnimationFrameStats getWindowAnimationFrameStats();
     void executeShellCommand(String command, in ParcelFileDescriptor fd);
+    void grantRuntimePermission(String packageName, String permission, int userId);
+    void revokeRuntimePermission(String packageName, String permission, int userId);
 
     // Called from the system process.
     oneway void shutdown();
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index a8494fb..efed2e0 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -30,6 +30,7 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.Log;
 import android.view.Display;
 import android.view.InputEvent;
@@ -846,6 +847,62 @@
     }
 
     /**
+     * Grants a runtime permission to a package for a user.
+     * @param packageName The package to which to grant.
+     * @param permission The permission to grant.
+     * @return Whether granting succeeded.
+     *
+     * @hide
+     */
+    public boolean grantRuntimePermission(String packageName, String permission,
+            UserHandle userHandle) {
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+        }
+        try {
+            if (DEBUG) {
+                Log.i(LOG_TAG, "Granting runtime permission");
+            }
+            // Calling out without a lock held.
+            mUiAutomationConnection.grantRuntimePermission(packageName,
+                    permission, userHandle.getIdentifier());
+            // TODO: The package manager API should return boolean.
+            return true;
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error granting runtime permission", re);
+        }
+        return false;
+    }
+
+    /**
+     * Revokes a runtime permission from a package for a user.
+     * @param packageName The package from which to revoke.
+     * @param permission The permission to revoke.
+     * @return Whether revoking succeeded.
+     *
+     * @hide
+     */
+    public boolean revokeRuntimePermission(String packageName, String permission,
+            UserHandle userHandle) {
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+        }
+        try {
+            if (DEBUG) {
+                Log.i(LOG_TAG, "Revoking runtime permission");
+            }
+            // Calling out without a lock held.
+            mUiAutomationConnection.revokeRuntimePermission(packageName,
+                    permission, userHandle.getIdentifier());
+            // TODO: The package manager API should return boolean.
+            return true;
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error revoking runtime permission", re);
+        }
+        return false;
+    }
+
+    /**
      * Executes a shell command. This method returs a file descriptor that points
      * to the standard output stream. The command execution is similar to running
      * "adb shell <command>" from a host connected to the device.
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 39cd3bc..13e27e2 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -19,6 +19,7 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.content.Context;
+import android.content.pm.IPackageManager;
 import android.graphics.Bitmap;
 import android.hardware.input.InputManager;
 import android.os.Binder;
@@ -60,6 +61,9 @@
     private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager.Stub
             .asInterface(ServiceManager.getService(Service.ACCESSIBILITY_SERVICE));
 
+    private final IPackageManager mPackageManager = IPackageManager.Stub
+            .asInterface(ServiceManager.getService("package"));
+
     private final Object mLock = new Object();
 
     private final Binder mToken = new Binder();
@@ -227,6 +231,38 @@
     }
 
     @Override
+    public void grantRuntimePermission(String packageName, String permission, int userId)
+            throws RemoteException {
+        synchronized (mLock) {
+            throwIfCalledByNotTrustedUidLocked();
+            throwIfShutdownLocked();
+            throwIfNotConnectedLocked();
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mPackageManager.grantRuntimePermission(packageName, permission, userId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public void revokeRuntimePermission(String packageName, String permission, int userId)
+            throws RemoteException {
+        synchronized (mLock) {
+            throwIfCalledByNotTrustedUidLocked();
+            throwIfShutdownLocked();
+            throwIfNotConnectedLocked();
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            mPackageManager.revokeRuntimePermission(packageName, permission, userId);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void executeShellCommand(final String command, final ParcelFileDescriptor sink)
             throws RemoteException {
         synchronized (mLock) {
diff --git a/core/java/android/content/pm/IntentFilterVerificationInfo.java b/core/java/android/content/pm/IntentFilterVerificationInfo.java
index 4dbac05..953b051 100644
--- a/core/java/android/content/pm/IntentFilterVerificationInfo.java
+++ b/core/java/android/content/pm/IntentFilterVerificationInfo.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
 
 import android.os.Parcel;
@@ -199,6 +200,10 @@
                 sb.append("never");
                 break;
 
+            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK:
+                sb.append("always-ask");
+                break;
+
             case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED:
             default:
                 sb.append("undefined");
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 0f936fd..c8e9402 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1073,6 +1073,18 @@
     public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER = 3;
 
     /**
+     * Used as the {@code status} argument for {@link PackageManager#updateIntentVerificationStatus}
+     * to indicate that this app should always be considered as an ambiguous candidate for
+     * handling the matching Intent even if there are other candidate apps in the "always"
+     * state.  Put another way: if there are any 'always ask' apps in a set of more than
+     * one candidate app, then a disambiguation is *always* presented even if there is
+     * another candidate app with the 'always' state.
+     *
+     * @hide
+     */
+    public static final int INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK = 4;
+
+    /**
      * Can be used as the {@code millisecondsToDelay} argument for
      * {@link PackageManager#extendVerificationTimeout}. This is the
      * maximum time {@code PackageManager} waits for the verification
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 20bcf62..bfca719 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -179,16 +179,16 @@
     }
 
     /**
-     * Returns the app id for a given shared app gid.
+     * Returns the app id for a given shared app gid. Returns -1 if the ID is invalid.
      * @hide
      */
     public static final int getAppIdFromSharedAppGid(int gid) {
-        final int noUserGid = getAppId(gid);
-        if (noUserGid < Process.FIRST_SHARED_APPLICATION_GID ||
-                noUserGid > Process.LAST_SHARED_APPLICATION_GID) {
-            throw new IllegalArgumentException(Integer.toString(gid) + " is not a shared app gid");
+        final int appId = getAppId(gid) + Process.FIRST_APPLICATION_UID
+                - Process.FIRST_SHARED_APPLICATION_GID;
+        if (appId < 0 || appId >= Process.FIRST_SHARED_APPLICATION_GID) {
+            return -1;
         }
-        return (noUserGid + Process.FIRST_APPLICATION_UID) - Process.FIRST_SHARED_APPLICATION_GID;
+        return appId;
     }
 
     /**
diff --git a/core/java/com/android/internal/util/ArrayUtils.java b/core/java/com/android/internal/util/ArrayUtils.java
index 9d0636a..f190d8c 100644
--- a/core/java/com/android/internal/util/ArrayUtils.java
+++ b/core/java/com/android/internal/util/ArrayUtils.java
@@ -294,6 +294,29 @@
     }
 
     /**
+     * Removes value from given array if present, providing set-like behavior.
+     */
+    public static @Nullable String[] removeString(@Nullable String[] cur, String val) {
+        if (cur == null) {
+            return null;
+        }
+        final int N = cur.length;
+        for (int i = 0; i < N; i++) {
+            if (Objects.equals(cur[i], val)) {
+                String[] ret = new String[N - 1];
+                if (i > 0) {
+                    System.arraycopy(cur, 0, ret, 0, i);
+                }
+                if (i < (N - 1)) {
+                    System.arraycopy(cur, i + 1, ret, i, N - i - 1);
+                }
+                return ret;
+            }
+        }
+        return cur;
+    }
+
+    /**
      * Adds value to given array if not already present, providing set-like
      * behavior.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
index fe876d7..7f68e29 100644
--- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java
@@ -159,7 +159,9 @@
             if (Binder.getCallingUid() != Process.SYSTEM_UID) {
                 throw new SecurityException("Async playback only available from system UID.");
             }
-
+            if (UserHandle.ALL.equals(user)) {
+                user = UserHandle.OWNER;
+            }
             mAsyncPlayer.play(getContextForUser(user), uri, looping, aa);
         }
 
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index c13401f..b766894 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -157,7 +157,7 @@
         mFactoryTest = factoryTest;
 
         // Let the package manager query for the sync adapters for a given authority
-        // as we grant default permissions to sync adapters for specifix authorities.
+        // as we grant default permissions to sync adapters for specific authorities.
         PackageManagerInternal packageManagerInternal = LocalServices.getService(
                 PackageManagerInternal.class);
         packageManagerInternal.setSyncAdapterPackagesprovider(
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 9426b76..4351798 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -3615,22 +3615,28 @@
 
         public ArraySet<String> getGrantedPackages() {
             final ArraySet<String> pkgs = new ArraySet<>();
-            final String setting = Settings.Secure.getStringForUser(
-                    getContext().getContentResolver(),
-                    Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
-                    ActivityManager.getCurrentUser());
-            if (setting != null) {
-                final String[] tokens = setting.split(SEPARATOR);
-                for (int i = 0; i < tokens.length; i++) {
-                    String token = tokens[i];
-                    if (token != null) {
-                        token.trim();
+
+            long identity = Binder.clearCallingIdentity();
+            try {
+                final String setting = Settings.Secure.getStringForUser(
+                        getContext().getContentResolver(),
+                        Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES,
+                        ActivityManager.getCurrentUser());
+                if (setting != null) {
+                    final String[] tokens = setting.split(SEPARATOR);
+                    for (int i = 0; i < tokens.length; i++) {
+                        String token = tokens[i];
+                        if (token != null) {
+                            token.trim();
+                        }
+                        if (TextUtils.isEmpty(token)) {
+                            continue;
+                        }
+                        pkgs.add(token);
                     }
-                    if (TextUtils.isEmpty(token)) {
-                        continue;
-                    }
-                    pkgs.add(token);
                 }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
             return pkgs;
         }
diff --git a/services/core/java/com/android/server/pm/BasePermission.java b/services/core/java/com/android/server/pm/BasePermission.java
index 18407c9..52d0928 100644
--- a/services/core/java/com/android/server/pm/BasePermission.java
+++ b/services/core/java/com/android/server/pm/BasePermission.java
@@ -88,4 +88,10 @@
         return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
                 == PermissionInfo.PROTECTION_DANGEROUS;
     }
+
+    public boolean isDevelopment() {
+        return (protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+                == PermissionInfo.PROTECTION_SIGNATURE
+                && (protectionLevel & PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) != 0;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
index 71a2d59..d2a70df 100644
--- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
@@ -296,7 +296,7 @@
             PackageParser.Package storagePackage = getDefaultProviderAuthorityPackageLPr(
                     "com.android.externalstorage.documents", userId);
             if (storagePackage != null) {
-                grantRuntimePermissionsLPw(storagePackage, STORAGE_PERMISSIONS, userId);
+                grantRuntimePermissionsLPw(storagePackage, STORAGE_PERMISSIONS, true, userId);
             }
 
             // CertInstaller
@@ -360,7 +360,7 @@
             PackageParser.Package cbrPackage =
                     getDefaultSystemHandlerActivityPackageLPr(cbrIntent, userId);
             if (cbrPackage != null && doesPackageSupportRuntimePermissions(cbrPackage)) {
-                grantRuntimePermissionsLPw(cbrPackage, SMS_PERMISSIONS, false, userId);
+                grantRuntimePermissionsLPw(cbrPackage, SMS_PERMISSIONS, userId);
             }
 
             // Calendar
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 21e256e8..f67f3f3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -56,6 +56,7 @@
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER;
 import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK;
 import static android.content.pm.PackageManager.MATCH_ALL;
 import static android.content.pm.PackageManager.MOVE_FAILED_DOESNT_EXIST;
 import static android.content.pm.PackageManager.MOVE_FAILED_INTERNAL_ERROR;
@@ -3432,14 +3433,14 @@
         }
     }
 
-    private static void enforceDeclaredAsUsedAndRuntimePermission(PackageParser.Package pkg,
+    private static void enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(PackageParser.Package pkg,
             BasePermission bp) {
         int index = pkg.requestedPermissions.indexOf(bp.name);
         if (index == -1) {
             throw new SecurityException("Package " + pkg.packageName
                     + " has not requested permission " + bp.name);
         }
-        if (!bp.isRuntime()) {
+        if (!bp.isRuntime() && !bp.isDevelopment()) {
             throw new SecurityException("Permission " + bp.name
                     + " is not a changeable permission type");
         }
@@ -3473,7 +3474,7 @@
                 throw new IllegalArgumentException("Unknown permission: " + name);
             }
 
-            enforceDeclaredAsUsedAndRuntimePermission(pkg, bp);
+            enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp);
 
             uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
             sb = (SettingBase) pkg.mExtras;
@@ -3489,6 +3490,16 @@
                         + name + " for package: " + packageName);
             }
 
+            if (bp.isDevelopment()) {
+                // Development permissions must be handled specially, since they are not
+                // normal runtime permissions.  For now they apply to all users.
+                if (permissionsState.grantInstallPermission(bp) !=
+                        PermissionsState.PERMISSION_OPERATION_FAILURE) {
+                    scheduleWriteSettingsLocked();
+                }
+                return;
+            }
+
             final int result = permissionsState.grantRuntimePermission(bp, userId);
             switch (result) {
                 case PermissionsState.PERMISSION_OPERATION_FAILURE: {
@@ -3557,7 +3568,7 @@
                 throw new IllegalArgumentException("Unknown permission: " + name);
             }
 
-            enforceDeclaredAsUsedAndRuntimePermission(pkg, bp);
+            enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp);
 
             SettingBase sb = (SettingBase) pkg.mExtras;
             if (sb == null) {
@@ -3572,6 +3583,16 @@
                         + name + " for package: " + packageName);
             }
 
+            if (bp.isDevelopment()) {
+                // Development permissions must be handled specially, since they are not
+                // normal runtime permissions.  For now they apply to all users.
+                if (permissionsState.revokeInstallPermission(bp) !=
+                        PermissionsState.PERMISSION_OPERATION_FAILURE) {
+                    scheduleWriteSettingsLocked();
+                }
+                return;
+            }
+
             if (permissionsState.revokeRuntimePermission(bp, userId) ==
                     PermissionsState.PERMISSION_OPERATION_FAILURE) {
                 return;
@@ -3799,21 +3820,6 @@
         return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0;
     }
 
-    void grantInstallPermissionLPw(String permission, PackageParser.Package pkg) {
-        BasePermission bp = mSettings.mPermissions.get(permission);
-        if (bp == null) {
-            throw new SecurityException("Missing " + permission + " permission");
-        }
-
-        SettingBase sb = (SettingBase) pkg.mExtras;
-        PermissionsState permissionsState = sb.getPermissionsState();
-
-        if (permissionsState.grantInstallPermission(bp) !=
-                PermissionsState.PERMISSION_OPERATION_FAILURE) {
-            scheduleWriteSettingsLocked();
-        }
-    }
-
     @Override
     public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
         mContext.enforceCallingOrSelfPermission(
@@ -4701,6 +4707,7 @@
         ArrayList<ResolveInfo> result = new ArrayList<ResolveInfo>();
         ArrayList<ResolveInfo> alwaysList = new ArrayList<ResolveInfo>();
         ArrayList<ResolveInfo> undefinedList = new ArrayList<ResolveInfo>();
+        ArrayList<ResolveInfo> alwaysAskList = new ArrayList<ResolveInfo>();
         ArrayList<ResolveInfo> neverList = new ArrayList<ResolveInfo>();
         ArrayList<ResolveInfo> matchAllList = new ArrayList<ResolveInfo>();
 
@@ -4737,6 +4744,11 @@
                             Slog.i(TAG, "  + never: " + info.activityInfo.packageName);
                         }
                         neverList.add(info);
+                    } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) {
+                        if (DEBUG_DOMAIN_VERIFICATION) {
+                            Slog.i(TAG, "  + always-ask: " + info.activityInfo.packageName);
+                        }
+                        alwaysAskList.add(info);
                     } else if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED ||
                             status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK) {
                         if (DEBUG_DOMAIN_VERIFICATION) {
@@ -4746,6 +4758,10 @@
                     }
                 }
             }
+
+            // We'll want to include browser possibilities in a few cases
+            boolean includeBrowser = false;
+
             // First try to add the "always" resolution(s) for the current user, if any
             if (alwaysList.size() > 0) {
                 result.addAll(alwaysList);
@@ -4754,7 +4770,7 @@
                     == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) {
                 result.add(xpDomainInfo.resolveInfo);
             } else {
-                // Add all undefined Apps as we want them to appear in the Disambiguation dialog.
+                // Add all undefined apps as we want them to appear in the disambiguation dialog.
                 result.addAll(undefinedList);
                 if (xpDomainInfo != null && (
                         xpDomainInfo.bestDomainVerificationStatus
@@ -4763,7 +4779,25 @@
                         == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK)) {
                     result.add(xpDomainInfo.resolveInfo);
                 }
-                // Also add Browsers (all of them or only the default one)
+                includeBrowser = true;
+            }
+
+            // The presence of any 'always ask' alternatives means we'll also offer browsers.
+            // If there were 'always' entries their preferred order has been set, so we also
+            // back that off to make the alternatives equivalent
+            if (alwaysAskList.size() > 0) {
+                for (ResolveInfo i : result) {
+                    i.preferredOrder = 0;
+                }
+                result.addAll(alwaysAskList);
+                includeBrowser = true;
+            }
+
+            if (includeBrowser) {
+                // Also add browsers (all of them or only the default one)
+                if (DEBUG_DOMAIN_VERIFICATION) {
+                    Slog.v(TAG, "   ...including browsers in candidate set");
+                }
                 if ((matchFlags & MATCH_ALL) != 0) {
                     result.addAll(matchAllList);
                 } else {
@@ -14764,6 +14798,7 @@
                 pw.println("    version: print database version info");
                 pw.println("    write: write current settings now");
                 pw.println("    installs: details about install sessions");
+                pw.println("    check-permission <permission> <package> [<user>]: does pkg hold perm?");
                 pw.println("    <package.name>: info about given package");
                 return;
             } else if ("--checkin".equals(opt)) {
@@ -14785,6 +14820,31 @@
                 // When dumping a single package, we always dump all of its
                 // filter information since the amount of data will be reasonable.
                 dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
+            } else if ("check-permission".equals(cmd)) {
+                if (opti >= args.length) {
+                    pw.println("Error: check-permission missing permission argument");
+                    return;
+                }
+                String perm = args[opti];
+                opti++;
+                if (opti >= args.length) {
+                    pw.println("Error: check-permission missing package argument");
+                    return;
+                }
+                String pkg = args[opti];
+                opti++;
+                int user = UserHandle.getUserId(Binder.getCallingUid());
+                if (opti < args.length) {
+                    try {
+                        user = Integer.parseInt(args[opti]);
+                    } catch (NumberFormatException e) {
+                        pw.println("Error: check-permission user argument is not a number: "
+                                + args[opti]);
+                        return;
+                    }
+                }
+                pw.println(checkPermission(perm, pkg, user));
+                return;
             } else if ("l".equals(cmd) || "libraries".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_LIBS);
             } else if ("f".equals(cmd) || "features".equals(cmd)) {
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 00d0fe1..a762014 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -3949,7 +3949,7 @@
 
     void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag,
             ArraySet<String> permissionNames, PackageSetting ps, SimpleDateFormat sdf,
-            Date date, List<UserInfo> users) {
+            Date date, List<UserInfo> users, boolean dumpAll) {
         if (checkinTag != null) {
             pw.print(checkinTag);
             pw.print(",");
@@ -4151,7 +4151,7 @@
                     pw.print(", COSTS_MONEY");
                 }
                 if ((perm.info.flags&PermissionInfo.FLAG_HIDDEN) != 0) {
-                    pw.print(", COSTS_HIDDEN");
+                    pw.print(", HIDDEN");
                 }
                 if ((perm.info.flags&PermissionInfo.FLAG_INSTALLED) != 0) {
                     pw.print(", INSTALLED");
@@ -4160,7 +4160,21 @@
             }
         }
 
-        if (ps.sharedUser == null || permissionNames != null) {
+        if ((permissionNames != null || dumpAll) && ps.pkg.requestedPermissions != null
+                && ps.pkg.requestedPermissions.size() > 0) {
+            final ArrayList<String> perms = ps.pkg.requestedPermissions;
+            pw.print(prefix); pw.println("  requested permissions:");
+            for (int i=0; i<perms.size(); i++) {
+                String perm = perms.get(i);
+                if (permissionNames != null
+                        && !permissionNames.contains(perm)) {
+                    continue;
+                }
+                pw.print(prefix); pw.print("    "); pw.println(perm);
+            }
+        }
+
+        if (ps.sharedUser == null || permissionNames != null || dumpAll) {
             PermissionsState permissionsState = ps.getPermissionsState();
             dumpInstallPermissionsLPr(pw, prefix + "  ", permissionNames, permissionsState);
         }
@@ -4187,7 +4201,7 @@
                 PermissionsState permissionsState = ps.getPermissionsState();
                 dumpGidsLPr(pw, prefix + "    ", permissionsState.computeGids(user.id));
                 dumpRuntimePermissionsLPr(pw, prefix + "    ", permissionNames, permissionsState
-                        .getRuntimePermissionStates(user.id));
+                        .getRuntimePermissionStates(user.id), dumpAll);
             }
 
             if (permissionNames == null) {
@@ -4235,11 +4249,12 @@
                 pw.println("Packages:");
                 printedSomething = true;
             }
-            dumpPackageLPr(pw, "  ", checkin ? "pkg" : null, permissionNames, ps, sdf, date, users);
+            dumpPackageLPr(pw, "  ", checkin ? "pkg" : null, permissionNames, ps, sdf, date, users,
+                    packageName != null);
         }
 
         printedSomething = false;
-        if (!checkin && mRenamedPackages.size() > 0 && permissionNames == null) {
+        if (mRenamedPackages.size() > 0 && permissionNames == null) {
             for (final Map.Entry<String, String> e : mRenamedPackages.entrySet()) {
                 if (packageName != null && !packageName.equals(e.getKey())
                         && !packageName.equals(e.getValue())) {
@@ -4276,7 +4291,7 @@
                     printedSomething = true;
                 }
                 dumpPackageLPr(pw, "  ", checkin ? "dis" : null, permissionNames, ps, sdf, date,
-                        users);
+                        users, packageName != null);
             }
         }
     }
@@ -4361,7 +4376,8 @@
                     if (!ArrayUtils.isEmpty(gids) || !permissions.isEmpty()) {
                         pw.print(prefix); pw.print("User "); pw.print(userId); pw.println(": ");
                         dumpGidsLPr(pw, prefix + "  ", gids);
-                        dumpRuntimePermissionsLPr(pw, prefix + "  ", permissionNames, permissions);
+                        dumpRuntimePermissionsLPr(pw, prefix + "  ", permissionNames, permissions,
+                                packageName != null);
                     }
                 }
             } else {
@@ -4407,8 +4423,8 @@
     }
 
     void dumpRuntimePermissionsLPr(PrintWriter pw, String prefix, ArraySet<String> permissionNames,
-            List<PermissionState> permissionStates) {
-        if (!permissionStates.isEmpty()) {
+            List<PermissionState> permissionStates, boolean dumpAll) {
+        if (!permissionStates.isEmpty() || dumpAll) {
             pw.print(prefix); pw.println("runtime permissions:");
             for (PermissionState permissionState : permissionStates) {
                 if (permissionNames != null
diff --git a/telecomm/java/android/telecom/DefaultDialerManager.java b/telecomm/java/android/telecom/DefaultDialerManager.java
index 3d49308..5852b8e 100644
--- a/telecomm/java/android/telecom/DefaultDialerManager.java
+++ b/telecomm/java/android/telecom/DefaultDialerManager.java
@@ -97,7 +97,7 @@
      * @hide
      * */
     public static String getDefaultDialerApplication(Context context) {
-        return getDefaultDialerApplication(context, ActivityManager.getCurrentUser());
+        return getDefaultDialerApplication(context, context.getUserId());
     }
 
     /**
diff --git a/tests/VoiceInteraction/AndroidManifest.xml b/tests/VoiceInteraction/AndroidManifest.xml
index 36d5d98..fe17c6e 100644
--- a/tests/VoiceInteraction/AndroidManifest.xml
+++ b/tests/VoiceInteraction/AndroidManifest.xml
@@ -2,6 +2,7 @@
         package="com.android.test.voiceinteraction">
 
     <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
+    <uses-permission android:name="android.permission.READ_LOGS" />
 
     <application>
         <activity android:name="VoiceInteractionMain" android:label="Voice Interaction"