Merge "Fix font golden image using Oracle JDK"
diff --git a/api/removed.txt b/api/removed.txt
index 8acf4ad..75da976 100644
--- a/api/removed.txt
+++ b/api/removed.txt
@@ -380,16 +380,6 @@
 
 }
 
-package android.view.textclassifier {
-
-  public abstract interface TextClassifier {
-    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
-    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
-    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
-  }
-
-}
-
 package android.webkit {
 
   public class WebViewClient {
diff --git a/api/system-removed.txt b/api/system-removed.txt
index a2fcbcd..3aa9398 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -374,16 +374,6 @@
 
 }
 
-package android.view.textclassifier {
-
-  public abstract interface TextClassifier {
-    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
-    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
-    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
-  }
-
-}
-
 package android.webkit {
 
   public class WebViewClient {
diff --git a/api/test-removed.txt b/api/test-removed.txt
index 8acf4ad..75da976 100644
--- a/api/test-removed.txt
+++ b/api/test-removed.txt
@@ -380,16 +380,6 @@
 
 }
 
-package android.view.textclassifier {
-
-  public abstract interface TextClassifier {
-    method public abstract android.view.textclassifier.LinksInfo getLinks(java.lang.CharSequence, int);
-    method public abstract android.view.textclassifier.TextClassificationResult getTextClassificationResult(java.lang.CharSequence, int, int);
-    method public abstract android.view.textclassifier.TextSelection suggestSelection(java.lang.CharSequence, int, int);
-  }
-
-}
-
 package android.webkit {
 
   public class WebViewClient {
diff --git a/cmds/sm/src/com/android/commands/sm/Sm.java b/cmds/sm/src/com/android/commands/sm/Sm.java
index db3772d..658d662 100644
--- a/cmds/sm/src/com/android/commands/sm/Sm.java
+++ b/cmds/sm/src/com/android/commands/sm/Sm.java
@@ -94,6 +94,8 @@
             runGetFbeMode();
         } else if ("fstrim".equals(op)) {
             runFstrim();
+        } else if ("set-virtual-disk".equals(op)) {
+            runSetVirtualDisk();
         } else {
             throw new IllegalArgumentException();
         }
@@ -225,6 +227,12 @@
         mSm.fstrim(0);
     }
 
+    public void runSetVirtualDisk() throws RemoteException {
+        final boolean virtualDisk = Boolean.parseBoolean(nextArg());
+        mSm.setDebugFlags(virtualDisk ? StorageManager.DEBUG_VIRTUAL_DISK : 0,
+                StorageManager.DEBUG_VIRTUAL_DISK);
+    }
+
     private String nextArg() {
         if (mNextArg >= mArgs.length) {
             return null;
@@ -240,6 +248,7 @@
         System.err.println("       sm has-adoptable");
         System.err.println("       sm get-primary-storage-uuid");
         System.err.println("       sm set-force-adoptable [true|false]");
+        System.err.println("       sm set-virtual-disk [true|false]");
         System.err.println("");
         System.err.println("       sm partition DISK [public|private|mixed] [ratio]");
         System.err.println("       sm mount VOLUME");
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 2e35a51..76128e6 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -2039,14 +2039,20 @@
         }
     }
 
+    /** @deprecated use {@link android.system.Os#open(String, int, int)} */
+    @Deprecated
+    static native FileDescriptor openFileDescriptor(String file, int mode)
+            throws FileNotFoundException;
 
-    /*package*/ static native FileDescriptor openFileDescriptor(String file,
-            int mode) throws FileNotFoundException;
-    /*package*/ static native FileDescriptor dupFileDescriptor(FileDescriptor orig)
-            throws IOException;
-    /*package*/ static native void closeFileDescriptor(FileDescriptor desc)
-            throws IOException;
-    /*package*/ static native void clearFileDescriptor(FileDescriptor desc);
+    /** @deprecated use {@link android.system.Os#dup(FileDescriptor)} */
+    @Deprecated
+    static native FileDescriptor dupFileDescriptor(FileDescriptor orig) throws IOException;
+
+    /** @deprecated use {@link android.system.Os#close(FileDescriptor)} */
+    @Deprecated
+    static native void closeFileDescriptor(FileDescriptor desc) throws IOException;
+
+    static native void clearFileDescriptor(FileDescriptor desc);
 
     /**
      * Read a byte value from the parcel at the current dataPosition().
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 8882672..3212139 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -17,11 +17,21 @@
 package android.os;
 
 import static android.system.OsConstants.AF_UNIX;
+import static android.system.OsConstants.O_APPEND;
+import static android.system.OsConstants.O_CREAT;
+import static android.system.OsConstants.O_RDONLY;
+import static android.system.OsConstants.O_RDWR;
+import static android.system.OsConstants.O_TRUNC;
+import static android.system.OsConstants.O_WRONLY;
 import static android.system.OsConstants.SEEK_SET;
-import static android.system.OsConstants.SOCK_STREAM;
 import static android.system.OsConstants.SOCK_SEQPACKET;
+import static android.system.OsConstants.SOCK_STREAM;
+import static android.system.OsConstants.S_IROTH;
+import static android.system.OsConstants.S_IRWXG;
+import static android.system.OsConstants.S_IRWXU;
 import static android.system.OsConstants.S_ISLNK;
 import static android.system.OsConstants.S_ISREG;
+import static android.system.OsConstants.S_IWOTH;
 
 import android.content.BroadcastReceiver;
 import android.content.ContentProvider;
@@ -33,6 +43,7 @@
 import android.util.Log;
 
 import dalvik.system.CloseGuard;
+
 import libcore.io.IoUtils;
 import libcore.io.Memory;
 
@@ -279,8 +290,28 @@
                     "Must specify MODE_READ_ONLY, MODE_WRITE_ONLY, or MODE_READ_WRITE");
         }
 
+        int flags = 0;
+        switch (mode & MODE_READ_WRITE) {
+            case 0:
+            case MODE_READ_ONLY: flags = O_RDONLY; break;
+            case MODE_WRITE_ONLY: flags = O_WRONLY; break;
+            case MODE_READ_WRITE: flags = O_RDWR; break;
+        }
+
+        if ((mode & MODE_CREATE) != 0) flags |= O_CREAT;
+        if ((mode & MODE_TRUNCATE) != 0) flags |= O_TRUNC;
+        if ((mode & MODE_APPEND) != 0) flags |= O_APPEND;
+
+        int realMode = S_IRWXU | S_IRWXG;
+        if ((mode & MODE_WORLD_READABLE) != 0) realMode |= S_IROTH;
+        if ((mode & MODE_WORLD_WRITEABLE) != 0) realMode |= S_IWOTH;
+
         final String path = file.getPath();
-        return Parcel.openFileDescriptor(path, mode);
+        try {
+            return Os.open(path, flags, realMode);
+        } catch (ErrnoException e) {
+            throw new FileNotFoundException(e.getMessage());
+        }
     }
 
     /**
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 53c9a23..7e1b5ab 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -113,6 +113,8 @@
     public static final String PROP_EMULATE_FBE = "persist.sys.emulate_fbe";
     /** {@hide} */
     public static final String PROP_SDCARDFS = "persist.sys.sdcardfs";
+    /** {@hide} */
+    public static final String PROP_VIRTUAL_DISK = "persist.sys.virtual_disk";
 
     /** {@hide} */
     public static final String UUID_PRIVATE_INTERNAL = null;
@@ -140,6 +142,8 @@
     public static final int DEBUG_SDCARDFS_FORCE_ON = 1 << 2;
     /** {@hide} */
     public static final int DEBUG_SDCARDFS_FORCE_OFF = 1 << 3;
+    /** {@hide} */
+    public static final int DEBUG_VIRTUAL_DISK = 1 << 4;
 
     // NOTE: keep in sync with installd
     /** {@hide} */
diff --git a/core/java/android/view/textclassifier/TextClassifier.java b/core/java/android/view/textclassifier/TextClassifier.java
index 46f7a81..dabbf31 100644
--- a/core/java/android/view/textclassifier/TextClassifier.java
+++ b/core/java/android/view/textclassifier/TextClassifier.java
@@ -70,26 +70,6 @@
         public LinksInfo getLinks(CharSequence text, int linkMask, LocaleList defaultLocales) {
             return LinksInfo.NO_OP;
         }
-
-        // TODO: Remove
-        @Override
-        public TextSelection suggestSelection(
-                CharSequence text, int selectionStartIndex, int selectionEndIndex) {
-            throw new UnsupportedOperationException("Removed");
-        }
-
-        // TODO: Remove
-        @Override
-        public TextClassificationResult getTextClassificationResult(
-                CharSequence text, int startIndex, int endIndex) {
-            throw new UnsupportedOperationException("Removed");
-        }
-
-        // TODO: Remove
-        @Override
-        public LinksInfo getLinks(CharSequence text, int linkMask) {
-            throw new UnsupportedOperationException("Removed");
-        }
     };
 
     /**
@@ -154,16 +134,4 @@
      */
     LinksInfo getLinks(
             @NonNull CharSequence text, int linkMask, @Nullable LocaleList defaultLocales);
-
-    // TODO: Remove
-    /** @removed */
-    TextSelection suggestSelection(
-            CharSequence text, int selectionStartIndex, int selectionEndIndex);
-    // TODO: Remove
-    /** @removed */
-    TextClassificationResult getTextClassificationResult(
-            CharSequence text, int startIndex, int endIndex);
-    // TODO: Remove
-    /** @removed */
-    LinksInfo getLinks(CharSequence text, int linkMask);
 }
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 06ac869..be12f57 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -120,10 +120,12 @@
                 SmartSelection.ClassificationResult[] results = getSmartSelection()
                         .classifyText(text.toString(), startIndex, endIndex);
                 if (results.length > 0) {
+                    final TextClassificationResult classificationResult =
+                            createClassificationResult(results, classified);
                     // TODO: Added this log for debug only. Remove before release.
                     Log.d(LOG_TAG, String.format(
-                            "Classification type: %s", getHighestScoringType(results)));
-                    return createClassificationResult(results, classified);
+                            "Classification type: %s", classificationResult));
+                    return classificationResult;
                 }
             }
         } catch (Throwable t) {
@@ -149,26 +151,6 @@
         return TextClassifier.NO_OP.getLinks(text, linkMask, defaultLocales);
     }
 
-    // TODO: Remove
-    @Override
-    public TextSelection suggestSelection(
-            CharSequence text, int selectionStartIndex, int selectionEndIndex) {
-        throw new UnsupportedOperationException("Removed");
-    }
-
-    // TODO: Remove
-    @Override
-    public TextClassificationResult getTextClassificationResult(
-            CharSequence text, int startIndex, int endIndex) {
-        throw new UnsupportedOperationException("Removed");
-    }
-
-    // TODO: Remove
-    @Override
-    public LinksInfo getLinks(CharSequence text, int linkMask) {
-        throw new UnsupportedOperationException("Removed");
-    }
-
     private SmartSelection getSmartSelection() throws FileNotFoundException {
         synchronized (mSmartSelectionLock) {
             if (mSmartSelection == null) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 55c886e..0280f26 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -95,7 +95,7 @@
 
     private WifiTrackerNetworkCallback mNetworkCallback;
 
-    private boolean mSavedNetworksExist;
+    private int mNumSavedNetworks;
     private boolean mRegistered;
 
     /** Updated using main handler. Clone of this collection is returned
@@ -363,11 +363,11 @@
     }
 
     /**
-     * @return true when there are saved networks on the device, regardless
-     * of whether the WifiTracker is tracking saved networks.
+     * Returns the number of saved networks on the device, regardless of whether the WifiTracker
+     * is tracking saved networks.
      */
-    public boolean doSavedNetworksExist() {
-        return mSavedNetworksExist;
+    public int getNumSavedNetworks() {
+        return mNumSavedNetworks;
     }
 
     public boolean isConnected() {
@@ -461,11 +461,12 @@
 
         final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
         if (configs != null) {
-            mSavedNetworksExist = configs.size() != 0;
+            mNumSavedNetworks = 0;
             for (WifiConfiguration config : configs) {
                 if (config.selfAdded && config.numAssociation == 0) {
                     continue;
                 }
+                mNumSavedNetworks++;
                 AccessPoint accessPoint = getCachedOrCreate(config, cachedAccessPoints);
                 if (mLastInfo != null && mLastNetworkInfo != null) {
                     accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index e100884..46726f2 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -395,6 +395,26 @@
     }
 
     @Test
+    public void testGetNumSavedNetworks() throws InterruptedException {
+        WifiConfiguration validConfig = new WifiConfiguration();
+        validConfig.SSID = SSID_1;
+        validConfig.BSSID = BSSID_1;
+
+        WifiConfiguration selfAddedNoAssociation = new WifiConfiguration();
+        selfAddedNoAssociation.selfAdded = true;
+        selfAddedNoAssociation.numAssociation = 0;
+        selfAddedNoAssociation.SSID = SSID_2;
+        selfAddedNoAssociation.BSSID = BSSID_2;
+
+        when(mockWifiManager.getConfiguredNetworks())
+                .thenReturn(Arrays.asList(validConfig, selfAddedNoAssociation));
+
+        WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
+
+        assertEquals(1, tracker.getNumSavedNetworks());
+    }
+
+    @Test
     public void startTrackingShouldSetConnectedAccessPointAsActive() throws InterruptedException {
         WifiTracker tracker =  createTrackerWithScanResultsAndAccessPoint1Connected();
 
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 81219da..457c5f8 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2080,6 +2080,20 @@
                 Binder.restoreCallingIdentity(token);
             }
         }
+
+        if ((mask & StorageManager.DEBUG_VIRTUAL_DISK) != 0) {
+            final boolean enabled = (flags & StorageManager.DEBUG_VIRTUAL_DISK) != 0;
+
+            final long token = Binder.clearCallingIdentity();
+            try {
+                SystemProperties.set(StorageManager.PROP_VIRTUAL_DISK, Boolean.toString(enabled));
+
+                // Reset storage to kick new setting into place
+                mHandler.obtainMessage(H_RESET).sendToTarget();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
     }
 
     @Override
diff --git a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
index 43f4ebc..e4b2020 100644
--- a/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
+++ b/tools/layoutlib/bridge/src/android/view/RectShadowPainter.java
@@ -127,6 +127,9 @@
 
     private static void paintGeometricShadow(@NonNull float[][] coordinates, float lightPosX,
             float lightPosY, float lightHeight, float lightSize, Canvas canvas) {
+        if (canvas == null || canvas.getWidth() == 0 || canvas.getHeight() == 0) {
+            return;
+        }
 
         // The polygon of shadow (same as the original item)
         float[] shadowPoly = new float[coordinates.length * 3];