Merge "Sigh." into klp-dev
diff --git a/api/current.txt b/api/current.txt
index 21ca3c0..4f398cf 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20978,6 +20978,7 @@
     method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
     method public static java.lang.String getRootId(android.net.Uri);
     method public static java.lang.String getSearchDocumentsQuery(android.net.Uri);
+    method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
     field public static final java.lang.String EXTRA_ERROR = "error";
     field public static final java.lang.String EXTRA_INFO = "info";
     field public static final java.lang.String EXTRA_LOADING = "loading";
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index fc277f1..30bffc4 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -550,8 +550,8 @@
      * fixed depth of field range
      * </p>
      */
-    public static final Key<Float> LENS_FOCUS_RANGE =
-            new Key<Float>("android.lens.focusRange", float.class);
+    public static final Key<float[]> LENS_FOCUS_RANGE =
+            new Key<float[]>("android.lens.focusRange", float[].class);
 
     /**
      * <p>
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 8f22312..4c9af19 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -21,7 +21,10 @@
 
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
+import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ProviderInfo;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.graphics.Bitmap;
@@ -573,6 +576,28 @@
     }
 
     /**
+     * Test if the given Uri represents a {@link Document} backed by a
+     * {@link DocumentsProvider}.
+     */
+    public static boolean isDocumentUri(Context context, Uri uri) {
+        final List<String> paths = uri.getPathSegments();
+        if (paths.size() < 2) {
+            return false;
+        }
+        if (!PATH_DOCUMENT.equals(paths.get(0))) {
+            return false;
+        }
+
+        final ProviderInfo info = context.getPackageManager()
+                .resolveContentProvider(uri.getAuthority(), PackageManager.GET_META_DATA);
+        if (info.metaData != null && info.metaData.containsKey(
+                DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Extract the {@link Root#COLUMN_ROOT_ID} from the given Uri.
      */
     public static String getRootId(Uri rootUri) {
diff --git a/core/java/com/android/internal/util/Preconditions.java b/core/java/com/android/internal/util/Preconditions.java
index a327adc..a54b364 100644
--- a/core/java/com/android/internal/util/Preconditions.java
+++ b/core/java/com/android/internal/util/Preconditions.java
@@ -66,4 +66,16 @@
             throw new IllegalStateException();
         }
     }
+
+    /**
+     * Check the requested flags, throwing if any requested flags are outside
+     * the allowed set.
+     */
+    public static void checkFlagsArgument(int requestedFlags, int allowedFlags) {
+        if ((requestedFlags & allowedFlags) != requestedFlags) {
+            throw new IllegalArgumentException("Requested flags 0x"
+                    + Integer.toHexString(requestedFlags) + ", but only 0x"
+                    + Integer.toHexString(allowedFlags) + " are allowed");
+        }
+    }
 }
diff --git a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java b/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
index 9861399..57fc7e4 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
@@ -21,6 +21,7 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.os.Bundle;
+import android.provider.DocumentsContract;
 import android.util.Log;
 import android.view.View;
 import android.view.View.OnClickListener;
@@ -209,6 +210,9 @@
         if (requestCode == CODE_READ) {
             final Uri uri = data != null ? data.getData() : null;
             if (uri != null) {
+                if (DocumentsContract.isDocumentUri(this, uri)) {
+                    result += "; DOC_ID";
+                }
                 getContentResolver()
                         .takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
                 InputStream is = null;
@@ -228,6 +232,9 @@
         } else if (requestCode == CODE_WRITE) {
             final Uri uri = data != null ? data.getData() : null;
             if (uri != null) {
+                if (DocumentsContract.isDocumentUri(this, uri)) {
+                    result += "; DOC_ID";
+                }
                 getContentResolver()
                         .takePersistableUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                 OutputStream os = null;
diff --git a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
index d6cf76c..8d11a93 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/PrintJobConfigActivity.java
@@ -56,6 +56,7 @@
 import android.text.TextUtils;
 import android.text.TextUtils.SimpleStringSplitter;
 import android.text.TextWatcher;
+import android.util.ArraySet;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -90,6 +91,7 @@
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -147,6 +149,26 @@
             "[\\s]*[0-9]*[\\s]*[\\-]?[\\s]*[0-9]*[\\s]*?(([,])"
             + "[\\s]*[0-9]*[\\s]*[\\-]?[\\s]*[0-9]*[\\s]*|[\\s]*)+");
 
+    // The list of countries where Letter is the default paper size. Culled from
+    // the OpenOffice wiki at http://wiki.openoffice.org/wiki/DefaultPaperSize.
+    private static final Set<String> sLetterDefaultCountries = new ArraySet<String>();
+    static {
+        sLetterDefaultCountries.add("US");
+        sLetterDefaultCountries.add("CA");
+        sLetterDefaultCountries.add("BZ");
+        sLetterDefaultCountries.add("CL");
+        sLetterDefaultCountries.add("CR");
+        sLetterDefaultCountries.add("GT");
+        sLetterDefaultCountries.add("NI");
+        sLetterDefaultCountries.add("PA");
+        sLetterDefaultCountries.add("PR");
+        sLetterDefaultCountries.add("SV");
+        sLetterDefaultCountries.add("VE");
+        sLetterDefaultCountries.add("MX");
+        sLetterDefaultCountries.add("CO");
+        sLetterDefaultCountries.add("PH");
+    }
+
     public static final PageRange[] ALL_PAGES_ARRAY = new PageRange[] {PageRange.ALL_PAGES};
 
     private final PrintAttributes mOldPrintAttributes = new PrintAttributes.Builder().build();
@@ -2136,12 +2158,20 @@
             }
 
             private PrinterInfo createFakePdfPrinter() {
+                final MediaSize defaultMediaSize;
+                String currentCountry = getResources().getConfiguration().locale.getCountry();
+                if (sLetterDefaultCountries.contains(currentCountry)) {
+                    defaultMediaSize = MediaSize.NA_LETTER;
+                } else {
+                    defaultMediaSize = MediaSize.ISO_A4;
+                }
+
                 PrinterId printerId = new PrinterId(getComponentName(), "PDF printer");
 
                 PrinterCapabilitiesInfo capabilities =
                         new PrinterCapabilitiesInfo.Builder(printerId)
-                    .addMediaSize(MediaSize.ISO_A4, true)
-                    .addMediaSize(MediaSize.NA_LETTER, false)
+                    .addMediaSize(MediaSize.ISO_A4, MediaSize.ISO_A4 == defaultMediaSize)
+                    .addMediaSize(MediaSize.NA_LETTER, MediaSize.NA_LETTER == defaultMediaSize)
                     .addResolution(new Resolution("PDF resolution", "PDF resolution",
                             300, 300), true)
                     .setColorModes(PrintAttributes.COLOR_MODE_COLOR
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3c11933..babe0e6 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -41,6 +41,7 @@
 import com.android.internal.util.FastPrintWriter;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.MemInfoReader;
+import com.android.internal.util.Preconditions;
 import com.android.server.AppOpsService;
 import com.android.server.AttributeCache;
 import com.android.server.IntentResolver;
@@ -6062,12 +6063,8 @@
             }
 
             // Persistable only supported through Intents
-            modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-            if (modeFlags == 0) {
-                throw new IllegalArgumentException("Mode flags must be "
-                        + "FLAG_GRANT_READ_URI_PERMISSION and/or FLAG_GRANT_WRITE_URI_PERMISSION");
-            }
+            Preconditions.checkFlagsArgument(modeFlags,
+                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 
             grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags,
                     null);
@@ -6408,11 +6405,8 @@
     public void takePersistableUriPermission(Uri uri, int modeFlags) {
         enforceNotIsolatedCaller("takePersistableUriPermission");
 
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-        if (modeFlags == 0) {
-            return;
-        }
+        Preconditions.checkFlagsArgument(modeFlags,
+                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 
         synchronized (this) {
             final int callingUid = Binder.getCallingUid();
@@ -6436,11 +6430,8 @@
     public void releasePersistableUriPermission(Uri uri, int modeFlags) {
         enforceNotIsolatedCaller("releasePersistableUriPermission");
 
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-        if (modeFlags == 0) {
-            return;
-        }
+        Preconditions.checkFlagsArgument(modeFlags,
+                Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
 
         synchronized (this) {
             final int callingUid = Binder.getCallingUid();
diff --git a/services/java/com/android/server/am/UriPermission.java b/services/java/com/android/server/am/UriPermission.java
index 7057c24..5868c08 100644
--- a/services/java/com/android/server/am/UriPermission.java
+++ b/services/java/com/android/server/am/UriPermission.java
@@ -22,6 +22,7 @@
 import android.util.Log;
 import android.util.Slog;
 
+import com.android.internal.util.Preconditions;
 import com.google.android.collect.Sets;
 
 import java.io.PrintWriter;
@@ -131,10 +132,7 @@
      * @return if mode changes should trigger persisting.
      */
     boolean takePersistableModes(int modeFlags) {
-        if ((~persistableModeFlags & modeFlags) != 0) {
-            Slog.w(TAG, "Trying to take 0x" + Integer.toHexString(modeFlags) + " but only 0x"
-                    + Integer.toHexString(persistableModeFlags) + " are available");
-        }
+        Preconditions.checkFlagsArgument(modeFlags, persistableModeFlags);
 
         final int before = persistedModeFlags;
         persistedModeFlags |= (persistableModeFlags & modeFlags);
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index d0e9fe1..c33134a 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -110,6 +110,7 @@
     private static final String USER_PHOTO_FILENAME = "photo.png";
 
     private static final String RESTRICTIONS_FILE_PREFIX = "res_";
+    private static final String XML_SUFFIX = ".xml";
 
     private static final int MIN_USER_ID = 10;
 
@@ -622,7 +623,7 @@
      */
     private void writeUserLocked(UserInfo userInfo) {
         FileOutputStream fos = null;
-        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userInfo.id + ".xml"));
+        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userInfo.id + XML_SUFFIX));
         try {
             fos = userFile.startWrite();
             final BufferedOutputStream bos = new BufferedOutputStream(fos);
@@ -751,7 +752,7 @@
         FileInputStream fis = null;
         try {
             AtomicFile userFile =
-                    new AtomicFile(new File(mUsersDir, Integer.toString(id) + ".xml"));
+                    new AtomicFile(new File(mUsersDir, Integer.toString(id) + XML_SUFFIX));
             fis = userFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(fis, null);
@@ -909,7 +910,7 @@
                         if (all) {
                             resFile.delete();
                         } else {
-                            String pkg = fileName.substring(RESTRICTIONS_FILE_PREFIX.length());
+                            String pkg = restrictionsFileNameToPackage(fileName);
                             if (!isPackageInstalled(pkg, userId)) {
                                 resFile.delete();
                             }
@@ -926,7 +927,7 @@
     private void cleanAppRestrictionsForPackage(String pkg, int userId) {
         synchronized (mPackagesLock) {
             File dir = Environment.getUserSystemDirectory(userId);
-            File resFile = new File(dir, RESTRICTIONS_FILE_PREFIX + pkg);
+            File resFile = new File(dir, packageToRestrictionsFileName(pkg));
             if (resFile.exists()) {
                 resFile.delete();
             }
@@ -1072,7 +1073,7 @@
 
         mRestrictionsPinStates.remove(userHandle);
         // Remove user file
-        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + ".xml"));
+        AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
         userFile.delete();
         // Update the user list
         writeUserListLocked();
@@ -1307,7 +1308,7 @@
         try {
             AtomicFile restrictionsFile =
                     new AtomicFile(new File(Environment.getUserSystemDirectory(userId),
-                            RESTRICTIONS_FILE_PREFIX + packageName + ".xml"));
+                            packageToRestrictionsFileName(packageName)));
             fis = restrictionsFile.openRead();
             XmlPullParser parser = Xml.newPullParser();
             parser.setInput(fis, null);
@@ -1368,7 +1369,7 @@
         FileOutputStream fos = null;
         AtomicFile restrictionsFile = new AtomicFile(
                 new File(Environment.getUserSystemDirectory(userId),
-                        RESTRICTIONS_FILE_PREFIX + packageName + ".xml"));
+                        packageToRestrictionsFileName(packageName)));
         try {
             fos = restrictionsFile.startWrite();
             final BufferedOutputStream bos = new BufferedOutputStream(fos);
@@ -1498,6 +1499,15 @@
         }
     }
 
+    private String packageToRestrictionsFileName(String packageName) {
+        return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX;
+    }
+
+    private String restrictionsFileNameToPackage(String fileName) {
+        return fileName.substring(RESTRICTIONS_FILE_PREFIX.length(),
+                (int) (fileName.length() - XML_SUFFIX.length()));
+    }
+
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java
index 625770c..d4583b5 100644
--- a/services/java/com/android/server/print/PrintManagerService.java
+++ b/services/java/com/android/server/print/PrintManagerService.java
@@ -448,6 +448,10 @@
                         .queryIntentServicesAsUser(intent, PackageManager.GET_SERVICES,
                                 getChangingUserId());
 
+                if (installedServices == null) {
+                    return;
+                }
+
                 final int installedServiceCount = installedServices.size();
                 for (int i = 0; i < installedServiceCount; i++) {
                     ServiceInfo serviceInfo = installedServices.get(i).serviceInfo;