summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/system-current.txt4
-rw-r--r--core/java/android/app/ActivityManagerNative.java21
-rw-r--r--core/java/android/app/IActivityManager.java2
-rw-r--r--core/java/android/app/NotificationManager.java8
-rw-r--r--core/java/android/app/StatusBarManager.java9
-rw-r--r--core/java/android/provider/Settings.java7
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java4
-rw-r--r--core/java/android/webkit/IWebViewUpdateService.aidl26
-rw-r--r--core/java/android/webkit/WebViewFactory.java281
-rw-r--r--core/java/android/webkit/WebViewProviderInfo.aidl19
-rw-r--r--core/java/android/webkit/WebViewProviderInfo.java140
-rw-r--r--core/java/android/webkit/WebViewProviderResponse.aidl19
-rw-r--r--core/java/android/webkit/WebViewProviderResponse.java61
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl2
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl2
-rw-r--r--core/java/com/android/internal/util/StateMachine.java10
-rw-r--r--core/res/res/values/config.xml5
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/res/res/xml/config_webview_packages.xml20
-rw-r--r--packages/FusedLocation/res/values-de/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-uz-rUZ/strings.xml2
-rw-r--r--packages/SettingsLib/res/values/strings.xml5
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml12
-rw-r--r--packages/SystemUI/res/values-lo-rLA/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ms-rMY/strings.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/Task.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java2
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java41
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java5
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java3
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java4
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdateService.java365
-rw-r--r--services/java/com/android/server/SystemServer.java5
38 files changed, 963 insertions, 217 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index 332a51623212..492d6a923f51 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -46479,8 +46479,6 @@ package android.webkit {
method public static android.content.pm.PackageInfo getLoadedPackageInfo();
method public static java.lang.String getWebViewPackageName();
method public static int loadWebViewNativeLibraryFromPackage(java.lang.String);
- method public static void onWebViewUpdateInstalled();
- method public static void prepareWebViewInSystemServer();
method public static void prepareWebViewInZygote();
field public static final java.lang.String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = "persist.sys.webview.vmsize";
field public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2; // 0x2
@@ -46489,7 +46487,9 @@ package android.webkit {
field public static final int LIBLOAD_FAILED_TO_LOAD_LIBRARY = 6; // 0x6
field public static final int LIBLOAD_FAILED_TO_OPEN_RELRO_FILE = 5; // 0x5
field public static final int LIBLOAD_FAILED_WAITING_FOR_RELRO = 3; // 0x3
+ field public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 9; // 0x9
field public static final int LIBLOAD_SUCCESS = 0; // 0x0
+ field public static final int LIBLOAD_WEBVIEW_BEING_REPLACED = 8; // 0x8
field public static final int LIBLOAD_WRONG_PACKAGE_NAME = 1; // 0x1
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 4cb261927ef8..f11bf742c925 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1558,6 +1558,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case KILL_PACKAGE_DEPENDENTS_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ String packageName = data.readString();
+ int userId = data.readInt();
+ killPackageDependents(packageName, userId);
+ reply.writeNoException();
+ return true;
+ }
+
case FORCE_STOP_PACKAGE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String packageName = data.readString();
@@ -4736,6 +4745,18 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
+ public void killPackageDependents(String packageName, int userId) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(packageName);
+ data.writeInt(userId);
+ mRemote.transact(KILL_PACKAGE_DEPENDENTS_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
public void forceStopPackage(String packageName, int userId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index eb8d6bc1e92a..64c69af8691d 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -259,6 +259,7 @@ public interface IActivityManager extends IInterface {
public void killBackgroundProcesses(final String packageName, int userId)
throws RemoteException;
public void killAllBackgroundProcesses() throws RemoteException;
+ public void killPackageDependents(final String packageName, int userId) throws RemoteException;
public void forceStopPackage(final String packageName, int userId) throws RemoteException;
// Note: probably don't want to allow applications access to these.
@@ -912,4 +913,5 @@ public interface IActivityManager extends IInterface {
int UNLOCK_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 351;
int IN_MULTI_WINDOW_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 352;
int IN_PICTURE_IN_PICTURE_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 353;
+ int KILL_PACKAGE_DEPENDENTS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 354;
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 89610e99a718..85d9831921ac 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -128,6 +128,14 @@ public class NotificationManager
= "android.app.action.INTERRUPTION_FILTER_CHANGED";
/**
+ * Intent that is broadcast when the state of getCurrentInterruptionFilter() changes.
+ * @hide
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_INTERRUPTION_FILTER_CHANGED_INTERNAL
+ = "android.app.action.INTERRUPTION_FILTER_CHANGED_INTERNAL";
+
+ /**
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
* Normal interruption filter.
*/
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index 5e8ad68957b2..b899116142c8 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -180,10 +180,17 @@ public class StatusBarManager {
* Expand the settings panel.
*/
public void expandSettingsPanel() {
+ expandSettingsPanel(null);
+ }
+
+ /**
+ * Expand the settings panel and open a subPanel, pass null to just open the settings panel.
+ */
+ public void expandSettingsPanel(String subPanel) {
try {
final IStatusBarService svc = getService();
if (svc != null) {
- svc.expandSettingsPanel();
+ svc.expandSettingsPanel(subPanel);
}
} catch (RemoteException ex) {
// system process is dead anyway.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 74fd8cd10de3..a1e551082799 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5749,6 +5749,13 @@ public final class Settings {
"camera_double_tap_power_gesture_disabled";
/**
+ * Name of the package used as WebView provider (if unset the provider is instead determined
+ * by the system).
+ * @hide
+ */
+ public static final String WEBVIEW_PROVIDER = "webview_provider";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 76c63b958046..232d4fe4e979 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -713,10 +713,10 @@ public abstract class NotificationListenerService extends Service {
createLegacyIconExtras(sbn.getNotification());
maybePopulateRemoteViews(sbn.getNotification());
} catch (IllegalArgumentException e) {
- // drop corrupt notification
- sbn = null;
+ // warn and drop corrupt notification
Log.w(TAG, "onNotificationPosted: can't rebuild notification from " +
sbn.getPackageName());
+ sbn = null;
}
// protect subclass from concurrent modifications of (@link mNotificationKeys}.
diff --git a/core/java/android/webkit/IWebViewUpdateService.aidl b/core/java/android/webkit/IWebViewUpdateService.aidl
index a77459b09251..89d5d69de392 100644
--- a/core/java/android/webkit/IWebViewUpdateService.aidl
+++ b/core/java/android/webkit/IWebViewUpdateService.aidl
@@ -16,6 +16,10 @@
package android.webkit;
+import android.content.pm.PackageInfo;
+import android.webkit.WebViewProviderInfo;
+import android.webkit.WebViewProviderResponse;
+
/**
* Private service to wait for the updatable WebView to be ready for use.
* @hide
@@ -25,12 +29,28 @@ interface IWebViewUpdateService {
/**
* Used by the relro file creator to notify the service that it's done.
*/
- void notifyRelroCreationCompleted(boolean is64Bit, boolean success);
+ void notifyRelroCreationCompleted();
/**
* Used by WebViewFactory to block loading of WebView code until
- * preparations are complete.
+ * preparations are complete. Returns the package used as WebView provider.
*/
- void waitForRelroCreationCompleted(boolean is64Bit);
+ WebViewProviderResponse waitForAndGetProvider();
+ /**
+ * DevelopmentSettings uses this to notify WebViewUpdateService that a
+ * new provider has been selected by the user.
+ */
+ void changeProviderAndSetting(String newProvider);
+
+ /**
+ * DevelopmentSettings uses this to get the current available WebView
+ * providers (to display as choices to the user).
+ */
+ WebViewProviderInfo[] getValidWebViewPackages();
+
+ /**
+ * Used by DevelopmentSetting to get the name of the WebView provider currently in use.
+ */
+ String getCurrentWebViewPackageName();
}
diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java
index 229011db049c..01d15664f24a 100644
--- a/core/java/android/webkit/WebViewFactory.java
+++ b/core/java/android/webkit/WebViewFactory.java
@@ -24,6 +24,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.res.XmlResourceParser;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
@@ -31,20 +32,27 @@ import android.os.ServiceManager;
import android.os.StrictMode;
import android.os.SystemProperties;
import android.os.Trace;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
import android.text.TextUtils;
import android.util.AndroidRuntimeException;
import android.util.Log;
+import com.android.internal.util.XmlUtils;
import com.android.server.LocalServices;
import dalvik.system.VMRuntime;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import org.xmlpull.v1.XmlPullParserException;
+
/**
* Top level factory, used creating all the main WebView implementation classes.
*
@@ -83,6 +91,8 @@ public final class WebViewFactory {
public static final int LIBLOAD_SUCCESS = 0;
public static final int LIBLOAD_WRONG_PACKAGE_NAME = 1;
public static final int LIBLOAD_ADDRESS_SPACE_NOT_RESERVED = 2;
+
+ // error codes for waiting for WebView preparation
public static final int LIBLOAD_FAILED_WAITING_FOR_RELRO = 3;
public static final int LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES = 4;
@@ -91,57 +101,95 @@ public final class WebViewFactory {
public static final int LIBLOAD_FAILED_TO_LOAD_LIBRARY = 6;
public static final int LIBLOAD_FAILED_JNI_CALL = 7;
- private static class MissingWebViewPackageException extends AndroidRuntimeException {
- public MissingWebViewPackageException(String message) { super(message); }
- public MissingWebViewPackageException(Exception e) { super(e); }
- }
-
- /** @hide */
- public static String[] getWebViewPackageNames() {
- return AppGlobals.getInitialApplication().getResources().getStringArray(
- com.android.internal.R.array.config_webViewPackageNames);
- }
-
- // TODO (gsennton) remove when committing webview xts test change
- public static String getWebViewPackageName() {
- String[] webViewPackageNames = getWebViewPackageNames();
- return webViewPackageNames[webViewPackageNames.length-1];
+ // more error codes for waiting for WebView preparation
+ public static final int LIBLOAD_WEBVIEW_BEING_REPLACED = 8;
+ public static final int LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN = 9;
+
+ private static String getWebViewPreparationErrorReason(int error) {
+ switch (error) {
+ case LIBLOAD_FAILED_WAITING_FOR_RELRO:
+ return "Time out waiting for Relro files being created";
+ case LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES:
+ return "No WebView installed";
+ case LIBLOAD_WEBVIEW_BEING_REPLACED:
+ return "Time out waiting for WebView to be replaced";
+ case LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN:
+ return "Crashed for unknown reason";
+ }
+ return "Unknown";
}
/**
- * Return the package info of the first package in the webview priority list that contains
- * webview.
- *
* @hide
*/
- public static PackageInfo findPreferredWebViewPackage() {
- PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
+ public static class MissingWebViewPackageException extends AndroidRuntimeException {
+ public MissingWebViewPackageException(String message) { super(message); }
+ public MissingWebViewPackageException(Exception e) { super(e); }
+ }
- for (String packageName : getWebViewPackageNames()) {
- try {
- PackageInfo packageInfo = pm.getPackageInfo(packageName,
- PackageManager.GET_META_DATA);
- ApplicationInfo applicationInfo = packageInfo.applicationInfo;
+ private static String TAG_START = "webviewproviders";
+ private static String TAG_WEBVIEW_PROVIDER = "webviewprovider";
+ private static String TAG_PACKAGE_NAME = "packageName";
+ private static String TAG_DESCRIPTION = "description";
+ private static String TAG_SIGNATURE = "signature";
- // If the correct flag is set the package contains webview.
- if (getWebViewLibrary(applicationInfo) != null) {
- return packageInfo;
+ /**
+ * Returns all packages declared in the framework resources as potential WebView providers.
+ * @hide
+ * */
+ public static WebViewProviderInfo[] getWebViewPackages() {
+ XmlResourceParser parser = null;
+ List<WebViewProviderInfo> webViewProviders = new ArrayList<WebViewProviderInfo>();
+ try {
+ parser = AppGlobals.getInitialApplication().getResources().getXml(
+ com.android.internal.R.xml.config_webview_packages);
+ XmlUtils.beginDocument(parser, TAG_START);
+ while(true) {
+ XmlUtils.nextElement(parser);
+ String element = parser.getName();
+ if (element == null) {
+ break;
+ }
+ if (element.equals(TAG_WEBVIEW_PROVIDER)) {
+ String packageName = parser.getAttributeValue(null, TAG_PACKAGE_NAME);
+ if (packageName == null) {
+ throw new MissingWebViewPackageException(
+ "WebView provider in framework resources missing package name");
+ }
+ String description = parser.getAttributeValue(null, TAG_DESCRIPTION);
+ if (description == null) {
+ throw new MissingWebViewPackageException(
+ "WebView provider in framework resources missing description");
+ }
+ String signature = parser.getAttributeValue(null, TAG_SIGNATURE);
+ webViewProviders.add(
+ new WebViewProviderInfo(packageName, description, signature));
+ }
+ else {
+ Log.e(LOGTAG, "Found an element that is not a webview provider");
}
- } catch (PackageManager.NameNotFoundException e) {
}
+ } catch(XmlPullParserException e) {
+ throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
+ } catch(IOException e) {
+ throw new MissingWebViewPackageException("Error when parsing WebView meta data " + e);
+ } finally {
+ if (parser != null) parser.close();
}
- throw new MissingWebViewPackageException("Could not find a loadable WebView package");
+ return webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]);
}
- // throws MissingWebViewPackageException
- private static ApplicationInfo getWebViewApplicationInfo() {
- if (sPackageInfo == null)
- return findPreferredWebViewPackage().applicationInfo;
- else
- return sPackageInfo.applicationInfo;
+
+ // TODO (gsennton) remove when committing webview xts test change
+ public static String getWebViewPackageName() {
+ WebViewProviderInfo[] providers = getWebViewPackages();
+ return providers[0].packageName;
}
- private static String getWebViewLibrary(ApplicationInfo ai) {
+ /**
+ * @hide
+ */
+ public static String getWebViewLibrary(ApplicationInfo ai) {
if (ai.metaData != null)
return ai.metaData.getString("com.android.webview.WebViewLibrary");
return null;
@@ -156,16 +204,14 @@ public final class WebViewFactory {
* name is the same as the one providing the webview.
*/
public static int loadWebViewNativeLibraryFromPackage(String packageName) {
- try {
- sPackageInfo = findPreferredWebViewPackage();
- } catch (MissingWebViewPackageException e) {
- return LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
+ int ret = waitForProviderAndSetPackageInfo();
+ if (ret != LIBLOAD_SUCCESS) {
+ return ret;
}
+ if (!sPackageInfo.packageName.equals(packageName))
+ return LIBLOAD_WRONG_PACKAGE_NAME;
- if (packageName != null && packageName.equals(sPackageInfo.packageName)) {
- return loadNativeLibrary();
- }
- return LIBLOAD_WRONG_PACKAGE_NAME;
+ return loadNativeLibrary();
}
static WebViewFactoryProvider getProvider() {
@@ -207,17 +253,45 @@ public final class WebViewFactory {
private static Class<WebViewFactoryProvider> getProviderClass() {
try {
// First fetch the package info so we can log the webview package version.
- sPackageInfo = findPreferredWebViewPackage();
+ int res = waitForProviderAndSetPackageInfo();
+ if (res != LIBLOAD_SUCCESS) {
+ throw new MissingWebViewPackageException(
+ "Failed to load WebView provider, error: "
+ + getWebViewPreparationErrorReason(res));
+ }
Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " +
sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")");
+ Application initialApplication = AppGlobals.getInitialApplication();
+ Context webViewContext = null;
+ try {
+ // Construct a package context to load the Java code into the current app.
+ // This is done as early as possible since by constructing a package context we
+ // register the WebView package as a dependency for the current application so that
+ // when the WebView package is updated this application will be killed.
+ webViewContext = initialApplication.createPackageContext(
+ sPackageInfo.packageName,
+ Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new MissingWebViewPackageException(e);
+ }
+
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
loadNativeLibrary();
Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()");
try {
- return getChromiumProviderClass();
+ initialApplication.getAssets().addAssetPathAsSharedLibrary(
+ webViewContext.getApplicationInfo().sourceDir);
+ ClassLoader clazzLoader = webViewContext.getClassLoader();
+ Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
+ try {
+ return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
+ true, clazzLoader);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
+ }
} catch (ClassNotFoundException e) {
Log.e(LOGTAG, "error loading provider", e);
throw new AndroidRuntimeException(e);
@@ -239,30 +313,6 @@ public final class WebViewFactory {
}
}
- // throws MissingWebViewPackageException
- private static Class<WebViewFactoryProvider> getChromiumProviderClass()
- throws ClassNotFoundException {
- Application initialApplication = AppGlobals.getInitialApplication();
- try {
- // Construct a package context to load the Java code into the current app.
- Context webViewContext = initialApplication.createPackageContext(
- sPackageInfo.packageName,
- Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
- initialApplication.getAssets().addAssetPathAsSharedLibrary(
- webViewContext.getApplicationInfo().sourceDir);
- ClassLoader clazzLoader = webViewContext.getClassLoader();
- Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
- try {
- return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true,
- clazzLoader);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
- }
- } catch (PackageManager.NameNotFoundException e) {
- throw new MissingWebViewPackageException(e);
- }
- }
-
/**
* Perform any WebView loading preparations that must happen in the zygote.
* Currently, this means allocating address space to load the real JNI library later.
@@ -289,44 +339,34 @@ public final class WebViewFactory {
}
}
- /**
- * Perform any WebView loading preparations that must happen at boot from the system server,
- * after the package manager has started or after an update to the webview is installed.
- * This must be called in the system server.
- * Currently, this means spawning the child processes which will create the relro files.
- */
- public static void prepareWebViewInSystemServer() {
- String[] nativePaths = null;
- try {
- nativePaths = getWebViewNativeLibraryPaths();
- } catch (Throwable t) {
- // Log and discard errors at this stage as we must not crash the system server.
- Log.e(LOGTAG, "error preparing webview native library", t);
- }
- prepareWebViewInSystemServer(nativePaths);
- }
-
- private static void prepareWebViewInSystemServer(String[] nativeLibraryPaths) {
+ private static int prepareWebViewInSystemServer(String[] nativeLibraryPaths) {
if (DEBUG) Log.v(LOGTAG, "creating relro files");
+ int numRelros = 0;
// We must always trigger createRelRo regardless of the value of nativeLibraryPaths. Any
// unexpected values will be handled there to ensure that we trigger notifying any process
- // waiting on relreo creation.
+ // waiting on relro creation.
if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro");
createRelroFile(false /* is64Bit */, nativeLibraryPaths);
+ numRelros++;
}
if (Build.SUPPORTED_64_BIT_ABIS.length > 0) {
if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro");
createRelroFile(true /* is64Bit */, nativeLibraryPaths);
+ numRelros++;
}
+ return numRelros;
}
- public static void onWebViewUpdateInstalled() {
+ /**
+ * @hide
+ */
+ public static int onWebViewProviderChanged(PackageInfo packageInfo) {
String[] nativeLibs = null;
try {
- nativeLibs = WebViewFactory.getWebViewNativeLibraryPaths();
+ nativeLibs = WebViewFactory.getWebViewNativeLibraryPaths(packageInfo);
if (nativeLibs != null) {
long newVmSize = 0L;
@@ -373,7 +413,7 @@ public final class WebViewFactory {
// Log and discard errors at this stage as we must not crash the system server.
Log.e(LOGTAG, "error preparing webview native library", t);
}
- prepareWebViewInSystemServer(nativeLibs);
+ return prepareWebViewInSystemServer(nativeLibs);
}
// throws MissingWebViewPackageException
@@ -397,8 +437,8 @@ public final class WebViewFactory {
}
// throws MissingWebViewPackageException
- private static String[] getWebViewNativeLibraryPaths() {
- ApplicationInfo ai = getWebViewApplicationInfo();
+ private static String[] getWebViewNativeLibraryPaths(PackageInfo packageInfo) {
+ ApplicationInfo ai = packageInfo.applicationInfo;
final String NATIVE_LIB_FILE_NAME = getWebViewLibrary(ai);
String path32;
@@ -460,7 +500,7 @@ public final class WebViewFactory {
public void run() {
try {
Log.e(LOGTAG, "relro file creator for " + abi + " crashed. Proceeding without");
- getUpdateService().notifyRelroCreationCompleted(is64Bit, false);
+ getUpdateService().notifyRelroCreationCompleted();
} catch (RemoteException e) {
Log.e(LOGTAG, "Cannot reach WebViewUpdateService. " + e.getMessage());
}
@@ -508,7 +548,7 @@ public final class WebViewFactory {
} finally {
// We must do our best to always notify the update service, even if something fails.
try {
- getUpdateService().notifyRelroCreationCompleted(is64Bit, result);
+ getUpdateService().notifyRelroCreationCompleted();
} catch (RemoteException e) {
Log.e(LOGTAG, "error notifying update service", e);
}
@@ -521,35 +561,38 @@ public final class WebViewFactory {
}
}
+ private static int waitForProviderAndSetPackageInfo() {
+ WebViewProviderResponse response = null;
+ try {
+ response =
+ getUpdateService().waitForAndGetProvider();
+ if (response.status == WebViewFactory.LIBLOAD_SUCCESS)
+ sPackageInfo = response.packageInfo;
+ } catch (RemoteException e) {
+ Log.e(LOGTAG, "error waiting for relro creation", e);
+ return LIBLOAD_FAILED_WAITING_FOR_WEBVIEW_REASON_UNKNOWN;
+ }
+ return response.status;
+ }
+
+ // Assumes that we have waited for relro creation and set sPackageInfo
private static int loadNativeLibrary() {
if (!sAddressSpaceReserved) {
Log.e(LOGTAG, "can't load with relro file; address space not reserved");
return LIBLOAD_ADDRESS_SPACE_NOT_RESERVED;
}
- try {
- getUpdateService().waitForRelroCreationCompleted(VMRuntime.getRuntime().is64Bit());
- } catch (RemoteException e) {
- Log.e(LOGTAG, "error waiting for relro creation, proceeding without", e);
- return LIBLOAD_FAILED_WAITING_FOR_RELRO;
- }
-
- try {
- String[] args = getWebViewNativeLibraryPaths();
- int result = nativeLoadWithRelroFile(args[0] /* path32 */,
- args[1] /* path64 */,
- CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
- CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
- if (result != LIBLOAD_SUCCESS) {
- Log.w(LOGTAG, "failed to load with relro file, proceeding without");
- } else if (DEBUG) {
- Log.v(LOGTAG, "loaded with relro file");
- }
- return result;
- } catch (MissingWebViewPackageException e) {
- Log.e(LOGTAG, "Failed to list WebView package libraries for loadNativeLibrary", e);
- return LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
+ String[] args = getWebViewNativeLibraryPaths(sPackageInfo);
+ int result = nativeLoadWithRelroFile(args[0] /* path32 */,
+ args[1] /* path64 */,
+ CHROMIUM_WEBVIEW_NATIVE_RELRO_32,
+ CHROMIUM_WEBVIEW_NATIVE_RELRO_64);
+ if (result != LIBLOAD_SUCCESS) {
+ Log.w(LOGTAG, "failed to load with relro file, proceeding without");
+ } else if (DEBUG) {
+ Log.v(LOGTAG, "loaded with relro file");
}
+ return result;
}
private static IWebViewUpdateService getUpdateService() {
diff --git a/core/java/android/webkit/WebViewProviderInfo.aidl b/core/java/android/webkit/WebViewProviderInfo.aidl
new file mode 100644
index 000000000000..82e5a7936de8
--- /dev/null
+++ b/core/java/android/webkit/WebViewProviderInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015 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 android.webkit;
+
+parcelable WebViewProviderInfo;
diff --git a/core/java/android/webkit/WebViewProviderInfo.java b/core/java/android/webkit/WebViewProviderInfo.java
new file mode 100644
index 000000000000..d5e3a230919b
--- /dev/null
+++ b/core/java/android/webkit/WebViewProviderInfo.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2015 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 android.webkit;
+
+import android.app.AppGlobals;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
+import android.os.Build;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AndroidRuntimeException;
+import android.util.Base64;
+
+import java.util.Arrays;
+
+/** @hide */
+public class WebViewProviderInfo implements Parcelable {
+
+ /**
+ * @hide
+ */
+ public static class WebViewPackageNotFoundException extends AndroidRuntimeException {
+ public WebViewPackageNotFoundException(String message) { super(message); }
+ public WebViewPackageNotFoundException(Exception e) { super(e); }
+ }
+
+ public WebViewProviderInfo(String packageName, String description, String signature) {
+ this.packageName = packageName;
+ this.description = description;
+ this.signature = signature;
+ }
+
+ private boolean hasValidSignature() {
+ if (Build.IS_DEBUGGABLE)
+ return true;
+ Signature[] packageSignatures;
+ try {
+ // If no signature is declared, instead check whether the package is included in the
+ // system.
+ if (signature == null)
+ return getPackageInfo().applicationInfo.isSystemApp();
+
+ packageSignatures = getPackageInfo().signatures;
+ } catch (WebViewPackageNotFoundException e) {
+ return false;
+ }
+ if (packageSignatures.length != 1)
+ return false;
+ final byte[] releaseSignature = Base64.decode(signature, Base64.DEFAULT);
+ return Arrays.equals(releaseSignature, packageSignatures[0].toByteArray());
+ }
+
+ /**
+ * Returns whether this provider is valid for use as a WebView provider.
+ */
+ public boolean isValidProvider() {
+ ApplicationInfo applicationInfo;
+ try {
+ applicationInfo = getPackageInfo().applicationInfo;
+ } catch (WebViewPackageNotFoundException e) {
+ return false;
+ }
+ if (hasValidSignature() && WebViewFactory.getWebViewLibrary(applicationInfo) != null) {
+ return true;
+ }
+ return false;
+ }
+
+ public PackageInfo getPackageInfo() {
+ if (packageInfo == null) {
+ try {
+ PackageManager pm = AppGlobals.getInitialApplication().getPackageManager();
+ packageInfo = pm.getPackageInfo(packageName, PACKAGE_FLAGS);
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new WebViewPackageNotFoundException(e);
+ }
+ }
+ return packageInfo;
+ }
+
+ // aidl stuff
+ public static final Parcelable.Creator<WebViewProviderInfo> CREATOR =
+ new Parcelable.Creator<WebViewProviderInfo>() {
+ public WebViewProviderInfo createFromParcel(Parcel in) {
+ return new WebViewProviderInfo(in);
+ }
+
+ public WebViewProviderInfo[] newArray(int size) {
+ return new WebViewProviderInfo[size];
+ }
+ };
+
+ private WebViewProviderInfo(Parcel in) {
+ packageName = in.readString();
+ description = in.readString();
+ signature = in.readString();
+ packageInfo = null;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(packageName);
+ out.writeString(description);
+ out.writeString(signature);
+ }
+
+ // fields read from framework resource
+ public String packageName;
+ public String description;
+
+ private String signature;
+
+ private PackageInfo packageInfo;
+ // flags declaring we want extra info from the package manager
+ private final static int PACKAGE_FLAGS =
+ PackageManager.GET_META_DATA
+ | PackageManager.GET_SIGNATURES;
+}
+
diff --git a/core/java/android/webkit/WebViewProviderResponse.aidl b/core/java/android/webkit/WebViewProviderResponse.aidl
new file mode 100644
index 000000000000..9c884cc7ad33
--- /dev/null
+++ b/core/java/android/webkit/WebViewProviderResponse.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2015 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 android.webkit;
+
+parcelable WebViewProviderResponse;
diff --git a/core/java/android/webkit/WebViewProviderResponse.java b/core/java/android/webkit/WebViewProviderResponse.java
new file mode 100644
index 000000000000..f5e09e2be71e
--- /dev/null
+++ b/core/java/android/webkit/WebViewProviderResponse.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 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 android.webkit;
+
+import android.content.pm.PackageInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public class WebViewProviderResponse implements Parcelable {
+
+ public WebViewProviderResponse(PackageInfo packageInfo, int status) {
+ this.packageInfo = packageInfo;
+ this.status = status;
+ }
+
+ // aidl stuff
+ public static final Parcelable.Creator<WebViewProviderResponse> CREATOR =
+ new Parcelable.Creator<WebViewProviderResponse>() {
+ public WebViewProviderResponse createFromParcel(Parcel in) {
+ return new WebViewProviderResponse(in);
+ }
+
+ public WebViewProviderResponse[] newArray(int size) {
+ return new WebViewProviderResponse[size];
+ }
+ };
+
+ private WebViewProviderResponse(Parcel in) {
+ packageInfo = in.readTypedObject(PackageInfo.CREATOR);
+ status = in.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeTypedObject(packageInfo, flags);
+ out.writeInt(status);
+ }
+
+ PackageInfo packageInfo;
+ int status;
+}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 11ef18b4d5c0..849d3145bb56 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -28,7 +28,7 @@ oneway interface IStatusBar
void removeIcon(int index);
void disable(int state1, int state2);
void animateExpandNotificationsPanel();
- void animateExpandSettingsPanel();
+ void animateExpandSettingsPanel(String subPanel);
void animateCollapsePanels();
void setSystemUiVisibility(int vis, int mask);
void topAppWindowChanged(boolean menuVisible);
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 6c957becc5e5..0a4ad0661c64 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -39,7 +39,7 @@ interface IStatusBarService
void topAppWindowChanged(boolean menuVisible);
void setImeWindowStatus(in IBinder token, int vis, int backDisposition,
boolean showImeSwitcher);
- void expandSettingsPanel();
+ void expandSettingsPanel(String subPanel);
void setCurrentUser(int newUserId);
// ---- Methods below are for use by the status bar policy services ----
diff --git a/core/java/com/android/internal/util/StateMachine.java b/core/java/com/android/internal/util/StateMachine.java
index 8c4d078ecd78..406b487f643d 100644
--- a/core/java/com/android/internal/util/StateMachine.java
+++ b/core/java/com/android/internal/util/StateMachine.java
@@ -778,8 +778,11 @@ public class StateMachine {
*/
@Override
public final void handleMessage(Message msg) {
- mSm.onPreHandleMessage(msg);
if (!mHasQuit) {
+ if (mSm != null) {
+ mSm.onPreHandleMessage(msg);
+ }
+
if (mDbg) mSm.log("handleMessage: E msg.what=" + msg.what);
/** Save the current message */
@@ -803,8 +806,11 @@ public class StateMachine {
// We need to check if mSm == null here as we could be quitting.
if (mDbg && mSm != null) mSm.log("handleMessage: X");
+
+ if (mSm != null) {
+ mSm.onPostHandleMessage(msg);
+ }
}
- mSm.onPostHandleMessage(msg);
}
/**
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 97c0e07186e0..e2b1dbb6300e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2154,11 +2154,6 @@
string that's stored in 8-bit unpacked format) characters.-->
<bool translatable="false" name="config_sms_decode_gsm_8bit_data">false</bool>
- <!-- List of package names (ordered by preference) providing WebView implementations. -->
- <string-array name="config_webViewPackageNames" translatable="false">
- <item>com.android.webview</item>
- </string-array>
-
<!-- If EMS is not supported, framework breaks down EMS into single segment SMS
and adds page info " x/y". This config is used to set which carrier doesn't
support EMS and whether page info should be added at the beginning or the end.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6367d3728d50..bf758c225859 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2018,7 +2018,7 @@
<java-symbol type="attr" name="actionModeWebSearchDrawable" />
<java-symbol type="string" name="websearch" />
<java-symbol type="drawable" name="ic_media_video_poster" />
- <java-symbol type="array" name="config_webViewPackageNames" />
+ <java-symbol type="xml" name="config_webview_packages" />
<!-- From SubtitleView -->
<java-symbol type="dimen" name="subtitle_corner_radius" />
diff --git a/core/res/res/xml/config_webview_packages.xml b/core/res/res/xml/config_webview_packages.xml
new file mode 100644
index 000000000000..6f9c58d2f9b7
--- /dev/null
+++ b/core/res/res/xml/config_webview_packages.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2015 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.
+-->
+
+<webviewproviders>
+ <!-- The default WebView implementation -->
+ <webviewprovider description="Android WebView" packageName="com.android.webview" />
+</webviewproviders>
diff --git a/packages/FusedLocation/res/values-de/strings.xml b/packages/FusedLocation/res/values-de/strings.xml
index d7e5faabe2a3..5c846d8efd16 100644
--- a/packages/FusedLocation/res/values-de/strings.xml
+++ b/packages/FusedLocation/res/values-de/strings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="5379477904423203699">"Kombinierte Standortbestimmung"</string>
+ <string name="app_label" msgid="5379477904423203699">"Kombinierte Standortbest."</string>
</resources>
diff --git a/packages/SettingsLib/res/values-uz-rUZ/strings.xml b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
index 82e8dc694cde..1033bb19c10c 100644
--- a/packages/SettingsLib/res/values-uz-rUZ/strings.xml
+++ b/packages/SettingsLib/res/values-uz-rUZ/strings.xml
@@ -141,7 +141,7 @@
<string name="development_settings_not_available" msgid="4308569041701535607">"Bu foydalanuvchiga dasturchi imkoniyatlari taqdim etilmagan"</string>
<string name="vpn_settings_not_available" msgid="956841430176985598">"Ushbu foydalanuvchi uchun VPN sozlamalari mavjud emas"</string>
<string name="tethering_settings_not_available" msgid="6765770438438291012">"Ushbu foydalanuvchi uchun Modem rejimi sozlamalari mavjud emas"</string>
- <string name="apn_settings_not_available" msgid="7873729032165324000">"Ushbu foydalanuvchi uchun Ulanish nuqtasi nomi (APN) sozlamalari mavjud emas"</string>
+ <string name="apn_settings_not_available" msgid="7873729032165324000">"Ushbu foydalanuvchi uchun Internetga kirish nuqtasi (APN) sozlamalari mavjud emas"</string>
<string name="enable_adb" msgid="7982306934419797485">"USB orqali nosozliklarni tuzatish"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"USB orqali kompyuterga ulanganda tuzatish rejimi yoqilsin"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"USB orqali nosozliklarni tuzatishni taqiqlash"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 55bd08a16d8f..7e2288133ab3 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -675,6 +675,11 @@
<!-- Sound & display settings screen, theme setting value to automatically switch between a light- or dark-colored user interface [CHAR LIMIT=30] -->
<string name="night_mode_auto">Automatic</string>
+ <!-- Developer settings: select WebView provider title -->
+ <string name="select_webview_provider_title">WebView implementation</string>
+ <!-- Developer settings: select WebView provider dialog title -->
+ <string name="select_webview_provider_dialog_title">Set WebView implementation</string>
+
<!-- Developer settings screen, convert userdata to file encryption option name -->
<string name="convert_to_file_encryption">Convert to file encryption</string>
<!-- Developer settings screen, convert userdata to file encryption summary when option is available -->
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 5acd0ef8fae8..8d3da1172771 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -217,7 +217,7 @@
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"העברת המסך הופסקה."</string>
<string name="accessibility_quick_settings_work_mode_off" msgid="7045417396436552890">"מצב עבודה כבוי."</string>
<string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"מצב עבודה מופעל."</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"מצב עבודה כובה."</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"מצב עבודה הושבת."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"מצב עבודה הופעל."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"בהירות תצוגה"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"‏השימוש בנתוני 2G-3G מושהה"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 1edfd5c3b784..ae57a32629f7 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -161,7 +161,7 @@
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"マナーモード着信。"</string>
<!-- no translation found for accessibility_casting (6887382141726543668) -->
<skip />
- <string name="accessibility_work_mode" msgid="2478631941714607225">"職場モード"</string>
+ <string name="accessibility_work_mode" msgid="2478631941714607225">"Work モード"</string>
<string name="accessibility_recents_item_will_be_dismissed" msgid="395770242498031481">"<xliff:g id="APP">%s</xliff:g>を削除します。"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g>は削除されました。"</string>
<string name="accessibility_recents_all_items_dismissed" msgid="4464697366179168836">"最近のアプリケーションをすべて消去しました。"</string>
@@ -213,10 +213,10 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"モバイルアクセスポイントをOFFにしました。"</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"モバイルアクセスポイントをONにしました。"</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"画面のキャストが停止しました。"</string>
- <string name="accessibility_quick_settings_work_mode_off" msgid="7045417396436552890">"職場モードがオフです。"</string>
- <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"職場モードがオンです。"</string>
- <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"職場モードをオフにしました。"</string>
- <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"職場モードをオンにしました。"</string>
+ <string name="accessibility_quick_settings_work_mode_off" msgid="7045417396436552890">"Work モードがオフです。"</string>
+ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Work モードがオンです。"</string>
+ <string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Work モードをオフにしました。"</string>
+ <string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Work モードをオンにしました。"</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"ディスプレイの明るさ"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5281770593459841889">"2G~3Gデータは一時停止中です"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="1601769736881078016">"4Gデータは一時停止中です"</string>
@@ -294,7 +294,7 @@
<string name="quick_settings_cellular_detail_data_used" msgid="1476810587475761478">"<xliff:g id="DATA_USED">%s</xliff:g>使用中"</string>
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"上限: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"警告: 上限は<xliff:g id="DATA_LIMIT">%s</xliff:g>です"</string>
- <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"職場モード"</string>
+ <string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Work モード"</string>
<string name="recents_empty_message" msgid="8682129509540827999">"ここに最近の画面が表示されます"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"アプリ情報"</string>
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"画面固定"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 9cccec47d7b8..35a6e1bab4e8 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -270,7 +270,7 @@
<string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"ບໍ່ມີເຄືອຂ່າຍ"</string>
<string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi​-Fi ປິດ"</string>
<string name="quick_settings_wifi_detail_empty_text" msgid="269990350383909226">"ບໍ່​ມີ​ເຄືອ​ຂ່າຍ Wi-Fi ຢູ່"</string>
- <string name="quick_settings_cast_title" msgid="7709016546426454729">"ຄາສທ໌"</string>
+ <string name="quick_settings_cast_title" msgid="7709016546426454729">"ການສົ່ງສັນຍານ"</string>
<string name="quick_settings_casting" msgid="6601710681033353316">"​ກຳ​ລັງ​ສົ່ງ​ສັນ​ຍານ"</string>
<string name="quick_settings_cast_device_default_name" msgid="5367253104742382945">"​ອຸ​ປະ​ກອນບໍ່​ມີ​ຊື່"</string>
<string name="quick_settings_cast_device_default_description" msgid="2484573682378634413">"​ພ້ອ​ມ​ສົ່ງ​ສັນ​ຍານ​ແລ້ວ"</string>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 9a22b2c30afd..9a0a0c0566a4 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -213,8 +213,8 @@
<string name="accessibility_quick_settings_hotspot_changed_off" msgid="5004708003447561394">"Tempat liputan mudah alih bergerak dimatikan."</string>
<string name="accessibility_quick_settings_hotspot_changed_on" msgid="2890951609226476206">"Tempat liputan mudah alih bergerak dihidupkan."</string>
<string name="accessibility_casting_turned_off" msgid="1430668982271976172">"Penghantaran skrin dihentikan."</string>
- <string name="accessibility_quick_settings_work_mode_off" msgid="7045417396436552890">"Mod kerja dimatikan."</string>
- <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Mod kerja dihidupkan."</string>
+ <string name="accessibility_quick_settings_work_mode_off" msgid="7045417396436552890">"Mod kerja mati."</string>
+ <string name="accessibility_quick_settings_work_mode_on" msgid="7650588553988014341">"Mod kerja hidup."</string>
<string name="accessibility_quick_settings_work_mode_changed_off" msgid="5605534876107300711">"Mod kerja dimatikan."</string>
<string name="accessibility_quick_settings_work_mode_changed_on" msgid="249840330756998612">"Mod kerja dihidupkan."</string>
<string name="accessibility_brightness" msgid="8003681285547803095">"Kecerahan paparan"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index ae8542ad9d88..16fd9ebba7fd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -154,6 +154,20 @@ public class QSPanel extends FrameLayout implements Tunable {
}
}
+ public void openDetails(String subPanel) {
+ QSTile<?> tile = getTile(subPanel);
+ showDetailAdapter(true, tile.getDetailAdapter(), new int[] {getWidth() / 2, 0});
+ }
+
+ private QSTile<?> getTile(String subPanel) {
+ for (int i = 0; i < mRecords.size(); i++) {
+ if (subPanel.equals(mRecords.get(i).tile.getTileSpec())) {
+ return mRecords.get(i).tile;
+ }
+ }
+ return mHost.createTile(subPanel);
+ }
+
protected void createCustomizePanel() {
mCustomizePanel = (QSCustomizer) LayoutInflater.from(mContext)
.inflate(R.layout.qs_customize_panel, null);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index 60bedaecdf2d..512effab047a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -93,7 +93,8 @@ public class Task {
public TaskKey key;
public TaskGrouping group;
- public int taskAffiliation;
+ // The taskAffiliationId is the task id of the parent task or itself if it is not affiliated with any task
+ public int taskAffiliationId;
public int taskAffiliationColor;
public boolean isLaunchTarget;
public Drawable applicationIcon;
@@ -123,7 +124,7 @@ public class Task {
boolean isInAffiliationGroup = (taskAffiliation != key.id);
boolean hasAffiliationGroupColor = isInAffiliationGroup && (taskAffiliationColor != 0);
this.key = key;
- this.taskAffiliation = taskAffiliation;
+ this.taskAffiliationId = taskAffiliation;
this.taskAffiliationColor = taskAffiliationColor;
this.activityLabel = activityTitle;
this.contentDescription = contentDescription;
@@ -142,7 +143,7 @@ public class Task {
/** Copies the other task. */
public void copyFrom(Task o) {
this.key = o.key;
- this.taskAffiliation = o.taskAffiliation;
+ this.taskAffiliationId = o.taskAffiliationId;
this.taskAffiliationColor = o.taskAffiliationColor;
this.activityLabel = o.activityLabel;
this.contentDescription = o.contentDescription;
@@ -206,6 +207,13 @@ public class Task {
}
}
+ /**
+ * Returns whether this task is affiliated with another task.
+ */
+ public boolean isAffiliatedTask() {
+ return key.id != taskAffiliationId;
+ }
+
@Override
public boolean equals(Object o) {
// Check that the id matches
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 7a9839365498..13ab3920065e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -23,6 +23,7 @@ import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
+import android.util.SparseArray;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsDebugFlags;
@@ -50,7 +51,7 @@ import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
*/
interface TaskFilter {
/** Returns whether the filter accepts the specified task */
- public boolean acceptTask(Task t, int index);
+ public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index);
}
/**
@@ -157,10 +158,17 @@ class FilteredTaskList {
private void updateFilteredTasks() {
mFilteredTasks.clear();
if (mFilter != null) {
+ // Create a sparse array from task id to Task
+ SparseArray<Task> taskIdMap = new SparseArray<>();
int taskCount = mTasks.size();
for (int i = 0; i < taskCount; i++) {
Task t = mTasks.get(i);
- if (mFilter.acceptTask(t, i)) {
+ taskIdMap.put(t.key.id, t);
+ }
+
+ for (int i = 0; i < taskCount; i++) {
+ Task t = mTasks.get(i);
+ if (mFilter.acceptTask(taskIdMap, t, i)) {
mFilteredTasks.add(t);
}
}
@@ -318,13 +326,29 @@ public class TaskStack {
// Ensure that we only show non-docked tasks
mStackTaskList.setFilter(new TaskFilter() {
@Override
- public boolean acceptTask(Task t, int index) {
+ public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index) {
+ if (t.isAffiliatedTask()) {
+ // If this task is affiliated with another parent in the stack, then the historical state of this
+ // task depends on the state of the parent task
+ Task parentTask = taskIdMap.get(t.taskAffiliationId);
+ if (parentTask != null) {
+ t = parentTask;
+ }
+ }
return !t.isHistorical && !SystemServicesProxy.isDockedStack(t.key.stackId);
}
});
mHistoryTaskList.setFilter(new TaskFilter() {
@Override
- public boolean acceptTask(Task t, int index) {
+ public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index) {
+ if (t.isAffiliatedTask()) {
+ // If this task is affiliated with another parent in the stack, then the historical state of this
+ // task depends on the state of the parent task
+ Task parentTask = taskIdMap.get(t.taskAffiliationId);
+ if (parentTask != null) {
+ t = parentTask;
+ }
+ }
return t.isHistorical && !SystemServicesProxy.isDockedStack(t.key.stackId);
}
});
@@ -585,8 +609,8 @@ public class TaskStack {
taskGrouping2.latestActiveTimeInGroup);
}
});
- // Sort group tasks by increasing firstActiveTime of the task, and also build a new list of
- // tasks
+ // Sort group tasks by increasing firstActiveTime of the task, and also build a new list
+ // of tasks
int taskIndex = 0;
int groupCount = mGroups.size();
for (int i = 0; i < groupCount; i++) {
@@ -607,13 +631,13 @@ public class TaskStack {
mStackTaskList.set(tasks);
} else {
// Create the task groups
- HashMap<Task.TaskKey, Task> tasksMap = new HashMap<Task.TaskKey, Task>();
+ HashMap<Task.TaskKey, Task> tasksMap = new HashMap<>();
ArrayList<Task> tasks = mStackTaskList.getTasks();
int taskCount = tasks.size();
for (int i = 0; i < taskCount; i++) {
Task t = tasks.get(i);
TaskGrouping group;
- int affiliation = t.taskAffiliation > 0 ? t.taskAffiliation :
+ int affiliation = t.taskAffiliationId > 0 ? t.taskAffiliationId :
IndividualTaskIdOffset + t.key.id;
if (mAffinitiesGroups.containsKey(affiliation)) {
group = getGroupWithAffiliation(affiliation);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 10d4a965852f..deedae0f6a80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -91,7 +91,7 @@ public class CommandQueue extends IStatusBar.Stub {
public void disable(int state1, int state2, boolean animate);
public void animateExpandNotificationsPanel();
public void animateCollapsePanels(int flags);
- public void animateExpandSettingsPanel();
+ public void animateExpandSettingsPanel(String obj);
public void setSystemUiVisibility(int vis, int mask);
public void topAppWindowChanged(boolean visible);
public void setImeWindowStatus(IBinder token, int vis, int backDisposition,
@@ -157,10 +157,10 @@ public class CommandQueue extends IStatusBar.Stub {
}
}
- public void animateExpandSettingsPanel() {
+ public void animateExpandSettingsPanel(String subPanel) {
synchronized (mList) {
mHandler.removeMessages(MSG_EXPAND_SETTINGS);
- mHandler.sendEmptyMessage(MSG_EXPAND_SETTINGS);
+ mHandler.obtainMessage(MSG_EXPAND_SETTINGS, subPanel).sendToTarget();
}
}
@@ -353,7 +353,7 @@ public class CommandQueue extends IStatusBar.Stub {
mCallbacks.animateCollapsePanels(0);
break;
case MSG_EXPAND_SETTINGS:
- mCallbacks.animateExpandSettingsPanel();
+ mCallbacks.animateExpandSettingsPanel((String) msg.obj);
break;
case MSG_SET_SYSTEMUI_VISIBILITY:
mCallbacks.setSystemUiVisibility(msg.arg1, msg.arg2);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 76b8223ba778..8f7c95e1b9af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -2162,7 +2162,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
animateExpandNotificationsPanel();
break;
case MSG_OPEN_SETTINGS_PANEL:
- animateExpandSettingsPanel();
+ animateExpandSettingsPanel((String) m.obj);
break;
case MSG_CLOSE_PANELS:
animateCollapsePanels();
@@ -2305,7 +2305,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
@Override
- public void animateExpandSettingsPanel() {
+ public void animateExpandSettingsPanel(String subPanel) {
if (SPEW) Log.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
if (!panelsEnabled()) {
return;
@@ -2314,6 +2314,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// Settings are not available in setup
if (!mUserSetup) return;
+
+ if (subPanel != null) {
+ mQSPanel.openDetails(subPanel);
+ }
mNotificationPanel.expandWithQs();
if (false) postStartTracing();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 856a774fdcce..44b41c55b4de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -135,7 +135,7 @@ public class TvStatusBar extends BaseStatusBar {
}
@Override
- public void animateExpandSettingsPanel() {
+ public void animateExpandSettingsPanel(String subPanel) {
}
@Override
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 22d30dfb499f..be1fd58fce3b 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5390,7 +5390,7 @@ public final class ActivityManagerService extends ActivityManagerNative
return;
}
killPackageProcessesLocked(packageName, appId, userId,
- ProcessList.SERVICE_ADJ, false, true, true, false, "kill background");
+ ProcessList.SERVICE_ADJ, false, true, true, false, true, "kill background");
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -5691,7 +5691,7 @@ public final class ActivityManagerService extends ActivityManagerNative
private final boolean killPackageProcessesLocked(String packageName, int appId,
int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
- boolean doit, boolean evenPersistent, String reason) {
+ boolean doit, boolean evenPersistent, boolean killPackageApp, String reason) {
ArrayList<ProcessRecord> procs = new ArrayList<>();
// Remove all processes this package may have touched: all with the
@@ -5740,7 +5740,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (userId != UserHandle.USER_ALL && app.userId != userId) {
continue;
}
- if (!app.pkgList.containsKey(packageName) && !isDep) {
+ if ((!killPackageApp || !app.pkgList.containsKey(packageName)) && !isDep) {
continue;
}
}
@@ -5906,7 +5906,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
boolean didSomething = killPackageProcessesLocked(packageName, appId, userId,
- ProcessList.INVALID_ADJ, callerWillRestart, true, doit, evenPersistent,
+ ProcessList.INVALID_ADJ, callerWillRestart, true, doit, evenPersistent, true,
packageName == null ? ("stop user " + userId) : ("stop " + packageName));
if (mStackSupervisor.finishDisabledPackageActivitiesLocked(
@@ -11819,7 +11819,7 @@ public final class ActivityManagerService extends ActivityManagerNative
final long identity = Binder.clearCallingIdentity();
try {
killPackageProcessesLocked(null, appId, userId,
- ProcessList.PERSISTENT_PROC_ADJ, false, true, true, true,
+ ProcessList.PERSISTENT_PROC_ADJ, false, true, true, true, true,
reason != null ? reason : "kill uid");
} finally {
Binder.restoreCallingIdentity(identity);
@@ -20777,4 +20777,35 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
}
+
+ /**
+ * Kill processes for the user with id userId and that depend on the package named packageName
+ */
+ @Override
+ public void killPackageDependents(String packageName, int userId) {
+ enforceCallingPermission(android.Manifest.permission.KILL_UID, "killPackageDependents()");
+ if (packageName == null) {
+ throw new NullPointerException("Cannot kill the dependents of a package without its name.");
+ }
+
+ long callingId = Binder.clearCallingIdentity();
+ IPackageManager pm = AppGlobals.getPackageManager();
+ int pkgUid = -1;
+ try {
+ pkgUid = pm.getPackageUid(packageName, userId);
+ } catch (RemoteException e) {
+ }
+ if (pkgUid == -1) {
+ throw new IllegalArgumentException("Cannot kill dependents of non-existing package " + packageName);
+ }
+ try {
+ synchronized(this) {
+ killPackageProcessesLocked(packageName, UserHandle.getAppId(pkgUid), userId,
+ ProcessList.FOREGROUND_APP_ADJ, false, true, true, false, false,
+ "dep: " + packageName);
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingId);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 07343a9fd2f1..e6a48a8cd87d 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -880,6 +880,9 @@ public class NotificationManagerService extends SystemService {
@Override
void onZenModeChanged() {
sendRegisteredOnlyBroadcast(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED);
+ getContext().sendBroadcastAsUser(
+ new Intent(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED_INTERNAL),
+ UserHandle.ALL, android.Manifest.permission.MANAGE_NOTIFICATIONS);
synchronized(mNotificationList) {
updateInterruptionFilterLocked();
}
@@ -3683,7 +3686,7 @@ public class NotificationManagerService extends SystemService {
for (int i = 0; i < tokens.length; i++) {
String token = tokens[i];
if (token != null) {
- token.trim();
+ token = token.trim();
}
if (TextUtils.isEmpty(token)) {
continue;
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 3c891dff5b1d..6030bab6db64 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -564,6 +564,7 @@ public class ZenModeHelper {
private boolean evaluateZenMode(String reason, boolean setRingerMode) {
if (DEBUG) Log.d(TAG, "evaluateZenMode");
+ final int zenBefore = mZenMode;
final int zen = computeZenMode();
ZenLog.traceSetZenMode(zen, reason);
mZenMode = zen;
@@ -573,7 +574,7 @@ public class ZenModeHelper {
applyZenToRingerMode();
}
applyRestrictions();
- if (zen != mZenMode) {
+ if (zen != zenBefore) {
mHandler.postDispatchOnZenModeChanged();
}
return true;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 19b03d5e56cd..fc271704a1ec 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -216,12 +216,12 @@ public class StatusBarManagerService extends IStatusBarService.Stub {
}
@Override
- public void expandSettingsPanel() {
+ public void expandSettingsPanel(String subPanel) {
enforceExpandStatusBar();
if (mBar != null) {
try {
- mBar.animateExpandSettingsPanel();
+ mBar.animateExpandSettingsPanel(subPanel);
} catch (RemoteException ex) {
}
}
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateService.java b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
index 97713fc2407a..7be0eadf895e 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateService.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateService.java
@@ -16,18 +16,35 @@
package com.android.server.webkit;
+import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.Signature;
import android.os.Binder;
import android.os.Process;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.provider.Settings.Secure;
+import android.util.AndroidRuntimeException;
import android.util.Slog;
import android.webkit.IWebViewUpdateService;
+import android.webkit.WebViewProviderInfo;
+import android.webkit.WebViewProviderResponse;
import android.webkit.WebViewFactory;
import com.android.server.SystemService;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
/**
* Private service to wait for the updatable WebView to be ready for use.
* @hide
@@ -35,12 +52,23 @@ import com.android.server.SystemService;
public class WebViewUpdateService extends SystemService {
private static final String TAG = "WebViewUpdateService";
- private static final int WAIT_TIMEOUT_MS = 5000; // Same as KEY_DISPATCHING_TIMEOUT.
+ private static final int WAIT_TIMEOUT_MS = 4500; // KEY_DISPATCHING_TIMEOUT is 5000.
+
+ // Keeps track of the number of running relro creations
+ private int mNumRelroCreationsStarted = 0;
+ private int mNumRelroCreationsFinished = 0;
+ // Implies that we need to rerun relro creation because we are using an out-of-date package
+ private boolean mWebViewPackageDirty = false;
+ // Set to true when the current provider is being replaced
+ private boolean mCurrentProviderBeingReplaced = false;
+ private boolean mAnyWebViewInstalled = false;
- private boolean mRelroReady32Bit = false;
- private boolean mRelroReady64Bit = false;
+ private int NUMBER_OF_RELROS_UNKNOWN = Integer.MAX_VALUE;
- private String oldWebViewPackageName = null;
+ // The WebView package currently in use (or the one we are preparing).
+ private PackageInfo mCurrentWebViewPackage = null;
+ // The WebView providers that are currently available.
+ private WebViewProviderInfo[] mCurrentValidWebViewPackages = null;
private BroadcastReceiver mWebViewUpdatedReceiver;
@@ -53,28 +81,69 @@ public class WebViewUpdateService extends SystemService {
mWebViewUpdatedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
-
- // When a package is replaced we will receive two intents, one representing the
- // removal of the old package and one representing the addition of the new
- // package. We here ignore the intent representing the removed package to make
- // sure we don't change WebView provider twice.
+ // When a package is replaced we will receive two intents, one representing
+ // the removal of the old package and one representing the addition of the
+ // new package.
+ // In the case where we receive an intent to remove the old version of the
+ // package that is being replaced we set a flag here and early-out so that we
+ // don't change provider while replacing the current package (we will instead
+ // change provider when the new version of the package is being installed).
if (intent.getAction().equals(Intent.ACTION_PACKAGE_REMOVED)
- && intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) {
+ && intent.getExtras().getBoolean(Intent.EXTRA_REPLACING)) {
+ synchronized(this) {
+ if (mCurrentWebViewPackage == null) return;
+
+ String webViewPackage = "package:" + mCurrentWebViewPackage.packageName;
+ if (webViewPackage.equals(intent.getDataString()))
+ mCurrentProviderBeingReplaced = true;
+ }
+
return;
}
- for (String packageName : WebViewFactory.getWebViewPackageNames()) {
- String webviewPackage = "package:" + packageName;
+ for (WebViewProviderInfo provider : WebViewFactory.getWebViewPackages()) {
+ String webviewPackage = "package:" + provider.packageName;
if (webviewPackage.equals(intent.getDataString())) {
- String usedPackageName =
- WebViewFactory.findPreferredWebViewPackage().packageName;
- // Only trigger update actions if the updated package is the one that
- // will be used, or the one that was in use before the update.
- if (packageName.equals(usedPackageName) ||
- packageName.equals(oldWebViewPackageName)) {
- onWebViewUpdateInstalled();
- oldWebViewPackageName = usedPackageName;
+ boolean updateWebView = false;
+ boolean removedOldPackage = false;
+ String oldProviderName = null;
+ PackageInfo newPackage = null;
+ synchronized(WebViewUpdateService.this) {
+ try {
+ updateValidWebViewPackages();
+ newPackage = findPreferredWebViewPackage();
+ if (mCurrentWebViewPackage != null)
+ oldProviderName = mCurrentWebViewPackage.packageName;
+ // Only trigger update actions if the updated package is the one
+ // that will be used, or the one that was in use before the
+ // update, or if we haven't seen a valid WebView package before.
+ updateWebView =
+ provider.packageName.equals(newPackage.packageName)
+ || provider.packageName.equals(oldProviderName)
+ || mCurrentWebViewPackage == null;
+ // We removed the old package if we received an intent to remove
+ // or replace the old package.
+ removedOldPackage =
+ provider.packageName.equals(oldProviderName);
+ if (updateWebView) {
+ onWebViewProviderChanged(newPackage);
+ }
+ } catch (WebViewFactory.MissingWebViewPackageException e) {
+ Slog.e(TAG, "Could not find valid WebView package to create " +
+ "relro with " + e);
+ }
+ }
+ if(updateWebView && !removedOldPackage && oldProviderName != null) {
+ // If the provider change is the result of adding or replacing a
+ // package that was not the previous provider then we must kill
+ // packages dependent on the old package ourselves. The framework
+ // only kills dependents of packages that are being removed.
+ try {
+ ActivityManagerNative.getDefault().killPackageDependents(
+ oldProviderName, getContext().getUserId());
+ } catch (RemoteException e) {
+ }
}
return;
}
@@ -90,14 +159,182 @@ public class WebViewUpdateService extends SystemService {
publishBinderService("webviewupdate", new BinderService());
}
- private void onWebViewUpdateInstalled() {
- Slog.d(TAG, "WebView Package updated!");
+ /**
+ * Perform any WebView loading preparations that must happen at boot from the system server,
+ * after the package manager has started or after an update to the webview is installed.
+ * This must be called in the system server.
+ * Currently, this means spawning the child processes which will create the relro files.
+ */
+ public void prepareWebViewInSystemServer() {
+ try {
+ synchronized(this) {
+ updateValidWebViewPackages();
+ mCurrentWebViewPackage = findPreferredWebViewPackage();
+ onWebViewProviderChanged(mCurrentWebViewPackage);
+ }
+ } catch (Throwable t) {
+ // Log and discard errors at this stage as we must not crash the system server.
+ Slog.e(TAG, "error preparing webview provider from system server", t);
+ }
+ }
+
- synchronized (this) {
- mRelroReady32Bit = false;
- mRelroReady64Bit = false;
+ /**
+ * Change WebView provider and provider setting and kill packages using the old provider.
+ */
+ private void changeProviderAndSetting(String newProviderName) {
+ PackageInfo oldPackage = null;
+ PackageInfo newPackage = null;
+ synchronized(this) {
+ oldPackage = mCurrentWebViewPackage;
+ updateUserSetting(newProviderName);
+
+ try {
+ newPackage = findPreferredWebViewPackage();
+ if (oldPackage != null && newPackage.packageName.equals(oldPackage.packageName)) {
+ // If we don't perform the user change, revert the settings change.
+ updateUserSetting(newPackage.packageName);
+ return;
+ }
+ } catch (WebViewFactory.MissingWebViewPackageException e) {
+ Slog.e(TAG, "Tried to change WebView provider but failed to fetch WebView package "
+ + e);
+ // If we don't perform the user change but don't have an installed WebView package,
+ // we will have changed the setting and it will be used when a package is available.
+ return;
+ }
+ onWebViewProviderChanged(newPackage);
+ }
+ // Kill apps using the old provider
+ try {
+ if (oldPackage != null) {
+ ActivityManagerNative.getDefault().killPackageDependents(
+ oldPackage.packageName, getContext().getUserId());
+ }
+ } catch (RemoteException e) {
+ }
+ return;
+ }
+
+ /**
+ * This is called when we change WebView provider, either when the current provider is updated
+ * or a new provider is chosen / takes precedence.
+ */
+ private void onWebViewProviderChanged(PackageInfo newPackage) {
+ synchronized(this) {
+ mAnyWebViewInstalled = true;
+ // If we have changed provider then the replacement of the old provider is
+ // irrelevant - we can only have chosen a new provider if its package is available.
+ mCurrentProviderBeingReplaced = false;
+ if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
+ mCurrentWebViewPackage = newPackage;
+ updateUserSetting(newPackage.packageName);
+
+ // The relro creations might 'finish' (not start at all) before
+ // WebViewFactory.onWebViewProviderChanged which means we might not know the number
+ // of started creations before they finish.
+ mNumRelroCreationsStarted = NUMBER_OF_RELROS_UNKNOWN;
+ mNumRelroCreationsFinished = 0;
+ mNumRelroCreationsStarted = WebViewFactory.onWebViewProviderChanged(newPackage);
+ // If the relro creations finish before we know the number of started creations we
+ // will have to do any cleanup/notifying here.
+ checkIfRelrosDoneLocked();
+ } else {
+ mWebViewPackageDirty = true;
+ }
+ }
+ }
+
+ /**
+ * Updates the currently valid WebView provider packages.
+ * Should be used when a provider has been installed or removed.
+ * @hide
+ * */
+ private void updateValidWebViewPackages() {
+ List<WebViewProviderInfo> webViewProviders =
+ new ArrayList<WebViewProviderInfo>(Arrays.asList(WebViewFactory.getWebViewPackages()));
+ Iterator<WebViewProviderInfo> it = webViewProviders.iterator();
+ // remove non-valid packages
+ while(it.hasNext()) {
+ WebViewProviderInfo current = it.next();
+ if (!current.isValidProvider())
+ it.remove();
+ }
+ synchronized(this) {
+ mCurrentValidWebViewPackages =
+ webViewProviders.toArray(new WebViewProviderInfo[webViewProviders.size()]);
+ }
+ }
+
+ private static String getUserChosenWebViewProvider() {
+ return Settings.Secure.getString(AppGlobals.getInitialApplication().getContentResolver(),
+ Settings.Secure.WEBVIEW_PROVIDER);
+ }
+
+ private void updateUserSetting(String newProviderName) {
+ Settings.Secure.putString(getContext().getContentResolver(),
+ Settings.Secure.WEBVIEW_PROVIDER,
+ newProviderName == null ? "" : newProviderName);
+ }
+
+ /**
+ * Returns either the package info of the WebView provider determined in the following way:
+ * If the user has chosen a provider then use that if it is valid,
+ * otherwise use the first package in the webview priority list that is valid.
+ *
+ * @hide
+ */
+ private PackageInfo findPreferredWebViewPackage() {
+ WebViewProviderInfo[] providers = mCurrentValidWebViewPackages;
+
+ String userChosenProvider = getUserChosenWebViewProvider();
+
+ // If the user has chosen provider, use that
+ for (WebViewProviderInfo provider : providers) {
+ if (provider.packageName.equals(userChosenProvider)) {
+ return provider.getPackageInfo();
+ }
+ }
+
+ // User did not choose, or the choice failed, use the most stable provider available
+ for (WebViewProviderInfo provider : providers) {
+ return provider.getPackageInfo();
+ }
+ mAnyWebViewInstalled = false;
+ throw new WebViewFactory.MissingWebViewPackageException(
+ "Could not find a loadable WebView package");
+ }
+
+ /**
+ * Returns whether WebView is ready and is not going to go through its preparation phase again
+ * directly.
+ */
+ private boolean webViewIsReadyLocked() {
+ return !mWebViewPackageDirty
+ && (mNumRelroCreationsStarted == mNumRelroCreationsFinished)
+ && !mCurrentProviderBeingReplaced
+ // The current package might be replaced though we haven't received an intent declaring
+ // this yet, the following flag makes anyone loading WebView to wait in this case.
+ && mAnyWebViewInstalled;
+ }
+
+ private void checkIfRelrosDoneLocked() {
+ if (mNumRelroCreationsStarted == mNumRelroCreationsFinished) {
+ if (mWebViewPackageDirty) {
+ mWebViewPackageDirty = false;
+ // If we have changed provider since we started the relro creation we need to
+ // redo the whole process using the new package instead.
+ // Though, if the current provider package is being replaced we don't want to change
+ // provider here since we will perform the change either when the package is added
+ // again or when we switch to another provider (whichever comes first).
+ if (!mCurrentProviderBeingReplaced) {
+ PackageInfo newPackage = findPreferredWebViewPackage();
+ onWebViewProviderChanged(newPackage);
+ }
+ } else {
+ this.notifyAll();
+ }
}
- WebViewFactory.onWebViewUpdateInstalled();
}
private class BinderService extends IWebViewUpdateService.Stub {
@@ -108,7 +345,7 @@ public class WebViewUpdateService extends SystemService {
* crashed.
*/
@Override // Binder call
- public void notifyRelroCreationCompleted(boolean is64Bit, boolean success) {
+ public void notifyRelroCreationCompleted() {
// Verify that the caller is either the shared relro process (nominal case) or the
// system server (only in the case the relro process crashes and we get here via the
// crashHandler).
@@ -118,20 +355,17 @@ public class WebViewUpdateService extends SystemService {
}
synchronized (WebViewUpdateService.this) {
- if (is64Bit) {
- mRelroReady64Bit = true;
- } else {
- mRelroReady32Bit = true;
- }
- WebViewUpdateService.this.notifyAll();
+ mNumRelroCreationsFinished++;
+ checkIfRelrosDoneLocked();
}
}
/**
* WebViewFactory calls this to block WebView loading until the relro file is created.
+ * Returns the WebView provider for which we create relro files.
*/
@Override // Binder call
- public void waitForRelroCreationCompleted(boolean is64Bit) {
+ public WebViewProviderResponse waitForAndGetProvider() {
// The WebViewUpdateService depends on the prepareWebViewInSystemServer call, which
// happens later (during the PHASE_ACTIVITY_MANAGER_READY) in SystemServer.java. If
// another service there tries to bring up a WebView in the between, the wait below
@@ -140,21 +374,74 @@ public class WebViewUpdateService extends SystemService {
throw new IllegalStateException("Cannot create a WebView from the SystemServer");
}
+ PackageInfo webViewPackage = null;
final long NS_PER_MS = 1000000;
final long timeoutTimeMs = System.nanoTime() / NS_PER_MS + WAIT_TIMEOUT_MS;
- boolean relroReady = (is64Bit ? mRelroReady64Bit : mRelroReady32Bit);
+ boolean webViewReady = false;
+ int webViewStatus = WebViewFactory.LIBLOAD_SUCCESS;
synchronized (WebViewUpdateService.this) {
- while (!relroReady) {
+ webViewReady = WebViewUpdateService.this.webViewIsReadyLocked();
+ while (!webViewReady) {
final long timeNowMs = System.nanoTime() / NS_PER_MS;
if (timeNowMs >= timeoutTimeMs) break;
try {
WebViewUpdateService.this.wait(timeoutTimeMs - timeNowMs);
} catch (InterruptedException e) {}
- relroReady = (is64Bit ? mRelroReady64Bit : mRelroReady32Bit);
+ webViewReady = WebViewUpdateService.this.webViewIsReadyLocked();
+ }
+ // Make sure we return the provider that was used to create the relro file
+ webViewPackage = WebViewUpdateService.this.mCurrentWebViewPackage;
+ if (webViewReady) {
+ } else if (mCurrentProviderBeingReplaced) {
+ // It is important that we check this flag before the one representing WebView
+ // being installed, otherwise we might think there is no WebView though the
+ // current one is just being replaced.
+ webViewStatus = WebViewFactory.LIBLOAD_WEBVIEW_BEING_REPLACED;
+ } else if (!mAnyWebViewInstalled) {
+ webViewStatus = WebViewFactory.LIBLOAD_FAILED_LISTING_WEBVIEW_PACKAGES;
+ } else {
+ // Either the current relro creation isn't done yet, or the new relro creatioin
+ // hasn't kicked off yet (the last relro creation used an out-of-date WebView).
+ webViewStatus = WebViewFactory.LIBLOAD_FAILED_WAITING_FOR_RELRO;
}
}
- if (!relroReady) Slog.w(TAG, "creating relro file timed out");
+ if (!webViewReady) Slog.w(TAG, "creating relro file timed out");
+ return new WebViewProviderResponse(webViewPackage, webViewStatus);
+ }
+
+ /**
+ * This is called from DeveloperSettings when the user changes WebView provider.
+ */
+ @Override // Binder call
+ public void changeProviderAndSetting(String newProvider) {
+ if (getContext().checkCallingPermission(
+ android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: changeProviderAndSetting() from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid()
+ + " requires " + android.Manifest.permission.WRITE_SECURE_SETTINGS;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+
+ WebViewUpdateService.this.changeProviderAndSetting(newProvider);
}
- }
+ @Override // Binder call
+ public WebViewProviderInfo[] getValidWebViewPackages() {
+ synchronized(WebViewUpdateService.this) {
+ return mCurrentValidWebViewPackages;
+ }
+ }
+
+ @Override // Binder call
+ public String getCurrentWebViewPackageName() {
+ synchronized(WebViewUpdateService.this) {
+ if (WebViewUpdateService.this.mCurrentWebViewPackage == null)
+ return null;
+ return WebViewUpdateService.this.mCurrentWebViewPackage.packageName;
+ }
+ }
+ }
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 2f33d7cdd3fe..189ed332abef 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -150,6 +150,7 @@ public final class SystemServer {
// TODO: remove all of these references by improving dependency resolution and boot phases
private PowerManagerService mPowerManagerService;
private ActivityManagerService mActivityManagerService;
+ private WebViewUpdateService mWebViewUpdateService;
private DisplayManagerService mDisplayManagerService;
private PackageManagerService mPackageManagerService;
private PackageManager mPackageManager;
@@ -409,7 +410,7 @@ public final class SystemServer {
LocalServices.getService(UsageStatsManagerInternal.class));
// Tracks whether the updatable WebView is in a ready state and watches for update installs.
- mSystemServiceManager.startService(WebViewUpdateService.class);
+ mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
}
/**
@@ -1180,7 +1181,7 @@ public final class SystemServer {
Slog.i(TAG, "WebViewFactory preparation");
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "WebViewFactoryPreparation");
- WebViewFactory.prepareWebViewInSystemServer();
+ mWebViewUpdateService.prepareWebViewInSystemServer();
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartSystemUI");