Merge "Revert "finished implementation of fingerprintservice enumerate"" into oc-dev
diff --git a/api/current.txt b/api/current.txt
index 058743a..9b6227f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -41082,9 +41082,9 @@
   public static final class FontConfig.Font implements android.os.Parcelable {
     method public int describeContents();
     method public android.text.FontConfig.Axis[] getAxes();
-    method public android.os.ParcelFileDescriptor getFd();
     method public java.lang.String getFontName();
     method public int getTtcIndex();
+    method public android.net.Uri getUri();
     method public int getWeight();
     method public boolean isItalic();
     method public void writeToParcel(android.os.Parcel, int);
@@ -48831,6 +48831,7 @@
     method public int getRendererRequestedPriority();
     method public deprecated float getScale();
     method public android.webkit.WebSettings getSettings();
+    method public android.view.textclassifier.TextClassifier getTextClassifier();
     method public java.lang.String getTitle();
     method public java.lang.String getUrl();
     method public android.webkit.WebChromeClient getWebChromeClient();
@@ -48877,6 +48878,7 @@
     method public void setNetworkAvailable(boolean);
     method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
     method public void setRendererPriorityPolicy(int, boolean);
+    method public void setTextClassifier(android.view.textclassifier.TextClassifier);
     method public deprecated void setVerticalScrollbarOverlay(boolean);
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
diff --git a/api/system-current.txt b/api/system-current.txt
index c1e3893..515cf97 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -44536,9 +44536,9 @@
   public static final class FontConfig.Font implements android.os.Parcelable {
     method public int describeContents();
     method public android.text.FontConfig.Axis[] getAxes();
-    method public android.os.ParcelFileDescriptor getFd();
     method public java.lang.String getFontName();
     method public int getTtcIndex();
+    method public android.net.Uri getUri();
     method public int getWeight();
     method public boolean isItalic();
     method public void writeToParcel(android.os.Parcel, int);
@@ -52382,6 +52382,7 @@
     method public int getRendererRequestedPriority();
     method public deprecated float getScale();
     method public android.webkit.WebSettings getSettings();
+    method public android.view.textclassifier.TextClassifier getTextClassifier();
     method public java.lang.String getTitle();
     method public java.lang.String getUrl();
     method public android.webkit.WebChromeClient getWebChromeClient();
@@ -52429,6 +52430,7 @@
     method public void setNetworkAvailable(boolean);
     method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
     method public void setRendererPriorityPolicy(int, boolean);
+    method public void setTextClassifier(android.view.textclassifier.TextClassifier);
     method public deprecated void setVerticalScrollbarOverlay(boolean);
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
@@ -52670,6 +52672,7 @@
     method public abstract float getScale();
     method public abstract android.webkit.WebViewProvider.ScrollDelegate getScrollDelegate();
     method public abstract android.webkit.WebSettings getSettings();
+    method public default android.view.textclassifier.TextClassifier getTextClassifier();
     method public abstract java.lang.String getTitle();
     method public abstract java.lang.String getTouchIconUrl();
     method public abstract java.lang.String getUrl();
@@ -52722,6 +52725,7 @@
     method public abstract void setNetworkAvailable(boolean);
     method public abstract void setPictureListener(android.webkit.WebView.PictureListener);
     method public abstract void setRendererPriorityPolicy(int, boolean);
+    method public default void setTextClassifier(android.view.textclassifier.TextClassifier);
     method public abstract void setVerticalScrollbarOverlay(boolean);
     method public abstract void setWebChromeClient(android.webkit.WebChromeClient);
     method public abstract void setWebViewClient(android.webkit.WebViewClient);
diff --git a/api/test-current.txt b/api/test-current.txt
index fae1436..051e2e6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -41289,9 +41289,9 @@
   public static final class FontConfig.Font implements android.os.Parcelable {
     method public int describeContents();
     method public android.text.FontConfig.Axis[] getAxes();
-    method public android.os.ParcelFileDescriptor getFd();
     method public java.lang.String getFontName();
     method public int getTtcIndex();
+    method public android.net.Uri getUri();
     method public int getWeight();
     method public boolean isItalic();
     method public void writeToParcel(android.os.Parcel, int);
@@ -49214,6 +49214,7 @@
     method public int getRendererRequestedPriority();
     method public deprecated float getScale();
     method public android.webkit.WebSettings getSettings();
+    method public android.view.textclassifier.TextClassifier getTextClassifier();
     method public java.lang.String getTitle();
     method public java.lang.String getUrl();
     method public android.webkit.WebChromeClient getWebChromeClient();
@@ -49260,6 +49261,7 @@
     method public void setNetworkAvailable(boolean);
     method public deprecated void setPictureListener(android.webkit.WebView.PictureListener);
     method public void setRendererPriorityPolicy(int, boolean);
+    method public void setTextClassifier(android.view.textclassifier.TextClassifier);
     method public deprecated void setVerticalScrollbarOverlay(boolean);
     method public void setWebChromeClient(android.webkit.WebChromeClient);
     method public static void setWebContentsDebuggingEnabled(boolean);
diff --git a/core/java/android/text/FontConfig.java b/core/java/android/text/FontConfig.java
index 70f9bdd..14d3ad7 100644
--- a/core/java/android/text/FontConfig.java
+++ b/core/java/android/text/FontConfig.java
@@ -22,13 +22,11 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.FontListParser;
+import android.net.Uri;
 import android.os.Parcel;
-import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
 
-import java.io.IOException;
 import java.lang.annotation.Retention;
-import java.util.Arrays;
 
 
 /**
@@ -44,20 +42,6 @@
     }
 
     /**
-     * For duplicating file descriptors.
-     *
-     * Note that this copy constructor can not be usable for deep copy.
-     * @hide
-     */
-    public FontConfig(@NonNull FontConfig config) {
-        mFamilies = new Family[config.mFamilies.length];
-        for (int i = 0; i < config.mFamilies.length; ++i) {
-            mFamilies[i] = new Family(config.mFamilies[i]);
-        }
-        mAliases = Arrays.copyOf(config.mAliases, config.mAliases.length);
-    }
-
-    /**
      * Returns the ordered list of families included in the system fonts.
      */
     public @NonNull Family[] getFamilies() {
@@ -174,7 +158,7 @@
         private final @NonNull Axis[] mAxes;
         private final int mWeight;
         private final boolean mIsItalic;
-        private @Nullable ParcelFileDescriptor mFd;
+        private Uri mUri;
 
         /**
          * @hide
@@ -186,29 +170,6 @@
             mAxes = axes;
             mWeight = weight;
             mIsItalic = isItalic;
-            mFd = null;
-        }
-
-        /**
-         * This is for duplicating FileDescriptors.
-         *
-         * Note that this copy ctor doesn't deep copy the members.
-         *
-         * @hide
-         */
-        public Font(Font origin) {
-            mFontName = origin.mFontName;
-            mTtcIndex = origin.mTtcIndex;
-            mAxes = origin.mAxes;
-            mWeight = origin.mWeight;
-            mIsItalic = origin.mIsItalic;
-            if (origin.mFd != null) {
-                try {
-                    mFd = origin.mFd.dup();
-                } catch (IOException e) {
-                    e.printStackTrace();
-                }
-            }
         }
 
         /**
@@ -247,17 +208,20 @@
         }
 
         /**
-         * Returns a file descriptor to access the specified font. This should be closed after use.
+         * Returns the content uri associated to this font.
+         *
+         * You can reach to the font contents by calling {@link
+         * android.content.ContentResolver#openInputStream}.
          */
-        public @Nullable ParcelFileDescriptor getFd() {
-            return mFd;
+        public @Nullable Uri getUri() {
+            return mUri;
         }
 
         /**
          * @hide
          */
-        public void setFd(@NonNull ParcelFileDescriptor fd) {
-            mFd = fd;
+        public void setUri(@NonNull Uri uri) {
+            mUri = uri;
         }
 
         /**
@@ -269,11 +233,7 @@
             mAxes = in.createTypedArray(Axis.CREATOR);
             mWeight = in.readInt();
             mIsItalic = in.readInt() == 1;
-            if (in.readInt() == 1) { /* has FD */
-                mFd = ParcelFileDescriptor.CREATOR.createFromParcel(in);
-            } else {
-                mFd = null;
-            }
+            mUri = in.readTypedObject(Uri.CREATOR);
         }
 
         @Override
@@ -283,10 +243,7 @@
             out.writeTypedArray(mAxes, flag);
             out.writeInt(mWeight);
             out.writeInt(mIsItalic ? 1 : 0);
-            out.writeInt(mFd == null ? 0 : 1);
-            if (mFd != null) {
-                mFd.writeToParcel(out, flag);
-            }
+            out.writeTypedObject(mUri, flag);
         }
 
         @Override
@@ -425,22 +382,6 @@
         }
 
         /**
-         * For duplicating file descriptor underlying Font object.
-         *
-         * This copy constructor is not for deep copying.
-         * @hide
-         */
-        public Family(Family origin) {
-            mName = origin.mName;
-            mLanguage = origin.mLanguage;
-            mVariant = origin.mVariant;
-            mFonts = new Font[origin.mFonts.length];
-            for (int i = 0; i < origin.mFonts.length; ++i) {
-                mFonts[i] = new Font(origin.mFonts[i]);
-            }
-        }
-
-        /**
          * Returns the name given by the system to this font family.
          */
         public @Nullable String getName() {
diff --git a/core/java/android/view/textclassifier/TextClassificationManager.java b/core/java/android/view/textclassifier/TextClassificationManager.java
index 35c9a29..5487965 100644
--- a/core/java/android/view/textclassifier/TextClassificationManager.java
+++ b/core/java/android/view/textclassifier/TextClassificationManager.java
@@ -44,8 +44,6 @@
     private final Object mLangIdLock = new Object();
 
     private final Context mContext;
-    // TODO: Implement a way to close the file descriptors.
-    private ParcelFileDescriptor mSmartSelectionFd;
     private ParcelFileDescriptor mLangIdFd;
     private TextClassifier mDefault;
     private LangId mLangId;
@@ -61,15 +59,7 @@
     public TextClassifier getDefaultTextClassifier() {
         synchronized (mTextClassifierLock) {
             if (mDefault == null) {
-                try {
-                    mSmartSelectionFd = ParcelFileDescriptor.open(
-                            new File("/etc/textclassifier/textclassifier.smartselection.en.model"),
-                            ParcelFileDescriptor.MODE_READ_ONLY);
-                    mDefault = new TextClassifierImpl(mContext, mSmartSelectionFd);
-                } catch (FileNotFoundException e) {
-                    Log.e(LOG_TAG, "Error accessing 'text classifier selection' model file.", e);
-                    mDefault = TextClassifier.NO_OP;
-                }
+                mDefault = new TextClassifierImpl(mContext);
             }
             return mDefault;
         }
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 66a62c3..f634a1b 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -38,17 +38,24 @@
 import android.util.Patterns;
 import android.view.View;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Default implementation of the {@link TextClassifier} interface.
@@ -62,16 +69,21 @@
 final class TextClassifierImpl implements TextClassifier {
 
     private static final String LOG_TAG = "TextClassifierImpl";
-
-    private final Object mSmartSelectionLock = new Object();
+    private static final String MODEL_DIR = "/etc/textclassifier/";
+    private static final String MODEL_FILE_REGEX = "textclassifier\\.smartselection\\.(.*)\\.model";
 
     private final Context mContext;
-    private final ParcelFileDescriptor mFd;
+
+    private final Object mSmartSelectionLock = new Object();
+    @GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
+    private Map<Locale, String> mModelFilePaths;
+    @GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
+    private Locale mLocale;
+    @GuardedBy("mSmartSelectionLock") // Do not access outside this lock.
     private SmartSelection mSmartSelection;
 
-    TextClassifierImpl(Context context, ParcelFileDescriptor fd) {
+    TextClassifierImpl(Context context) {
         mContext = Preconditions.checkNotNull(context);
-        mFd = Preconditions.checkNotNull(fd);
     }
 
     @Override
@@ -81,15 +93,16 @@
         validateInput(text, selectionStartIndex, selectionEndIndex);
         try {
             if (text.length() > 0) {
+                final SmartSelection smartSelection = getSmartSelection(defaultLocales);
                 final String string = text.toString();
-                final int[] startEnd = getSmartSelection()
-                        .suggest(string, selectionStartIndex, selectionEndIndex);
+                final int[] startEnd = smartSelection.suggest(
+                        string, selectionStartIndex, selectionEndIndex);
                 final int start = startEnd[0];
                 final int end = startEnd[1];
                 if (start >= 0 && end <= string.length() && start <= end) {
                     final TextSelection.Builder tsBuilder = new TextSelection.Builder(start, end);
                     final SmartSelection.ClassificationResult[] results =
-                            getSmartSelection().classifyText(
+                            smartSelection.classifyText(
                                     string, start, end,
                                     getHintFlags(string, start, end));
                     final int size = results.length;
@@ -120,7 +133,7 @@
         try {
             if (text.length() > 0) {
                 final String string = text.toString();
-                SmartSelection.ClassificationResult[] results = getSmartSelection()
+                SmartSelection.ClassificationResult[] results = getSmartSelection(defaultLocales)
                         .classifyText(string, startIndex, endIndex,
                                 getHintFlags(string, startIndex, endIndex));
                 if (results.length > 0) {
@@ -147,7 +160,7 @@
         Preconditions.checkArgument(text != null);
         try {
             return LinksInfoFactory.create(
-                    mContext, getSmartSelection(), text.toString(), linkMask);
+                    mContext, getSmartSelection(defaultLocales), text.toString(), linkMask);
         } catch (Throwable t) {
             // Avoid throwing from this method. Log the error.
             Log.e(LOG_TAG, "Error getting links info.", t);
@@ -156,15 +169,69 @@
         return TextClassifier.NO_OP.getLinks(text, linkMask, defaultLocales);
     }
 
-    private SmartSelection getSmartSelection() throws FileNotFoundException {
+    private SmartSelection getSmartSelection(LocaleList localeList) throws FileNotFoundException {
         synchronized (mSmartSelectionLock) {
-            if (mSmartSelection == null) {
-                mSmartSelection = new SmartSelection(mFd.getFd());
+            localeList = localeList == null ? LocaleList.getEmptyLocaleList() : localeList;
+            final Locale locale = findBestSupportedLocaleLocked(localeList);
+            if (mSmartSelection == null || !Objects.equals(mLocale, locale)) {
+                destroySmartSelectionIfExistsLocked();
+                mSmartSelection = new SmartSelection(
+                        ParcelFileDescriptor.open(
+                                // findBestSupportedLocaleLocked should have initialized
+                                // mModelFilePaths
+                                new File(mModelFilePaths.get(locale)),
+                                ParcelFileDescriptor.MODE_READ_ONLY)
+                                .getFd());
+                mLocale = locale;
             }
             return mSmartSelection;
         }
     }
 
+    @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
+    private void destroySmartSelectionIfExistsLocked() {
+        if (mSmartSelection != null) {
+            mSmartSelection.close();
+            mSmartSelection = null;
+        }
+    }
+
+    @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
+    @Nullable
+    private Locale findBestSupportedLocaleLocked(LocaleList localeList) {
+        final List<Locale.LanguageRange> languageRangeList = Locale.LanguageRange.parse(
+                new StringJoiner(",")
+                        // Specified localeList takes priority over the system default
+                        .add(localeList.toLanguageTags())
+                        .add(LocaleList.getDefault().toLanguageTags())
+                        .toString());
+        return Locale.lookup(languageRangeList, loadModelFilePathsLocked().keySet());
+    }
+
+    @GuardedBy("mSmartSelectionLock") // Do not call outside this lock.
+    private Map<Locale, String> loadModelFilePathsLocked() {
+        if (mModelFilePaths == null) {
+            final Map<Locale, String> modelFilePaths = new HashMap<>();
+            final File modelsDir = new File(MODEL_DIR);
+            if (modelsDir.exists() && modelsDir.isDirectory()) {
+                final File[] models = modelsDir.listFiles();
+                final Pattern modelFilenamePattern = Pattern.compile(MODEL_FILE_REGEX);
+                final int size = models.length;
+                for (int i = 0; i < size; i++) {
+                    final File modelFile = models[i];
+                    final Matcher matcher = modelFilenamePattern.matcher(modelFile.getName());
+                    if (matcher.matches() && modelFile.isFile()) {
+                        final String language = matcher.group(1);
+                        final Locale locale = Locale.forLanguageTag(language);
+                        modelFilePaths.put(locale, modelFile.getAbsolutePath());
+                    }
+                }
+            }
+            mModelFilePaths = modelFilePaths;
+        }
+        return mModelFilePaths;
+    }
+
     private TextClassificationResult createClassificationResult(
             SmartSelection.ClassificationResult[] classifications, CharSequence text) {
         final TextClassificationResult.Builder builder = new TextClassificationResult.Builder()
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index c2b4138..bc49123 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.Widget;
 import android.content.Context;
@@ -58,6 +59,7 @@
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
+import android.view.textclassifier.TextClassifier;
 import android.widget.AbsoluteLayout;
 
 import java.io.BufferedWriter;
@@ -2249,6 +2251,23 @@
     public boolean getRendererPriorityWaivedWhenNotVisible() {
         return mProvider.getRendererPriorityWaivedWhenNotVisible();
     }
+
+    /**
+     * Sets the {@link TextClassifier} for this WebView.
+     */
+    public void setTextClassifier(@Nullable TextClassifier textClassifier) {
+        mProvider.setTextClassifier(textClassifier);
+    }
+
+    /**
+     * Returns the {@link TextClassifier} used by this WebView.
+     * If no TextClassifier has been set, this WebView uses the default set by the system.
+     */
+    @NonNull
+    public TextClassifier getTextClassifier() {
+        return mProvider.getTextClassifier();
+    }
+
     //-------------------------------------------------------------------------
     // Interface for WebView providers
     //-------------------------------------------------------------------------
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 5724a9b..aa1ffa2 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -16,6 +16,8 @@
 
 package android.webkit;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.content.res.Configuration;
 import android.content.Intent;
@@ -41,6 +43,7 @@
 import android.view.accessibility.AccessibilityNodeProvider;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
+import android.view.textclassifier.TextClassifier;
 import android.webkit.WebView.HitTestResult;
 import android.webkit.WebView.PictureListener;
 import android.webkit.WebView.VisualStateCallback;
@@ -275,6 +278,12 @@
 
     public boolean getRendererPriorityWaivedWhenNotVisible();
 
+    @SuppressWarnings("unused")
+    public default void setTextClassifier(@Nullable TextClassifier textClassifier) {}
+
+    @NonNull
+    public default TextClassifier getTextClassifier() { return TextClassifier.NO_OP; }
+
     //-------------------------------------------------------------------------
     // Provider internal methods
     //-------------------------------------------------------------------------
diff --git a/graphics/java/android/graphics/FontListParser.java b/graphics/java/android/graphics/FontListParser.java
index b78df34..ff9f11d 100644
--- a/graphics/java/android/graphics/FontListParser.java
+++ b/graphics/java/android/graphics/FontListParser.java
@@ -189,9 +189,8 @@
                 skip(parser);
             }
         }
-        String fullFilename = "/system/fonts/" +
-                FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
-        return new FontConfig.Font(fullFilename, index,
+        String sanitizedName = FILENAME_WHITESPACE_PATTERN.matcher(filename).replaceAll("");
+        return new FontConfig.Font(sanitizedName, index,
                 axes.toArray(new FontConfig.Axis[axes.size()]), weight, isItalic);
     }
 
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 228d950..8c3a2e8 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1003,21 +1003,22 @@
             Map<String, ByteBuffer> bufferForPath) {
         FontFamily fontFamily = new FontFamily(family.getLanguage(), family.getVariant());
         for (FontConfig.Font font : family.getFonts()) {
-            ByteBuffer fontBuffer = bufferForPath.get(font.getFontName());
+            String fullPathName = "/system/fonts/" + font.getFontName();
+            ByteBuffer fontBuffer = bufferForPath.get(fullPathName);
             if (fontBuffer == null) {
-                try (FileInputStream file = new FileInputStream(font.getFontName())) {
+                try (FileInputStream file = new FileInputStream(fullPathName)) {
                     FileChannel fileChannel = file.getChannel();
                     long fontSize = fileChannel.size();
                     fontBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fontSize);
-                    bufferForPath.put(font.getFontName(), fontBuffer);
+                    bufferForPath.put(fullPathName, fontBuffer);
                 } catch (IOException e) {
-                    Log.e(TAG, "Error mapping font file " + font.getFontName());
+                    Log.e(TAG, "Error mapping font file " + fullPathName);
                     continue;
                 }
             }
             if (!fontFamily.addFontFromBuffer(fontBuffer, font.getTtcIndex(), font.getAxes(),
                     font.getWeight(), font.isItalic() ? Builder.ITALIC : Builder.NORMAL)) {
-                Log.e(TAG, "Error creating font " + font.getFontName() + "#" + font.getTtcIndex());
+                Log.e(TAG, "Error creating font " + fullPathName + "#" + font.getTtcIndex());
             }
         }
         fontFamily.freeze();
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index bf17e38..0c0bdeb 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1869,9 +1869,6 @@
     <!-- Title of menu shown over picture-in-picture. Used for accessibility. -->
     <string name="pip_menu_title">Picture in picture menu</string>
 
-    <!-- User visible notification channel name for the PiP BTW notification. [CHAR LIMIT=NONE] -->
-    <string name="pip_notification_channel_name">Picture-in-picture</string>
-
     <!-- PiP BTW notification title. [CHAR LIMIT=50] -->
     <string name="pip_notification_title"><xliff:g id="name" example="Google Maps">%s</xliff:g> is in picture-in-picture</string>
 
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java
index bdd6b65..9bf6d6e 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipNotificationController.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.pip.phone;
 
-import static android.app.NotificationManager.IMPORTANCE_MIN;
 import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -24,7 +23,6 @@
 
 import android.app.IActivityManager;
 import android.app.Notification;
-import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -40,6 +38,7 @@
 
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
+import com.android.systemui.util.NotificationChannels;
 
 /**
  * Manages the BTW notification that shows whenever an activity enters or leaves picture-in-picture.
@@ -47,8 +46,8 @@
 public class PipNotificationController {
     private static final String TAG = PipNotificationController.class.getSimpleName();
 
-    private static final String CHANNEL_ID = PipNotificationController.class.getName();
-    private static final int BTW_NOTIFICATION_ID = 0;
+    private static final String NOTIFICATION_TAG = PipNotificationController.class.getName();
+    private static final int NOTIFICATION_ID = 0;
 
     private Context mContext;
     private IActivityManager mActivityManager;
@@ -58,25 +57,25 @@
         mContext = context;
         mActivityManager = activityManager;
         mNotificationManager = NotificationManager.from(context);
-        createNotificationChannel();
     }
 
     public void onActivityPinned(String packageName) {
         // Clear any existing notification
-        mNotificationManager.cancel(CHANNEL_ID, BTW_NOTIFICATION_ID);
+        mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
 
         // Build a new notification
-        final Notification.Builder builder = new Notification.Builder(mContext, CHANNEL_ID)
-                .setLocalOnly(true)
-                .setOngoing(true)
-                .setSmallIcon(R.drawable.pip_notification_icon)
-                .setColor(mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color));
+        final Notification.Builder builder =
+                new Notification.Builder(mContext, NotificationChannels.GENERAL)
+                        .setLocalOnly(true)
+                        .setOngoing(true)
+                        .setSmallIcon(R.drawable.pip_notification_icon)
+                        .setColor(mContext.getColor(
+                                com.android.internal.R.color.system_notification_accent_color));
         if (updateNotificationForApp(builder, packageName)) {
             SystemUI.overrideNotificationAppName(mContext, builder);
 
             // Show the new notification
-            mNotificationManager.notify(CHANNEL_ID, BTW_NOTIFICATION_ID, builder.build());
+            mNotificationManager.notify(NOTIFICATION_TAG, NOTIFICATION_ID, builder.build());
         }
     }
 
@@ -85,26 +84,11 @@
         if (topPipActivity != null) {
             onActivityPinned(topPipActivity.getPackageName());
         } else {
-            mNotificationManager.cancel(CHANNEL_ID, BTW_NOTIFICATION_ID);
+            mNotificationManager.cancel(NOTIFICATION_TAG, NOTIFICATION_ID);
         }
     }
 
     /**
-     * Create the notification channel for the PiP BTW notifications if necessary.
-     */
-    private NotificationChannel createNotificationChannel() {
-        NotificationChannel channel = mNotificationManager.getNotificationChannel(CHANNEL_ID);
-        if (channel == null) {
-            channel = new NotificationChannel(CHANNEL_ID,
-                    mContext.getString(R.string.pip_notification_channel_name), IMPORTANCE_MIN);
-            channel.enableLights(false);
-            channel.enableVibration(false);
-            mNotificationManager.createNotificationChannel(channel);
-        }
-        return channel;
-    }
-
-    /**
      * Updates the notification builder with app-specific information, returning whether it was
      * successful.
      */
diff --git a/services/core/java/com/android/server/FontManagerService.java b/services/core/java/com/android/server/FontManagerService.java
index 55a945a..f172647 100644
--- a/services/core/java/com/android/server/FontManagerService.java
+++ b/services/core/java/com/android/server/FontManagerService.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.graphics.FontListParser;
+import android.net.Uri;
 import android.os.ParcelFileDescriptor;
 import android.text.FontConfig;
 import android.util.Slog;
@@ -34,6 +35,7 @@
 public class FontManagerService extends IFontManager.Stub {
     private static final String TAG = "FontManagerService";
     private static final String FONTS_CONFIG = "/system/etc/fonts.xml";
+    private static final String SYSTEM_FONT_DIR = "/system/fonts/";
 
     @GuardedBy("mLock")
     private FontConfig mConfig;
@@ -63,28 +65,22 @@
     public FontConfig getSystemFonts() {
         synchronized (mLock) {
             if (mConfig != null) {
-                return new FontConfig(mConfig);
+                return mConfig;
             }
 
-            FontConfig config = loadFromSystem();
-            if (config == null) {
+            mConfig = loadFromSystem();
+            if (mConfig == null) {
                 return null;
             }
 
-            for (FontConfig.Family family : config.getFamilies()) {
+            for (FontConfig.Family family : mConfig.getFamilies()) {
                 for (FontConfig.Font font : family.getFonts()) {
-                    File fontFile = new File(font.getFontName());
-                    try {
-                        font.setFd(ParcelFileDescriptor.open(
-                                fontFile, ParcelFileDescriptor.MODE_READ_ONLY));
-                    } catch (IOException e) {
-                        Slog.e(TAG, "Error opening font file " + font.getFontName(), e);
-                    }
+                    File fontFile = new File(SYSTEM_FONT_DIR, font.getFontName());
+                    font.setUri(Uri.fromFile(fontFile));
                 }
             }
 
-            mConfig = config;
-            return new FontConfig(mConfig);
+            return mConfig;
         }
     }