diff options
40 files changed, 725 insertions, 127 deletions
diff --git a/api/current.txt b/api/current.txt index 8d2790568f9b..e6363dbd8992 100644 --- a/api/current.txt +++ b/api/current.txt @@ -12695,7 +12695,7 @@ package android.graphics { enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLE_STRIP; } - public class Color { + public final class Color { ctor public Color(); method public static int HSVToColor(float[]); method public static int HSVToColor(int, float[]); @@ -12720,6 +12720,7 @@ package android.graphics { method public float getComponent(int); method public int getComponentCount(); method public float[] getComponents(); + method public float[] getComponents(float[]); method public android.graphics.ColorSpace.Model getModel(); method public float green(); method public static float green(long); diff --git a/api/system-current.txt b/api/system-current.txt index badd31e3583a..03b522d457dc 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -11172,6 +11172,7 @@ package android.content.pm { method public abstract byte[] getInstantAppCookie(); method public abstract int getInstantAppCookieMaxSize(); method public abstract android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String); + method public abstract android.content.ComponentName getInstantAppResolverSettingsComponent(); method public abstract java.util.List<android.content.pm.InstantAppInfo> getInstantApps(); method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(java.lang.String); @@ -11421,6 +11422,7 @@ package android.content.pm { field public static final int MATCH_DIRECT_BOOT_UNAWARE = 262144; // 0x40000 field public static final int MATCH_DISABLED_COMPONENTS = 512; // 0x200 field public static final int MATCH_DISABLED_UNTIL_USED_COMPONENTS = 32768; // 0x8000 + field public static final int MATCH_FACTORY_ONLY = 2097152; // 0x200000 field public static final int MATCH_INSTANT = 8388608; // 0x800000 field public static final int MATCH_SYSTEM_ONLY = 1048576; // 0x100000 field public static final int MATCH_UNINSTALLED_PACKAGES = 8192; // 0x2000 @@ -13421,7 +13423,7 @@ package android.graphics { enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLE_STRIP; } - public class Color { + public final class Color { ctor public Color(); method public static int HSVToColor(float[]); method public static int HSVToColor(int, float[]); @@ -13446,6 +13448,7 @@ package android.graphics { method public float getComponent(int); method public int getComponentCount(); method public float[] getComponents(); + method public float[] getComponents(float[]); method public android.graphics.ColorSpace.Model getModel(); method public float green(); method public static float green(long); @@ -44214,6 +44217,7 @@ package android.test.mock { method public byte[] getInstantAppCookie(); method public int getInstantAppCookieMaxSize(); method public android.graphics.drawable.Drawable getInstantAppIcon(java.lang.String); + method public android.content.ComponentName getInstantAppResolverSettingsComponent(); method public java.util.List<android.content.pm.InstantAppInfo> getInstantApps(); method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException; method public java.util.List<android.content.pm.IntentFilterVerificationInfo> getIntentFilterVerifications(java.lang.String); diff --git a/api/test-current.txt b/api/test-current.txt index 3a23cd98730a..b09136e54304 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -12745,7 +12745,7 @@ package android.graphics { enum_constant public static final android.graphics.Canvas.VertexMode TRIANGLE_STRIP; } - public class Color { + public final class Color { ctor public Color(); method public static int HSVToColor(float[]); method public static int HSVToColor(int, float[]); @@ -12770,6 +12770,7 @@ package android.graphics { method public float getComponent(int); method public int getComponentCount(); method public float[] getComponents(); + method public float[] getComponents(float[]); method public android.graphics.ColorSpace.Model getModel(); method public float green(); method public static float green(long); diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java index ef2db4a0d795..2062930929a2 100644 --- a/core/java/android/app/ApplicationLoaders.java +++ b/core/java/android/app/ApplicationLoaders.java @@ -18,6 +18,7 @@ package android.app; import android.os.Build; import android.os.Trace; +import android.text.TextUtils; import android.util.ArrayMap; import com.android.internal.os.PathClassLoaderFactory; import dalvik.system.PathClassLoader; @@ -29,8 +30,16 @@ public class ApplicationLoaders { } ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled, - String librarySearchPath, String libraryPermittedPath, - ClassLoader parent) { + String librarySearchPath, String libraryPermittedPath, + ClassLoader parent) { + // For normal usage the cache key used is the same as the zip path. + return getClassLoader(zip, targetSdkVersion, isBundled, librarySearchPath, + libraryPermittedPath, parent, zip); + } + + private ClassLoader getClassLoader(String zip, int targetSdkVersion, boolean isBundled, + String librarySearchPath, String libraryPermittedPath, + ClassLoader parent, String cacheKey) { /* * This is the parent we use if they pass "null" in. In theory * this should be the "system" class loader; in practice we @@ -50,7 +59,7 @@ public class ApplicationLoaders { * new ClassLoader for the zip archive. */ if (parent == baseParent) { - ClassLoader loader = mLoaders.get(zip); + ClassLoader loader = mLoaders.get(cacheKey); if (loader != null) { return loader; } @@ -71,7 +80,7 @@ public class ApplicationLoaders { setupVulkanLayerPath(pathClassloader, librarySearchPath); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); - mLoaders.put(zip, pathClassloader); + mLoaders.put(cacheKey, pathClassloader); return pathClassloader; } @@ -87,12 +96,16 @@ public class ApplicationLoaders { * by this class. This is used in the WebView zygote, where its presence in the cache speeds up * startup and enables memory sharing. */ - public ClassLoader createAndCacheWebViewClassLoader(String packagePath, String libsPath) { - // The correct paths are calculated by WebViewZygote in the system server and passed to - // us here. We hardcode the other parameters: WebView always targets the current SDK, - // does not need to use non-public system libraries, and uses the base classloader as its - // parent to permit usage of the cache. - return getClassLoader(packagePath, Build.VERSION.SDK_INT, false, libsPath, null, null); + public ClassLoader createAndCacheWebViewClassLoader(String packagePath, String libsPath, + String cacheKey) { + // The correct paths are calculated by WebViewZygote in the system server and passed to + // us here. We hardcode the other parameters: WebView always targets the current SDK, + // does not need to use non-public system libraries, and uses the base classloader as its + // parent to permit usage of the cache. + // The cache key is passed separately to enable the stub WebView to be cached under the + // stub's APK path, when the actual package path is the donor APK. + return getClassLoader(packagePath, Build.VERSION.SDK_INT, false, libsPath, null, null, + cacheKey); } private static native void setupVulkanLayerPath(ClassLoader classLoader, String librarySearchPath); diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 286f8570f55c..461f9cc35125 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -2630,4 +2630,13 @@ public class ApplicationPackageManager extends PackageManager { throw e.rethrowAsRuntimeException(); } } + + @Override + public ComponentName getInstantAppResolverSettingsComponent() { + try { + return mPM.getInstantAppResolverSettingsComponent(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } } diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index fb86791a509c..7890a9607932 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -1532,6 +1532,19 @@ public class Intent implements Parcelable, Cloneable { = "android.intent.action.RESOLVE_EPHEMERAL_PACKAGE"; /** + * Activity Action: Launch ephemeral settings. + * + * <p class="note"> + * This is a protected intent that can only be sent by the system. + * </p> + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_EPHEMERAL_RESOLVER_SETTINGS + = "android.intent.action.EPHEMERAL_RESOLVER_SETTINGS"; + + /** * Used as a string extra field with {@link #ACTION_INSTALL_PACKAGE} to install a * package. Specifies the installer package name; this package will receive the * {@link #ACTION_APP_ERROR} intent. diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 59b022ded9bf..147df763fce2 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -630,4 +630,6 @@ interface IPackageManager { boolean canRequestPackageInstalls(String packageName, int userId); void deletePreloadsFileCache(); + + ComponentName getInstantAppResolverSettingsComponent(); } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 71db5d311bd6..136c13b6f37d 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -153,6 +153,7 @@ public abstract class PackageManager { MATCH_UNINSTALLED_PACKAGES, MATCH_SYSTEM_ONLY, MATCH_DEBUG_TRIAGED_MISSING, + MATCH_DISABLED_COMPONENTS, MATCH_DISABLED_UNTIL_USED_COMPONENTS, MATCH_INSTANT, GET_DISABLED_UNTIL_USED_COMPONENTS, @@ -431,6 +432,7 @@ public abstract class PackageManager { * This will not return information on any unbundled update to system components. * @hide */ + @SystemApi public static final int MATCH_FACTORY_ONLY = 0x00200000; /** @@ -3730,6 +3732,7 @@ public abstract class PackageManager { * * @param flags Additional option flags. Use any combination of * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, + * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS} * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES} * to modify the data returned. * @@ -3743,6 +3746,7 @@ public abstract class PackageManager { * * @see #GET_META_DATA * @see #GET_SHARED_LIBRARY_FILES + * @see #MATCH_DISABLED_COMPONENTS * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS * @see #MATCH_SYSTEM_ONLY * @see #MATCH_UNINSTALLED_PACKAGES @@ -3757,6 +3761,7 @@ public abstract class PackageManager { * * @param flags Additional option flags. Use any combination of * {@link #GET_META_DATA}, {@link #GET_SHARED_LIBRARY_FILES}, + * {@link #MATCH_DISABLED_COMPONENTS}, {@link #MATCH_DISABLED_UNTIL_USED_COMPONENTS} * {@link #MATCH_SYSTEM_ONLY}, {@link #MATCH_UNINSTALLED_PACKAGES} * to modify the data returned. * @param userId The user for whom the installed applications are to be listed @@ -3772,6 +3777,7 @@ public abstract class PackageManager { * * @see #GET_META_DATA * @see #GET_SHARED_LIBRARY_FILES + * @see #MATCH_DISABLED_COMPONENTS * @see #MATCH_DISABLED_UNTIL_USED_COMPONENTS * @see #MATCH_SYSTEM_ONLY * @see #MATCH_UNINSTALLED_PACKAGES @@ -6233,4 +6239,14 @@ public abstract class PackageManager { * @see {@link android.provider.Settings#ACTION_MANAGE_EXTERNAL_SOURCES} */ public abstract boolean canRequestPackageInstalls(); + + /** + * Return the {@link ComponentName} of the activity providing Settings for the Instant App + * resolver. + * + * @see {@link android.content.intent#ACTION_EPHEMERAL_RESOLVER_SETTINGS} + * @hide + */ + @SystemApi + public abstract ComponentName getInstantAppResolverSettingsComponent(); } diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java index 0bc8d59d71a8..370af177288f 100644 --- a/core/java/android/content/pm/PackageManagerInternal.java +++ b/core/java/android/content/pm/PackageManagerInternal.java @@ -172,6 +172,7 @@ public abstract class PackageManagerInternal { * @param packageName The package name. * @param userId The user for which to check. * @return Whether was launched. + * @throws IllegalArgumentException if the package is not found */ public abstract boolean wasPackageEverLaunched(String packageName, int userId); diff --git a/core/java/android/os/ZygoteProcess.java b/core/java/android/os/ZygoteProcess.java index b3366d883fc6..8208438dc62a 100644 --- a/core/java/android/os/ZygoteProcess.java +++ b/core/java/android/os/ZygoteProcess.java @@ -487,11 +487,11 @@ public class ZygoteProcess { * Instructs the zygote to pre-load the classes and native libraries at the given paths * for the specified abi. Not all zygotes support this function. */ - public void preloadPackageForAbi(String packagePath, String libsPath, String abi) - throws ZygoteStartFailedEx, IOException { + public void preloadPackageForAbi(String packagePath, String libsPath, String cacheKey, + String abi) throws ZygoteStartFailedEx, IOException { synchronized(mLock) { ZygoteState state = openZygoteSocketIfNeeded(abi); - state.writer.write("3"); + state.writer.write("4"); state.writer.newLine(); state.writer.write("--preload-package"); @@ -503,6 +503,9 @@ public class ZygoteProcess { state.writer.write(libsPath); state.writer.newLine(); + state.writer.write(cacheKey); + state.writer.newLine(); + state.writer.flush(); } } diff --git a/core/java/android/service/quicksettings/TileService.java b/core/java/android/service/quicksettings/TileService.java index 21168475adf7..8e0103078a42 100644 --- a/core/java/android/service/quicksettings/TileService.java +++ b/core/java/android/service/quicksettings/TileService.java @@ -433,6 +433,7 @@ public class TileService extends Service { public static final void requestListeningState(Context context, ComponentName component) { Intent intent = new Intent(ACTION_REQUEST_LISTENING); intent.putExtra(EXTRA_COMPONENT, component); + intent.setPackage("com.android.systemui"); context.sendBroadcast(intent, Manifest.permission.BIND_QUICK_SETTINGS_TILE); } } diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java index 44309a7b68c2..28c2d016f6db 100644 --- a/core/java/android/view/inputmethod/InputMethodSubtype.java +++ b/core/java/android/view/inputmethod/InputMethodSubtype.java @@ -520,27 +520,27 @@ public final class InputMethodSubtype implements Parcelable { } private HashMap<String, String> getExtraValueHashMap() { - if (mExtraValueHashMapCache == null) { - synchronized(this) { - if (mExtraValueHashMapCache == null) { - mExtraValueHashMapCache = new HashMap<String, String>(); - final String[] pairs = mSubtypeExtraValue.split(EXTRA_VALUE_PAIR_SEPARATOR); - final int N = pairs.length; - for (int i = 0; i < N; ++i) { - final String[] pair = pairs[i].split(EXTRA_VALUE_KEY_VALUE_SEPARATOR); - if (pair.length == 1) { - mExtraValueHashMapCache.put(pair[0], null); - } else if (pair.length > 1) { - if (pair.length > 2) { - Slog.w(TAG, "ExtraValue has two or more '='s"); - } - mExtraValueHashMapCache.put(pair[0], pair[1]); - } + synchronized (this) { + HashMap<String, String> extraValueMap = mExtraValueHashMapCache; + if (extraValueMap != null) { + return extraValueMap; + } + extraValueMap = new HashMap<>(); + final String[] pairs = mSubtypeExtraValue.split(EXTRA_VALUE_PAIR_SEPARATOR); + for (int i = 0; i < pairs.length; ++i) { + final String[] pair = pairs[i].split(EXTRA_VALUE_KEY_VALUE_SEPARATOR); + if (pair.length == 1) { + extraValueMap.put(pair[0], null); + } else if (pair.length > 1) { + if (pair.length > 2) { + Slog.w(TAG, "ExtraValue has two or more '='s"); } + extraValueMap.put(pair[0], pair[1]); } } + mExtraValueHashMapCache = extraValueMap; + return extraValueMap; } - return mExtraValueHashMapCache; } /** diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 81c2f5d5ef4c..71db6b141ca9 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -280,6 +280,44 @@ public final class WebViewFactory { } } + /** + * If the ApplicationInfo provided is for a stub WebView, fix up the object to include the + * required values from the donor package. If the ApplicationInfo is for a full WebView, + * leave it alone. Throws MissingWebViewPackageException if the donor is missing. + */ + private static void fixupStubApplicationInfo(ApplicationInfo ai, PackageManager pm) { + String donorPackageName = null; + if (ai.metaData != null) { + donorPackageName = ai.metaData.getString("com.android.webview.WebViewDonorPackage"); + } + if (donorPackageName != null) { + PackageInfo donorPackage; + try { + donorPackage = pm.getPackageInfo( + donorPackageName, + PackageManager.GET_SHARED_LIBRARY_FILES + | PackageManager.MATCH_DEBUG_TRIAGED_MISSING + | PackageManager.MATCH_UNINSTALLED_PACKAGES + | PackageManager.MATCH_FACTORY_ONLY); + } catch (PackageManager.NameNotFoundException e) { + throw new MissingWebViewPackageException("Failed to find donor package: " + + donorPackageName); + } + ApplicationInfo donorInfo = donorPackage.applicationInfo; + + // Replace the stub's code locations with the donor's. + ai.sourceDir = donorInfo.sourceDir; + ai.splitSourceDirs = donorInfo.splitSourceDirs; + ai.nativeLibraryDir = donorInfo.nativeLibraryDir; + ai.secondaryNativeLibraryDir = donorInfo.secondaryNativeLibraryDir; + + // Copy the donor's primary and secondary ABIs, since the stub doesn't have native code + // and so they are unset. + ai.primaryCpuAbi = donorInfo.primaryCpuAbi; + ai.secondaryCpuAbi = donorInfo.secondaryCpuAbi; + } + } + private static Context getWebViewContextAndSetProvider() { Application initialApplication = AppGlobals.getInitialApplication(); try { @@ -307,9 +345,10 @@ public final class WebViewFactory { } // Fetch package info and verify it against the chosen package PackageInfo newPackageInfo = null; + PackageManager pm = initialApplication.getPackageManager(); Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "PackageManager.getPackageInfo()"); try { - newPackageInfo = initialApplication.getPackageManager().getPackageInfo( + newPackageInfo = pm.getPackageInfo( response.packageInfo.packageName, PackageManager.GET_SHARED_LIBRARY_FILES | PackageManager.MATCH_DEBUG_TRIAGED_MISSING @@ -328,12 +367,15 @@ public final class WebViewFactory { // failure verifyPackageInfo(response.packageInfo, newPackageInfo); + ApplicationInfo ai = newPackageInfo.applicationInfo; + fixupStubApplicationInfo(ai, pm); + Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "initialApplication.createApplicationContext"); try { // Construct an app context to load the Java code into the current app. Context webViewContext = initialApplication.createApplicationContext( - newPackageInfo.applicationInfo, + ai, Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); sPackageInfo = newPackageInfo; return webViewContext; @@ -449,7 +491,11 @@ public final class WebViewFactory { */ public static int onWebViewProviderChanged(PackageInfo packageInfo) { String[] nativeLibs = null; + String originalSourceDir = packageInfo.applicationInfo.sourceDir; try { + fixupStubApplicationInfo(packageInfo.applicationInfo, + AppGlobals.getInitialApplication().getPackageManager()); + nativeLibs = WebViewFactory.getWebViewNativeLibraryPaths(packageInfo); if (nativeLibs != null) { long newVmSize = 0L; @@ -498,7 +544,7 @@ public final class WebViewFactory { Log.e(LOGTAG, "error preparing webview native library", t); } - WebViewZygote.onWebViewProviderChanged(packageInfo); + WebViewZygote.onWebViewProviderChanged(packageInfo, originalSourceDir); return prepareWebViewInSystemServer(nativeLibs); } diff --git a/core/java/android/webkit/WebViewZygote.java b/core/java/android/webkit/WebViewZygote.java index f78d62250029..2123debfeb67 100644 --- a/core/java/android/webkit/WebViewZygote.java +++ b/core/java/android/webkit/WebViewZygote.java @@ -67,6 +67,13 @@ public class WebViewZygote { private static PackageInfo sPackage; /** + * Cache key for the selected WebView package's classloader. This is set from + * #onWebViewProviderChanged(). + */ + @GuardedBy("sLock") + private static String sPackageCacheKey; + + /** * Flag for whether multi-process WebView is enabled. If this is false, the zygote * will not be started. */ @@ -118,9 +125,10 @@ public class WebViewZygote { } } - public static void onWebViewProviderChanged(PackageInfo packageInfo) { + public static void onWebViewProviderChanged(PackageInfo packageInfo, String cacheKey) { synchronized (sLock) { sPackage = packageInfo; + sPackageCacheKey = cacheKey; // If multi-process is not enabled, then do not start the zygote service. if (!sMultiprocessEnabled) { @@ -210,7 +218,8 @@ public class WebViewZygote { TextUtils.join(File.pathSeparator, zipPaths); Log.d(LOGTAG, "Preloading package " + zip + " " + librarySearchPath); - sZygote.preloadPackageForAbi(zip, librarySearchPath, Build.SUPPORTED_ABIS[0]); + sZygote.preloadPackageForAbi(zip, librarySearchPath, sPackageCacheKey, + Build.SUPPORTED_ABIS[0]); } catch (Exception e) { Log.e(LOGTAG, "Error connecting to " + serviceName, e); sZygote = null; diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java index 78d18fdbca5f..ab4cce479005 100644 --- a/core/java/android/widget/ListPopupWindow.java +++ b/core/java/android/widget/ListPopupWindow.java @@ -523,9 +523,17 @@ public class ListPopupWindow implements ShowableListMenu { /** * Sets the height of the popup window in pixels. Can also be {@link #MATCH_PARENT}. * - * @param height Height of the popup window. + * @param height Height of the popup window must be a positive value, + * {@link #MATCH_PARENT}, or {@link #WRAP_CONTENT}. + * + * @throws IllegalArgumentException if height is set to negative value */ public void setHeight(int height) { + if (height < 0 && ViewGroup.LayoutParams.WRAP_CONTENT != height + && ViewGroup.LayoutParams.MATCH_PARENT != height) { + throw new IllegalArgumentException( + "Invalid height. Must be a positive value, MATCH_PARENT, or WRAP_CONTENT."); + } mDropDownHeight = height; } diff --git a/core/java/com/android/internal/os/WebViewZygoteInit.java b/core/java/com/android/internal/os/WebViewZygoteInit.java index f27c0d4df4ce..cc3f58cb0c3d 100644 --- a/core/java/com/android/internal/os/WebViewZygoteInit.java +++ b/core/java/com/android/internal/os/WebViewZygoteInit.java @@ -26,6 +26,7 @@ import android.util.Log; import android.webkit.WebViewFactory; import android.webkit.WebViewFactoryProvider; +import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -67,16 +68,20 @@ class WebViewZygoteInit { } @Override - protected boolean handlePreloadPackage(String packagePath, String libsPath) { + protected boolean handlePreloadPackage(String packagePath, String libsPath, + String cacheKey) { // Ask ApplicationLoaders to create and cache a classloader for the WebView APK so that // our children will reuse the same classloader instead of creating their own. // This enables us to preload Java and native code in the webview zygote process and // have the preloaded versions actually be used post-fork. ClassLoader loader = ApplicationLoaders.getDefault().createAndCacheWebViewClassLoader( - packagePath, libsPath); + packagePath, libsPath, cacheKey); // Add the APK to the Zygote's list of allowed files for children. - Zygote.nativeAllowFileAcrossFork(packagePath); + String[] packageList = TextUtils.split(packagePath, File.pathSeparator); + for (String packageEntry : packageList) { + Zygote.nativeAllowFileAcrossFork(packageEntry); + } // Once we have the classloader, look up the WebViewFactoryProvider implementation and // call preloadInZygote() on it to give it the opportunity to preload the native library diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java index e2485e90e537..a9bec4123fd2 100644 --- a/core/java/com/android/internal/os/ZygoteConnection.java +++ b/core/java/com/android/internal/os/ZygoteConnection.java @@ -177,7 +177,7 @@ class ZygoteConnection { if (parsedArgs.preloadPackage != null) { return handlePreloadPackage(parsedArgs.preloadPackage, - parsedArgs.preloadPackageLibs); + parsedArgs.preloadPackageLibs, parsedArgs.preloadPackageCacheKey); } if (parsedArgs.permittedCapabilities != 0 || parsedArgs.effectiveCapabilities != 0) { @@ -314,7 +314,7 @@ class ZygoteConnection { return ZygoteInit.isPreloadComplete(); } - protected boolean handlePreloadPackage(String packagePath, String libsPath) { + protected boolean handlePreloadPackage(String packagePath, String libsPath, String cacheKey) { throw new RuntimeException("Zyogte does not support package preloading"); } @@ -428,6 +428,7 @@ class ZygoteConnection { */ String preloadPackage; String preloadPackageLibs; + String preloadPackageCacheKey; /** * Whether this is a request to start preloading the default resources and classes. @@ -599,6 +600,7 @@ class ZygoteConnection { } else if (arg.equals("--preload-package")) { preloadPackage = args[++curArg]; preloadPackageLibs = args[++curArg]; + preloadPackageCacheKey = args[++curArg]; } else if (arg.equals("--preload-default")) { preloadDefault = true; } else { diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 7704519415b2..db234e753bbc 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2801,4 +2801,9 @@ <!-- Colon separated list of package names that should be granted Notification Listener access --> <string name="config_defaultListenerAccessPackages" translatable="false"></string> + + <!-- Maximum size, specified in pixels, to restrain the display space width to. Height and + density will be scaled accordingly to maintain aspect ratio. A value of 0 indicates no + constraint will be enforced. --> + <integer name="config_maxUiWidth">0</integer> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 868e256496bb..4afa8dcdfb4a 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -189,22 +189,23 @@ <!-- Displayed to tell the user that they cannot change the caller ID setting. --> <string name="CLIRPermanent">You can\'t change the caller ID setting.</string> - <!-- Displayed to tell the user that data service is blocked by access control. --> - <string name="RestrictedOnData">Data service is blocked.</string> - <!-- Displayed to tell the user that emergency service is blocked by access control. --> - <string name="RestrictedOnEmergency">Emergency service is blocked.</string> - <!-- Displayed to tell the user that normal service is blocked by access control. --> - <string name="RestrictedOnNormal">Voice service is blocked.</string> - <!-- Displayed to tell the user that all emergency and normal voice services are blocked by access control. --> - <string name="RestrictedOnAllVoice">All voice services are blocked.</string> - <!-- Displayed to tell the user that sms service is blocked by access control. --> - <string name="RestrictedOnSms">SMS service is blocked.</string> - <!-- Displayed to tell the user that voice/data service is blocked by access control. --> - <string name="RestrictedOnVoiceData">Voice/data services are blocked.</string> - <!-- Displayed to tell the user that voice and sms service are blocked by access control. --> - <string name="RestrictedOnVoiceSms">Voice/SMS services are blocked.</string> - <!-- Displayed to tell the user that all service is blocked by access control. --> - <string name="RestrictedOnAll">All voice/data/SMS services are blocked.</string> + <!-- Notification title to tell the user that data service is blocked by access control. --> + <string name="RestrictedOnDataTitle">No data service</string> + <!-- Notification title to tell the user that emergency service is blocked by access control. --> + <string name="RestrictedOnEmergencyTitle">No emergency service</string> + <!-- Notification title to tell the user that normal service is blocked by access control. --> + <string name="RestrictedOnNormalTitle">No voice service</string> + <!-- Notification title to tell the user that all emergency and normal voice services are blocked by access control. --> + <string name="RestrictedOnAllVoiceTitle">No voice/emergency service</string> + + <!-- Notification content to tell the user that data service is blocked by access control. --> + <string name="RestrictedOnDataContent">Your carrier has temporarily suspended data service at this location</string> + <!-- Notification content to tell the user that emergency service is blocked by access control. --> + <string name="RestrictedOnEmergencyContent">Your carrier has temporarily suspended emergency calls at this location</string> + <!-- Notification content to tell the user that normal service is blocked by access control. --> + <string name="RestrictedOnNormalContent">Your carrier has temporarily suspended voice calls at this location</string> + <!-- Notification content to tell the user that all emergency and normal voice services are blocked by access control. --> + <string name="RestrictedOnAllVoiceContent">Your carrier has temporarily suspended voice and emergency calls at this location</string> <!-- Displayed to tell the user that they should switch their network preference. --> <string name="NetworkPreferenceSwitchTitle">Can\u2019t reach network</string> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index b23c96c9b05f..92436f482f7f 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -507,12 +507,16 @@ <java-symbol type="string" name="Noon" /> <java-symbol type="string" name="PinMmi" /> <java-symbol type="string" name="PwdMmi" /> - <java-symbol type="string" name="RestrictedOnAllVoice" /> - <java-symbol type="string" name="RestrictedOnData" /> - <java-symbol type="string" name="RestrictedOnEmergency" /> - <java-symbol type="string" name="RestrictedOnNormal" /> <java-symbol type="string" name="NetworkPreferenceSwitchSummary" /> <java-symbol type="string" name="NetworkPreferenceSwitchTitle" /> + <java-symbol type="string" name="RestrictedOnAllVoiceTitle" /> + <java-symbol type="string" name="RestrictedOnDataTitle" /> + <java-symbol type="string" name="RestrictedOnEmergencyTitle" /> + <java-symbol type="string" name="RestrictedOnNormalTitle" /> + <java-symbol type="string" name="RestrictedOnAllVoiceContent" /> + <java-symbol type="string" name="RestrictedOnDataContent" /> + <java-symbol type="string" name="RestrictedOnEmergencyContent" /> + <java-symbol type="string" name="RestrictedOnNormalContent" /> <java-symbol type="string" name="SetupCallDefault" /> <java-symbol type="string" name="accept" /> <java-symbol type="string" name="activity_chooser_view_see_all" /> @@ -2919,6 +2923,9 @@ <!-- Colon separated list of package names that should be granted Notification Listener access --> <java-symbol type="string" name="config_defaultListenerAccessPackages" /> + <!-- maximum width of the display --> + <java-symbol type="integer" name="config_maxUiWidth" /> + <!-- system notification channels --> <java-symbol type="string" name="notification_channel_virtual_keyboard" /> <java-symbol type="string" name="notification_channel_physical_keyboard" /> diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java index 33d19d4063f5..d69f67d138a1 100644 --- a/graphics/java/android/graphics/Color.java +++ b/graphics/java/android/graphics/Color.java @@ -22,6 +22,7 @@ import android.annotation.ColorLong; import android.annotation.HalfFloat; import android.annotation.IntRange; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.Size; import android.util.Half; @@ -288,7 +289,7 @@ import java.util.function.DoubleUnaryOperator; * and <code>(1.0, 0.0, 0.0, 0.5)</code>.</p> */ @AnyThread -public class Color { +public final class Color { @ColorInt public static final int BLACK = 0xFF000000; @ColorInt public static final int DKGRAY = 0xFF444444; @ColorInt public static final int GRAY = 0xFF888888; @@ -415,7 +416,7 @@ public class Color { * to this color space's color model, plus one extra component for * alpha. * - * @return An integer between 4 and 5 + * @return The integer 4 or 5 */ @IntRange(from = 4, to = 5) public int getComponentCount() { @@ -560,7 +561,37 @@ public class Color { @NonNull @Size(min = 4, max = 5) public float[] getComponents() { - return Arrays.copyOf(mComponents, mColorSpace.getComponentCount() + 1); + return Arrays.copyOf(mComponents, mComponents.length); + } + + /** + * Copies this color's components in the supplied array. The last element of the + * array is always the alpha component. + * + * @param components An array of floats whose size must be at least + * {@link #getComponentCount()}, can be null + * @return The array passed as a parameter if not null, or a new array of length + * {@link #getComponentCount()} + * + * @see #getComponent(int) + * + * @throws IllegalArgumentException If the specified array's length is less than + * {@link #getComponentCount()} + */ + @NonNull + @Size(min = 4) + public float[] getComponents(@Nullable @Size(min = 4) float[] components) { + if (components == null) { + return Arrays.copyOf(mComponents, mComponents.length); + } + + if (components.length < mComponents.length) { + throw new IllegalArgumentException("The specified array's length must be at " + + "least " + mComponents.length); + } + + System.arraycopy(mComponents, 0, components, 0, mComponents.length); + return components; } /** @@ -570,7 +601,7 @@ public class Color { * * <p>If the requested component index is {@link #getComponentCount()}, * this method returns the alpha component, always in the range - * \([0..1\).</p> + * \([0..1]\).</p> * * @see #getComponents() * diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index 1f49c1ac19f8..406f107f9872 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -21,6 +21,7 @@ import android.app.Fragment; import android.content.res.Configuration; import android.graphics.Rect; import android.os.Bundle; +import android.support.annotation.VisibleForTesting; import android.util.Log; import android.view.LayoutInflater; import android.view.View; @@ -39,6 +40,8 @@ import com.android.systemui.statusbar.stack.StackStateAnimator; public class QSFragment extends Fragment implements QS { private static final String TAG = "QS"; private static final boolean DEBUG = false; + private static final String EXTRA_EXPANDED = "expanded"; + private static final String EXTRA_LISTENING = "listening"; private final Rect mQsBounds = new Rect(); private boolean mQsExpanded; @@ -85,6 +88,35 @@ public class QSFragment extends Fragment implements QS { mQSCustomizer = view.findViewById(R.id.qs_customize); mQSCustomizer.setQs(this); + if (savedInstanceState != null) { + setExpanded(savedInstanceState.getBoolean(EXTRA_EXPANDED)); + setListening(savedInstanceState.getBoolean(EXTRA_LISTENING)); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (mListening) { + setListening(false); + } + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putBoolean(EXTRA_EXPANDED, mQsExpanded); + outState.putBoolean(EXTRA_LISTENING, mListening); + } + + @VisibleForTesting + boolean isListening() { + return mListening; + } + + @VisibleForTesting + boolean isExpanded() { + return mQsExpanded; } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java index a751ef465147..6e2add493779 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java @@ -84,12 +84,14 @@ public class QSIconViewImpl extends QSIconView { protected void updateIcon(ImageView iv, State state) { if (!Objects.equals(state.icon, iv.getTag(R.id.qs_icon_tag))) { + boolean shouldAnimate = iv.isShown() && mAnimationEnabled + && iv.getDrawable() != null; Drawable d = state.icon != null - ? iv.isShown() && mAnimationEnabled ? state.icon.getDrawable(mContext) + ? shouldAnimate ? state.icon.getDrawable(mContext) : state.icon.getInvisibleDrawable(mContext) : null; int padding = state.icon != null ? state.icon.getPadding() : 0; if (d != null) { - d.setAutoMirrored(true); + d.setAutoMirrored(false); } iv.setImageDrawable(d); iv.setTag(R.id.qs_icon_tag, state.icon); @@ -114,7 +116,7 @@ public class QSIconViewImpl extends QSIconView { if (state.state != mState) { int color = getColor(state.state); mState = state.state; - if (iv.isShown()) { + if (iv.isShown() && mTint != 0) { animateGrayScale(mTint, color, iv); mTint = color; } else { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java index d77ed3d9cd6e..673ffc5d0fbf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java @@ -15,8 +15,11 @@ package com.android.systemui.qs; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; +import android.app.FragmentController; +import android.app.FragmentManagerNonConfig; import android.os.Looper; import com.android.internal.logging.MetricsLogger; @@ -24,6 +27,7 @@ import com.android.keyguard.CarrierText; import com.android.systemui.Dependency; import com.android.systemui.R; +import android.os.Parcelable; import android.testing.AndroidTestingRunner; import com.android.systemui.SysuiBaseFragmentTest; @@ -90,4 +94,23 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { host.destroy(); processAllMessages(); } + + @Test + public void testSaveState() { + QSFragment qs = (QSFragment) mFragment; + + mFragments.dispatchResume(); + processAllMessages(); + + qs.setListening(true); + qs.setExpanded(true); + processAllMessages(); + recreateFragment(); + processAllMessages(); + + // Get the reference to the new fragment. + qs = (QSFragment) mFragment; + assertTrue(qs.isListening()); + assertTrue(qs.isExpanded()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java new file mode 100644 index 000000000000..59483f2df5bb --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSIconViewImplTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package com.android.systemui.qs.tileimpl; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import android.service.quicksettings.Tile; +import android.testing.AndroidTestingRunner; +import android.testing.UiThreadTest; +import android.widget.ImageView; + +import com.android.systemui.SysuiTestCase; +import com.android.systemui.plugins.qs.QSTile.Icon; +import com.android.systemui.plugins.qs.QSTile.State; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; + +@RunWith(AndroidTestingRunner.class) +@UiThreadTest +public class QSIconViewImplTest extends SysuiTestCase { + + private QSIconViewImpl mIconView; + + @Before + public void setup() { + mIconView = new QSIconViewImpl(mContext); + } + + @Test + public void testNoFirstAnimation() { + ImageView iv = mock(ImageView.class); + State s = new State(); + when(iv.isShown()).thenReturn(true); + + // No current icon, only the static drawable should be used. + s.icon = mock(Icon.class); + when(iv.getDrawable()).thenReturn(null); + mIconView.updateIcon(iv, s); + verify(s.icon, never()).getDrawable(any()); + verify(s.icon).getInvisibleDrawable(any()); + + // Has icon, should use the standard (animated) form. + s.icon = mock(Icon.class); + when(iv.getDrawable()).thenReturn(mock(Drawable.class)); + mIconView.updateIcon(iv, s); + verify(s.icon).getDrawable(any()); + verify(s.icon, never()).getInvisibleDrawable(any()); + } + + @Test + public void testNoFirstFade() { + ImageView iv = mock(ImageView.class); + State s = new State(); + s.state = Tile.STATE_ACTIVE; + int desiredColor = mIconView.getColor(s.state); + when(iv.isShown()).thenReturn(true); + + mIconView.setIcon(iv, s); + verify(iv).setImageTintList(argThat(stateList -> stateList.getColors()[0] == desiredColor)); + } +} diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index bbad493a913f..1a27a39bd1bf 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -907,7 +907,12 @@ public class SyncManager { Bundle finalExtras = new Bundle(extras); String packageName = syncAdapterInfo.componentName.getPackageName(); // If the app did not run and has no account access, done - if (!mPackageManagerInternal.wasPackageEverLaunched(packageName, userId)) { + try { + if (!mPackageManagerInternal.wasPackageEverLaunched(packageName, userId)) { + continue; + } + } catch (IllegalArgumentException e) { + // Package not found, race with an uninstall continue; } mAccountManagerInternal.requestAccountAccess(account.account, diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 7f75c83f8d51..53a8092fa558 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -772,7 +772,12 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { private final class SessionStub extends ISession.Stub { @Override public void destroy() { - mService.destroySession(MediaSessionRecord.this); + final long token = Binder.clearCallingIdentity(); + try { + mService.destroySession(MediaSessionRecord.this); + } finally { + Binder.restoreCallingIdentity(token); + } } @Override diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 09df156afd2c..621e37b58d6d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -842,6 +842,8 @@ public class PackageManagerService extends IPackageManager.Stub { /** Component used to install ephemeral applications */ ComponentName mInstantAppInstallerComponent; + /** Component used to show resolver settings for Instant Apps */ + ComponentName mInstantAppResolverSettingsComponent; ActivityInfo mInstantAppInstallerActivity; final ResolveInfo mInstantAppInstallerInfo = new ResolveInfo(); @@ -2890,6 +2892,7 @@ public class PackageManagerService extends IPackageManager.Stub { mInstantAppResolverConnection = null; } updateInstantAppInstallerLocked(); + mInstantAppResolverSettingsComponent = getEphemeralResolverSettingsLPr(); // Read and update the usage of dex files. // Do this at the end of PM init so that all the packages have their @@ -3196,6 +3199,37 @@ public class PackageManagerService extends IPackageManager.Stub { } } + private @Nullable ComponentName getEphemeralResolverSettingsLPr() { + final Intent intent = new Intent(Intent.ACTION_EPHEMERAL_RESOLVER_SETTINGS); + intent.addCategory(Intent.CATEGORY_DEFAULT); + final int resolveFlags = + MATCH_DIRECT_BOOT_AWARE + | MATCH_DIRECT_BOOT_UNAWARE + | (!Build.IS_DEBUGGABLE ? MATCH_SYSTEM_ONLY : 0); + final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null, + resolveFlags, UserHandle.USER_SYSTEM); + Iterator<ResolveInfo> iter = matches.iterator(); + while (iter.hasNext()) { + final ResolveInfo rInfo = iter.next(); + final PackageSetting ps = mSettings.mPackages.get(rInfo.activityInfo.packageName); + if (ps != null) { + final PermissionsState permissionsState = ps.getPermissionsState(); + if (permissionsState.hasPermission(Manifest.permission.ACCESS_INSTANT_APPS, 0)) { + continue; + } + } + iter.remove(); + } + if (matches.size() == 0) { + return null; + } else if (matches.size() == 1) { + return matches.get(0).getComponentInfo().getComponentName(); + } else { + throw new RuntimeException( + "There must be at most one ephemeral resolver settings; found " + matches); + } + } + private void primeDomainVerificationsLPw(int userId) { if (DEBUG_DOMAIN_VERIFICATION) { Slog.d(TAG, "Priming domain verifications in user " + userId); @@ -23323,4 +23357,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } return checkUidPermission(appOpPermission, uid) == PERMISSION_GRANTED; } + + @Override + public ComponentName getInstantAppResolverSettingsComponent() { + return mInstantAppResolverSettingsComponent; + } } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 8f391a718269..aa8557490f25 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -175,6 +175,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo private boolean mTmpRecoveringMemory; private boolean mUpdateImeTarget; private boolean mTmpInitial; + private int mMaxUiWidth; // Mapping from a token IBinder to a WindowToken object on this display. private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap(); @@ -1559,6 +1560,39 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo } } + /** Sets the maximum width the screen resolution can be */ + void setMaxUiWidth(int width) { + if (DEBUG_DISPLAY) { + Slog.v(TAG_WM, "Setting max ui width:" + width + " on display:" + getDisplayId()); + } + + mMaxUiWidth = width; + + // Update existing metrics. + updateBaseDisplayMetrics(mBaseDisplayWidth, mBaseDisplayHeight, mBaseDisplayDensity); + } + + /** Update base (override) display metrics. */ + void updateBaseDisplayMetrics(int baseWidth, int baseHeight, int baseDensity) { + mBaseDisplayWidth = baseWidth; + mBaseDisplayHeight = baseHeight; + mBaseDisplayDensity = baseDensity; + + if (mMaxUiWidth > 0 && mBaseDisplayWidth > mMaxUiWidth) { + mBaseDisplayHeight = (mMaxUiWidth * mBaseDisplayHeight) / mBaseDisplayWidth; + mBaseDisplayDensity = (mMaxUiWidth * mBaseDisplayDensity) / mBaseDisplayWidth; + mBaseDisplayWidth = mMaxUiWidth; + + if (DEBUG_DISPLAY) { + Slog.v(TAG_WM, "Applying config restraints:" + mBaseDisplayWidth + "x" + + mBaseDisplayHeight + " at density:" + mBaseDisplayDensity + + " on display:" + getDisplayId()); + } + } + + mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); + } + void getContentRect(Rect out) { out.set(mContentRect); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index fa9c2a7edae2..0dc74d72635b 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -385,6 +385,7 @@ public class WindowManagerService extends IWindowManager.Stub final boolean mAllowBootMessages; final boolean mLimitedAlphaCompositing; + final int mMaxUiWidth; final WindowManagerPolicy mPolicy; @@ -949,6 +950,8 @@ public class WindowManagerService extends IWindowManager.Stub com.android.internal.R.integer.config_drawLockTimeoutMillis); mAllowAnimationsInLowPowerMode = context.getResources().getBoolean( com.android.internal.R.bool.config_allowAnimationsInLowPowerMode); + mMaxUiWidth = context.getResources().getInteger( + com.android.internal.R.integer.config_maxUiWidth); mInputManager = inputManager; // Must be before createDisplayContentLocked. mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); mDisplaySettings = new DisplaySettings(); @@ -4572,6 +4575,9 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { final DisplayContent displayContent = getDefaultDisplayContentLocked(); + if (mMaxUiWidth > 0) { + displayContent.setMaxUiWidth(mMaxUiWidth); + } readForcedDisplayPropertiesLocked(displayContent); mDisplayReady = true; } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java index 9b4de043a647..70c7e586d3fe 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLoggingHandler.java @@ -26,6 +26,7 @@ import android.os.Looper; import android.os.Message; import android.os.SystemClock; import android.util.Log; +import android.util.LongSparseArray; import com.android.internal.annotations.GuardedBy; @@ -44,12 +45,21 @@ final class NetworkLoggingHandler extends Handler { // If this value changes, update DevicePolicyManager#retrieveNetworkLogs() javadoc private static final int MAX_EVENTS_PER_BATCH = 1200; - private static final long BATCH_FINALIZATION_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(90); - private static final long BATCH_FINALIZATION_TIMEOUT_ALARM_INTERVAL_MS = - TimeUnit.MINUTES.toMillis(30); + + /** + * Maximum number of batches to store in memory. If more batches are generated and the DO + * doesn't fetch them, we will discard the oldest one. + */ + private static final int MAX_BATCHES = 5; + + private static final long BATCH_FINALIZATION_TIMEOUT_MS = 90 * 60 * 1000; // 1.5h + private static final long BATCH_FINALIZATION_TIMEOUT_ALARM_INTERVAL_MS = 30 * 60 * 1000; // 30m private static final String NETWORK_LOGGING_TIMEOUT_ALARM_TAG = "NetworkLogging.batchTimeout"; + /** Delay after which older batches get discarded after a retrieval. */ + private static final long RETRIEVED_BATCH_DISCARD_DELAY_MS = 5 * 60 * 1000; // 5m + private final DevicePolicyManagerService mDpm; private final AlarmManager mAlarmManager; @@ -66,22 +76,27 @@ final class NetworkLoggingHandler extends Handler { static final int LOG_NETWORK_EVENT_MSG = 1; - // threadsafe as it's Handler's thread confined + /** Network events accumulated so far to be finalized into a batch at some point. */ @GuardedBy("this") - private ArrayList<NetworkEvent> mNetworkEvents = new ArrayList<NetworkEvent>(); + private ArrayList<NetworkEvent> mNetworkEvents = new ArrayList<>(); + /** + * Up to {@code MAX_BATCHES} finalized batches of logs ready to be retrieved by the DO. Already + * retrieved batches are discarded after {@code RETRIEVED_BATCH_DISCARD_DELAY_MS}. + */ @GuardedBy("this") - private ArrayList<NetworkEvent> mFullBatch; + private final LongSparseArray<ArrayList<NetworkEvent>> mBatches = + new LongSparseArray<>(MAX_BATCHES); @GuardedBy("this") private boolean mPaused = false; // each full batch is represented by its token, which the DPC has to provide back to retrieve it @GuardedBy("this") - private long mCurrentFullBatchToken; + private long mCurrentBatchToken; @GuardedBy("this") - private long mLastRetrievedFullBatchToken; + private long mLastRetrievedBatchToken; NetworkLoggingHandler(Looper looper, DevicePolicyManagerService dpm) { super(looper); @@ -93,7 +108,7 @@ final class NetworkLoggingHandler extends Handler { public void handleMessage(Message msg) { switch (msg.what) { case LOG_NETWORK_EVENT_MSG: { - NetworkEvent networkEvent = msg.getData().getParcelable(NETWORK_EVENT_KEY); + final NetworkEvent networkEvent = msg.getData().getParcelable(NETWORK_EVENT_KEY); if (networkEvent != null) { synchronized (NetworkLoggingHandler.this) { mNetworkEvents.add(networkEvent); @@ -113,6 +128,8 @@ final class NetworkLoggingHandler extends Handler { void scheduleBatchFinalization() { final long when = SystemClock.elapsedRealtime() + BATCH_FINALIZATION_TIMEOUT_MS; + // We use alarm manager and not just postDelayed here to ensure the batch gets finalized + // even if the device goes to sleep. mAlarmManager.setWindow(AlarmManager.ELAPSED_REALTIME_WAKEUP, when, BATCH_FINALIZATION_TIMEOUT_ALARM_INTERVAL_MS, NETWORK_LOGGING_TIMEOUT_ALARM_TAG, mBatchTimeoutAlarmListener, this); @@ -131,62 +148,80 @@ final class NetworkLoggingHandler extends Handler { return; } - Log.d(TAG, "Resumed network logging. Current batch=" - + mCurrentFullBatchToken + ", LastRetrievedBatch=" + mLastRetrievedFullBatchToken); + Log.d(TAG, "Resumed network logging. Current batch=" + mCurrentBatchToken + + ", LastRetrievedBatch=" + mLastRetrievedBatchToken); mPaused = false; - // If there is a full batch ready that the device owner hasn't been notified about, do it - // now. - if (mFullBatch != null && mFullBatch.size() > 0 - && mLastRetrievedFullBatchToken != mCurrentFullBatchToken) { + // If there is a batch ready that the device owner hasn't been notified about, do it now. + if (mBatches.size() > 0 && mLastRetrievedBatchToken != mCurrentBatchToken) { scheduleBatchFinalization(); notifyDeviceOwnerLocked(); } } synchronized void discardLogs() { - mFullBatch = null; - mNetworkEvents = new ArrayList<NetworkEvent>(); + mBatches.clear(); + mNetworkEvents = new ArrayList<>(); Log.d(TAG, "Discarded all network logs"); } @GuardedBy("this") private void finalizeBatchAndNotifyDeviceOwnerLocked() { if (mNetworkEvents.size() > 0) { - // finalize the batch and start a new one from scratch - mFullBatch = mNetworkEvents; - mCurrentFullBatchToken++; - mNetworkEvents = new ArrayList<NetworkEvent>(); + // Finalize the batch and start a new one from scratch. + if (mBatches.size() >= MAX_BATCHES) { + // Remove the oldest batch if we hit the limit. + mBatches.removeAt(0); + } + mCurrentBatchToken++; + mBatches.append(mCurrentBatchToken, mNetworkEvents); + mNetworkEvents = new ArrayList<>(); if (!mPaused) { notifyDeviceOwnerLocked(); } } else { - // don't notify the DO, since there are no events; DPC can still retrieve + // Don't notify the DO, since there are no events; DPC can still retrieve // the last full batch if not paused. Log.d(TAG, "Was about to finalize the batch, but there were no events to send to" - + " the DPC, the batchToken of last available batch: " - + mCurrentFullBatchToken); + + " the DPC, the batchToken of last available batch: " + mCurrentBatchToken); } - // regardless of whether the batch was non-empty schedule a new finalization after timeout + // Regardless of whether the batch was non-empty schedule a new finalization after timeout. scheduleBatchFinalization(); } + /** Sends a notification to the DO. Should only be called when there is a batch available. */ @GuardedBy("this") private void notifyDeviceOwnerLocked() { - Bundle extras = new Bundle(); - extras.putLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, mCurrentFullBatchToken); - extras.putInt(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT, mFullBatch.size()); + final Bundle extras = new Bundle(); + final int lastBatchSize = mBatches.valueAt(mBatches.size() - 1).size(); + extras.putLong(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_TOKEN, mCurrentBatchToken); + extras.putInt(DeviceAdminReceiver.EXTRA_NETWORK_LOGS_COUNT, lastBatchSize); Log.d(TAG, "Sending network logging batch broadcast to device owner, batchToken: " - + mCurrentFullBatchToken); + + mCurrentBatchToken); mDpm.sendDeviceOwnerCommand(DeviceAdminReceiver.ACTION_NETWORK_LOGS_AVAILABLE, extras); } - synchronized List<NetworkEvent> retrieveFullLogBatch(long batchToken) { - if (batchToken != mCurrentFullBatchToken) { + synchronized List<NetworkEvent> retrieveFullLogBatch(final long batchToken) { + final int index = mBatches.indexOfKey(batchToken); + if (index < 0) { + // Invalid token or batch has already been discarded. return null; } - mLastRetrievedFullBatchToken = mCurrentFullBatchToken; - return mFullBatch; + + // Schedule this and older batches to be discarded after a delay to lessen memory load + // without interfering with the admin's ability to collect logs out-of-order. + // It isn't critical and we allow it to be delayed further if the phone sleeps, so we don't + // use the alarm manager here. + postDelayed(() -> { + synchronized(this) { + while (mBatches.size() > 0 && mBatches.keyAt(0) <= batchToken) { + mBatches.removeAt(0); + } + } + }, RETRIEVED_BATCH_DISCARD_DELAY_MS); + + mLastRetrievedBatchToken = batchToken; + return mBatches.valueAt(index); } } diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java index dd94a2123d58..1729ceec0005 100644 --- a/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/DisplayContentTests.java @@ -254,6 +254,48 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(window1, sWm.mRoot.computeFocusedWindow()); } + /** + * This tests setting the maximum ui width on a display. + */ + @Test + public void testMaxUiWidth() throws Exception { + final int baseWidth = 1440; + final int baseHeight = 2560; + final int baseDensity = 300; + + sDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity); + + final int maxWidth = 300; + final int resultingHeight = (maxWidth * baseHeight) / baseWidth; + final int resultingDensity = (maxWidth * baseDensity) / baseWidth; + + sDisplayContent.setMaxUiWidth(maxWidth); + verifySizes(sDisplayContent, maxWidth, resultingHeight, resultingDensity); + + // Assert setting values again does not change; + sDisplayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity); + verifySizes(sDisplayContent, maxWidth, resultingHeight, resultingDensity); + + final int smallerWidth = 200; + final int smallerHeight = 400; + final int smallerDensity = 100; + + // Specify smaller dimension, verify that it is honored + sDisplayContent.updateBaseDisplayMetrics(smallerWidth, smallerHeight, smallerDensity); + verifySizes(sDisplayContent, smallerWidth, smallerHeight, smallerDensity); + + // Verify that setting the max width to a greater value than the base width has no effect + sDisplayContent.setMaxUiWidth(maxWidth); + verifySizes(sDisplayContent, smallerWidth, smallerHeight, smallerDensity); + } + + private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth, + int expectedBaseHeight, int expectedBaseDensity) { + assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth); + assertEquals(displayContent.mBaseDisplayHeight, expectedBaseHeight); + assertEquals(displayContent.mBaseDisplayDensity, expectedBaseDensity); + } + private void assertForAllWindowsOrder(List<WindowState> expectedWindows) { final LinkedList<WindowState> actualWindows = new LinkedList(); diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index f1cf4414de9e..d69f933d1fe9 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -554,7 +554,7 @@ public class UsbDeviceManager { boolean usbDataUnlocked) { if (DEBUG) { Slog.d(TAG, "setEnabledFunctions functions=" + functions + ", " - + "forceRestart=" + forceRestart); + + "forceRestart=" + forceRestart + ", usbDataUnlocked=" + usbDataUnlocked); } if (usbDataUnlocked != mUsbDataUnlocked) { @@ -878,7 +878,12 @@ public class UsbDeviceManager { setEnabledFunctions(functions, false, msg.arg1 == 1); break; case MSG_UPDATE_USER_RESTRICTIONS: - setEnabledFunctions(mCurrentFunctions, false, mUsbDataUnlocked); + // Restart the USB stack if USB transfer is enabled but no longer allowed. + final boolean forceRestart = mUsbDataUnlocked + && isUsbDataTransferActive() + && !isUsbTransferAllowed(); + setEnabledFunctions( + mCurrentFunctions, forceRestart, mUsbDataUnlocked && !forceRestart); break; case MSG_SYSTEM_READY: updateUsbNotification(); @@ -902,12 +907,10 @@ public class UsbDeviceManager { case MSG_USER_SWITCHED: { if (mCurrentUser != msg.arg1) { // Restart the USB stack and re-apply user restrictions for MTP or PTP. - final boolean active = UsbManager.containsFunction(mCurrentFunctions, - UsbManager.USB_FUNCTION_MTP) - || UsbManager.containsFunction(mCurrentFunctions, - UsbManager.USB_FUNCTION_PTP); - if (mUsbDataUnlocked && active && mCurrentUser != UserHandle.USER_NULL) { - Slog.v(TAG, "Current user switched to " + mCurrentUser + if (mUsbDataUnlocked + && isUsbDataTransferActive() + && mCurrentUser != UserHandle.USER_NULL) { + Slog.v(TAG, "Current user switched to " + msg.arg1 + "; resetting USB host stack for MTP or PTP"); // avoid leaking sensitive data from previous user setEnabledFunctions(mCurrentFunctions, true, false); @@ -928,6 +931,11 @@ public class UsbDeviceManager { } } + private boolean isUsbDataTransferActive() { + return UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MTP) + || UsbManager.containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_PTP); + } + public UsbAccessory getCurrentAccessory() { return mCurrentAccessory; } diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java index 506f406c333f..960a2d9fd726 100644 --- a/test-runner/src/android/test/mock/MockPackageManager.java +++ b/test-runner/src/android/test/mock/MockPackageManager.java @@ -1118,4 +1118,12 @@ public class MockPackageManager extends PackageManager { public int getInstallReason(String packageName, UserHandle user) { throw new UnsupportedOperationException(); } + + /** + * @hide + */ + @Override + public ComponentName getInstantAppResolverSettingsComponent() { + throw new UnsupportedOperationException(); + } } diff --git a/tests/testables/src/android/testing/BaseFragmentTest.java b/tests/testables/src/android/testing/BaseFragmentTest.java index 53841d597e26..b09bcde897d7 100644 --- a/tests/testables/src/android/testing/BaseFragmentTest.java +++ b/tests/testables/src/android/testing/BaseFragmentTest.java @@ -133,14 +133,7 @@ public abstract class BaseFragmentTest { public void testRecreate() { mFragments.dispatchResume(); processAllMessages(); - mFragments.dispatchPause(); - Parcelable p = mFragments.saveAllState(); - mFragments.dispatchDestroy(); - - mFragments = FragmentController.createController(new HostCallbacks()); - mFragments.attachHost(null); - mFragments.restoreAllState(p, (FragmentManagerNonConfig) null); - mFragments.dispatchResume(); + recreateFragment(); processAllMessages(); } @@ -154,6 +147,18 @@ public abstract class BaseFragmentTest { processAllMessages(); } + protected void recreateFragment() { + mFragments.dispatchPause(); + Parcelable p = mFragments.saveAllState(); + mFragments.dispatchDestroy(); + + mFragments = FragmentController.createController(new HostCallbacks()); + mFragments.attachHost(null); + mFragments.restoreAllState(p, (FragmentManagerNonConfig) null); + mFragments.dispatchResume(); + mFragment = mFragments.getFragmentManager().findFragmentById(VIEW_ID); + } + protected void attachFragmentToWindow() { ViewUtils.attachView(mView); TestableLooper.get(this).processMessages(1); diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index 3330b1a78c1e..2bf52066b618 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -1403,7 +1403,8 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil String8 src = it.getFile()->getPrintableSource(); err = compileXmlFile(bundle, assets, String16(it.getBaseName()), it.getFile(), &table, xmlFlags); - if (err == NO_ERROR) { + // Only verify IDs if there was no error and the file is non-empty. + if (err == NO_ERROR && it.getFile()->hasData()) { ResXMLTree block; block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true); checkForIds(src, block); @@ -1550,7 +1551,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil String8 src = it.getFile()->getPrintableSource(); err = compileXmlFile(bundle, assets, String16(it.getBaseName()), it.getFile(), &table, xmlFlags); - if (err == NO_ERROR) { + if (err == NO_ERROR && it.getFile()->hasData()) { ResXMLTree block; block.setTo(it.getFile()->getData(), it.getFile()->getSize(), true); checkForIds(src, block); @@ -1598,7 +1599,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil err = compileXmlFile(bundle, assets, workItem.resourceName, workItem.xmlRoot, workItem.file, &table, xmlCompilationFlags); - if (err == NO_ERROR) { + if (err == NO_ERROR && workItem.file->hasData()) { assets->addResource(workItem.resPath.getPathLeaf(), workItem.resPath, workItem.file, diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index 391aa47469ef..221f3c2cd0c3 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -78,6 +78,17 @@ status_t compileXmlFile(const Bundle* bundle, ResourceTable* table, int options) { + if (table->versionForCompat(bundle, resourceName, target, root)) { + // The file was versioned, so stop processing here. + // The resource entry has already been removed and the new one added. + // Remove the assets entry. + sp<AaptDir> resDir = assets->getDirs().valueFor(String8("res")); + sp<AaptDir> dir = resDir->getDirs().valueFor(target->getGroupEntry().toDirName( + target->getResourceType())); + dir->removeFile(target->getPath().getPathLeaf()); + return NO_ERROR; + } + if ((options&XML_COMPILE_STRIP_WHITESPACE) != 0) { root->removeWhitespace(true, NULL); } else if ((options&XML_COMPILE_COMPACT_WHITESPACE) != 0) { @@ -4758,6 +4769,77 @@ static bool IsTransitionElement(const String16& name) { return false; } +bool ResourceTable::versionForCompat(const Bundle* bundle, const String16& resourceName, + const sp<AaptFile>& target, const sp<XMLNode>& root) { + XMLNode* node = root.get(); + while (node->getType() != XMLNode::TYPE_ELEMENT) { + // We're assuming the root element is what we're looking for, which can only be under a + // bunch of namespace declarations. + if (node->getChildren().size() != 1) { + // Not sure what to do, bail. + return false; + } + node = node->getChildren().itemAt(0).get(); + } + + if (node->getElementNamespace().size() != 0) { + // Not something we care about. + return false; + } + + int versionedSdk = 0; + if (node->getElementName() == String16("adaptive-icon")) { + versionedSdk = SDK_O; + } + + const int minSdkVersion = getMinSdkVersion(bundle); + const ConfigDescription config(target->getGroupEntry().toParams()); + if (versionedSdk <= minSdkVersion || versionedSdk <= config.sdkVersion) { + return false; + } + + sp<ConfigList> cl = getConfigList(String16(mAssets->getPackage()), + String16(target->getResourceType()), resourceName); + if (!shouldGenerateVersionedResource(cl, config, versionedSdk)) { + return false; + } + + // Remove the original entry. + cl->removeEntry(config); + + // We need to wholesale version this file. + ConfigDescription newConfig(config); + newConfig.sdkVersion = versionedSdk; + sp<AaptFile> newFile = new AaptFile(target->getSourceFile(), + AaptGroupEntry(newConfig), target->getResourceType()); + String8 resPath = String8::format("res/%s/%s.xml", + newFile->getGroupEntry().toDirName(target->getResourceType()).string(), + String8(resourceName).string()); + resPath.convertToResPath(); + + // Add a resource table entry. + addEntry(SourcePos(), + String16(mAssets->getPackage()), + String16(target->getResourceType()), + resourceName, + String16(resPath), + NULL, + &newConfig); + + // Schedule this to be compiled. + CompileResourceWorkItem item; + item.resourceName = resourceName; + item.resPath = resPath; + item.file = newFile; + item.xmlRoot = root->clone(); + item.needsCompiling = false; // This step occurs after we parse/assign, so we don't need + // to do it again. + mWorkQueue.push(item); + + // Now mark the old entry as deleted. + return true; +} + status_t ResourceTable::modifyForCompat(const Bundle* bundle, const String16& resourceName, const sp<AaptFile>& target, diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h index cf1e992ec330..aff22d4d1364 100644 --- a/tools/aapt/ResourceTable.h +++ b/tools/aapt/ResourceTable.h @@ -203,6 +203,9 @@ public: size_t numLocalResources() const; bool hasResources() const; + bool versionForCompat(const Bundle* bundle, const String16& resourceName, + const sp<AaptFile>& file, const sp<XMLNode>& root); + status_t modifyForCompat(const Bundle* bundle); status_t modifyForCompat(const Bundle* bundle, const String16& resourceName, @@ -431,6 +434,10 @@ public: mEntries.add(config, entry); } + void removeEntry(const ResTable_config& config) { + mEntries.removeItem(config); + } + const DefaultKeyedVector<ConfigDescription, sp<Entry> >& getEntries() const { return mEntries; } private: const String16 mName; diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java index 906ebb1fe39e..53c3f90e0137 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePackageManager.java @@ -916,4 +916,9 @@ public class BridgePackageManager extends PackageManager { public boolean canRequestPackageInstalls() { return false; } + + @Override + public ComponentName getInstantAppResolverSettingsComponent() { + return null; + } } diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 10ffd8ae1f7d..1852feb8afc9 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -81,8 +81,6 @@ interface IWifiManager boolean disableNetwork(int netId); - boolean pingSupplicant(); - void startScan(in ScanSettings requested, in WorkSource ws); List<ScanResult> getScanResults(String callingPackage); |