Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ed36dcd authored by Ziad Youssef's avatar Ziad Youssef Committed by Android (Google) Code Review
Browse files

Merge "Refactor pinning webview logic to System dependencies" into main

parents 97062db0 869d25db
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.webkit.Flags.updateServiceV2;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -39,11 +40,14 @@ import android.webkit.WebViewProviderInfo;
import android.webkit.WebViewZygote;

import com.android.internal.util.XmlUtils;
import com.android.server.LocalServices;
import com.android.server.PinnerService;

import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
@@ -60,6 +64,7 @@ public class SystemImpl implements SystemInterface {
    private static final String TAG_AVAILABILITY = "availableByDefault";
    private static final String TAG_SIGNATURE = "signature";
    private static final String TAG_FALLBACK = "isFallback";
    private static final String PIN_GROUP = "webview";
    private final WebViewProviderInfo[] mWebViewProviderPackages;

    // Initialization-on-demand holder idiom for getting the WebView provider packages once and
@@ -277,6 +282,36 @@ public class SystemImpl implements SystemInterface {
        return true;
    }

    @Override
    public void pinWebviewIfRequired(ApplicationInfo appInfo) {
        PinnerService pinnerService = LocalServices.getService(PinnerService.class);
        int webviewPinQuota = pinnerService.getWebviewPinQuota();
        if (webviewPinQuota <= 0) {
            return;
        }

        pinnerService.unpinGroup(PIN_GROUP);

        ArrayList<String> apksToPin = new ArrayList<>();
        boolean pinSharedFirst = appInfo.metaData.getBoolean("PIN_SHARED_LIBS_FIRST", true);
        for (String sharedLib : appInfo.sharedLibraryFiles) {
            apksToPin.add(sharedLib);
        }
        apksToPin.add(appInfo.sourceDir);
        if (!pinSharedFirst) {
            // We want to prioritize pinning of the native library that is most likely used by apps
            // which in some build flavors live in the main apk and as a shared library for others.
            Collections.reverse(apksToPin);
        }
        for (String apk : apksToPin) {
            if (webviewPinQuota <= 0) {
                break;
            }
            int bytesPinned = pinnerService.pinFile(apk, webviewPinQuota, appInfo, PIN_GROUP);
            webviewPinQuota -= bytesPinned;
        }
    }

    // flags declaring we want extra info from the package manager for webview providers
    private final static int PACKAGE_FLAGS = PackageManager.GET_META_DATA
            | PackageManager.GET_SIGNATURES | PackageManager.GET_SHARED_LIBRARY_FILES
+3 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.webkit;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.webkit.UserPackage;
@@ -61,4 +62,6 @@ public interface SystemInterface {
    /** Start the zygote if it's not already running. */
    public void ensureZygoteStarted();
    public boolean isMultiProcessDefaultEnabled();

    public void pinWebviewIfRequired(ApplicationInfo appInfo);
}
+1 −40
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ package com.android.server.webkit;

import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
@@ -30,12 +29,8 @@ import android.webkit.WebViewFactory;
import android.webkit.WebViewProviderInfo;
import android.webkit.WebViewProviderResponse;

import com.android.server.LocalServices;
import com.android.server.PinnerService;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
@@ -93,8 +88,6 @@ class WebViewUpdateServiceImpl implements WebViewUpdateServiceInterface {
    private static final int MULTIPROCESS_SETTING_ON_VALUE = Integer.MAX_VALUE;
    private static final int MULTIPROCESS_SETTING_OFF_VALUE = Integer.MIN_VALUE;

    private static final String PIN_GROUP = "webview";

    private final SystemInterface mSystemInterface;
    private final Context mContext;

@@ -346,38 +339,6 @@ class WebViewUpdateServiceImpl implements WebViewUpdateServiceInterface {
        return newPackage;
    }

    private void pinWebviewIfRequired(ApplicationInfo appInfo) {
        PinnerService pinnerService = LocalServices.getService(PinnerService.class);
        if (pinnerService == null) {
            // This happens in unit tests which do not have services.
            return;
        }
        int webviewPinQuota = pinnerService.getWebviewPinQuota();
        if (webviewPinQuota <= 0) {
            return;
        }

        pinnerService.unpinGroup(PIN_GROUP);

        ArrayList<String> apksToPin = new ArrayList<>();
        boolean pinSharedFirst = appInfo.metaData.getBoolean("PIN_SHARED_LIBS_FIRST", true);
        for (String sharedLib : appInfo.sharedLibraryFiles) {
            apksToPin.add(sharedLib);
        }
        apksToPin.add(appInfo.sourceDir);
        if (!pinSharedFirst) {
            // We want to prioritize pinning of the native library that is most likely used by apps
            // which in some build flavors live in the main apk and as a shared library for others.
            Collections.reverse(apksToPin);
        }
        for (String apk : apksToPin) {
            if (webviewPinQuota <= 0) {
                break;
            }
            int bytesPinned = pinnerService.pinFile(apk, webviewPinQuota, appInfo, PIN_GROUP);
            webviewPinQuota -= bytesPinned;
        }
    }
    /**
     * This is called when we change WebView provider, either when the current provider is
     * updated or a new provider is chosen / takes precedence.
@@ -386,7 +347,7 @@ class WebViewUpdateServiceImpl implements WebViewUpdateServiceInterface {
        synchronized (mLock) {
            mAnyWebViewInstalled = true;
            if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
                pinWebviewIfRequired(newPackage.applicationInfo);
                mSystemInterface.pinWebviewIfRequired(newPackage.applicationInfo);
                mCurrentWebViewPackage = newPackage;

                // The relro creations might 'finish' (not start at all) before
+1 −41
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ package com.android.server.webkit;

import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.Signature;
@@ -32,12 +31,8 @@ import android.webkit.WebViewFactory;
import android.webkit.WebViewProviderInfo;
import android.webkit.WebViewProviderResponse;

import com.android.server.LocalServices;
import com.android.server.PinnerService;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
@@ -88,8 +83,6 @@ class WebViewUpdateServiceImpl2 implements WebViewUpdateServiceInterface {
    private static final int VALIDITY_INCORRECT_SIGNATURE = 3;
    private static final int VALIDITY_NO_LIBRARY_FLAG = 4;

    private static final String PIN_GROUP = "webview";

    private final SystemInterface mSystemInterface;
    private final Context mContext;

@@ -356,39 +349,6 @@ class WebViewUpdateServiceImpl2 implements WebViewUpdateServiceInterface {
        return newPackage;
    }

    private void pinWebviewIfRequired(ApplicationInfo appInfo) {
        PinnerService pinnerService = LocalServices.getService(PinnerService.class);
        if (pinnerService == null) {
            // This happens in unit tests which do not have services.
            return;
        }
        int webviewPinQuota = pinnerService.getWebviewPinQuota();
        if (webviewPinQuota <= 0) {
            return;
        }

        pinnerService.unpinGroup(PIN_GROUP);

        ArrayList<String> apksToPin = new ArrayList<>();
        boolean pinSharedFirst = appInfo.metaData.getBoolean("PIN_SHARED_LIBS_FIRST", true);
        for (String sharedLib : appInfo.sharedLibraryFiles) {
            apksToPin.add(sharedLib);
        }
        apksToPin.add(appInfo.sourceDir);
        if (!pinSharedFirst) {
            // We want to prioritize pinning of the native library that is most likely used by apps
            // which in some build flavors live in the main apk and as a shared library for others.
            Collections.reverse(apksToPin);
        }
        for (String apk : apksToPin) {
            if (webviewPinQuota <= 0) {
                break;
            }
            int bytesPinned = pinnerService.pinFile(apk, webviewPinQuota, appInfo, PIN_GROUP);
            webviewPinQuota -= bytesPinned;
        }
    }

    /**
     * This is called when we change WebView provider, either when the current provider is
     * updated or a new provider is chosen / takes precedence.
@@ -397,7 +357,7 @@ class WebViewUpdateServiceImpl2 implements WebViewUpdateServiceInterface {
        synchronized (mLock) {
            mAnyWebViewInstalled = true;
            if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
                pinWebviewIfRequired(newPackage.applicationInfo);
                mSystemInterface.pinWebviewIfRequired(newPackage.applicationInfo);
                mCurrentWebViewPackage = newPackage;

                // The relro creations might 'finish' (not start at all) before
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.webkit;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
@@ -179,4 +180,7 @@ public class TestSystemImpl implements SystemInterface {
    public boolean isMultiProcessDefaultEnabled() {
        return mMultiProcessDefault;
    }

    @Override
    public void pinWebviewIfRequired(ApplicationInfo appInfo) {}
}