summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt5
-rw-r--r--core/java/android/app/ZygotePreload.java42
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java6
-rw-r--r--core/java/android/content/pm/PackageParser.java3
-rw-r--r--core/java/android/net/NetworkStack.java2
-rw-r--r--core/java/com/android/internal/os/AppZygoteInit.java39
-rw-r--r--core/res/res/values/attrs_manifest.xml21
-rw-r--r--core/res/res/values/public.xml1
-rw-r--r--packages/CaptivePortalLogin/Android.bp27
-rw-r--r--packages/CaptivePortalLogin/Android.mk14
-rw-r--r--packages/CaptivePortalLogin/AndroidManifest.xml5
-rw-r--r--packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml28
-rw-r--r--packages/CaptivePortalLogin/res/layout/ssl_warning.xml11
-rw-r--r--packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java71
-rw-r--r--packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java6
-rw-r--r--packages/NetworkStack/src/com/android/server/util/PermissionUtil.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java22
-rw-r--r--proto/Android.bp21
19 files changed, 245 insertions, 95 deletions
diff --git a/api/current.txt b/api/current.txt
index 2f4f2c35acc2..83de0b17181f 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -1622,6 +1622,7 @@ package android {
field @Deprecated public static final int yearListSelectorColor = 16843930; // 0x101049a
field public static final int yesNoPreferenceStyle = 16842896; // 0x1010090
field public static final int zAdjustment = 16843201; // 0x10101c1
+ field public static final int zygotePreloadName = 16844195; // 0x10105a3
}
public static final class R.bool {
@@ -6483,6 +6484,10 @@ package android.app {
method public void onColorsChanged(android.app.WallpaperColors, int);
}
+ public interface ZygotePreload {
+ method public void doPreload(android.content.pm.ApplicationInfo);
+ }
+
}
package android.app.admin {
diff --git a/core/java/android/app/ZygotePreload.java b/core/java/android/app/ZygotePreload.java
new file mode 100644
index 000000000000..a295af352c0a
--- /dev/null
+++ b/core/java/android/app/ZygotePreload.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 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.app;
+
+import android.content.pm.ApplicationInfo;
+
+/**
+ * This is the interface to be implemented for the class that is specified by the
+ * {@link android.R.styleable#AndroidManifestApplication_zygotePreloadName
+ * android:zygotePreloadName} of the <application> tag.
+ *
+ * It is responsible for preloading application code and data, that will be shared by all
+ * isolated services that have the
+ * {@link android.R.styleable#AndroidManifestService_useAppZygote android:useAppZygote} attribute
+ * of the &lt;service&gt; tag set to <code>true</code>.
+ *
+ * Note that this implementations of this class must provide a default constructor with no
+ * arguments.
+ */
+public interface ZygotePreload {
+ /**
+ * This method is called once every time the Application Zygote is started. It is normally
+ * started the first time an isolated service that uses it is started. The Application Zygote
+ * will be stopped when all isolated services that use it are stopped.
+ *
+ * @param appInfo The ApplicationInfo object belonging to the application
+ */
+ void doPreload(ApplicationInfo appInfo);
+}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 5d6d1444eaf3..1358bc25a07b 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1192,6 +1192,9 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
/** @hide */
public boolean hiddenUntilInstalled;
+ /** @hide */
+ public String zygotePreloadName;
+
/**
* Represents the default policy. The actual policy used will depend on other properties of
* the application, e.g. the target SDK version.
@@ -1533,6 +1536,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
compileSdkVersionCodename = orig.compileSdkVersionCodename;
mHiddenApiPolicy = orig.mHiddenApiPolicy;
hiddenUntilInstalled = orig.hiddenUntilInstalled;
+ zygotePreloadName = orig.zygotePreloadName;
}
public String toString() {
@@ -1609,6 +1613,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
dest.writeString(appComponentFactory);
dest.writeInt(mHiddenApiPolicy);
dest.writeInt(hiddenUntilInstalled ? 1 : 0);
+ dest.writeString(zygotePreloadName);
}
public static final Parcelable.Creator<ApplicationInfo> CREATOR
@@ -1682,6 +1687,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
appComponentFactory = source.readString();
mHiddenApiPolicy = source.readInt();
hiddenUntilInstalled = source.readInt() != 0;
+ zygotePreloadName = source.readString();
}
/**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index eb59cfc0fc4b..1fab443629a4 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3907,6 +3907,9 @@ public class PackageParser {
outError[0] = "Invalid class loader name: " + ai.classLoaderName;
}
+ ai.zygotePreloadName = sa.getString(
+ com.android.internal.R.styleable.AndroidManifestApplication_zygotePreloadName);
+
sa.recycle();
if (outError[0] != null) {
diff --git a/core/java/android/net/NetworkStack.java b/core/java/android/net/NetworkStack.java
index ac6bff029e8c..d21e674719df 100644
--- a/core/java/android/net/NetworkStack.java
+++ b/core/java/android/net/NetworkStack.java
@@ -223,7 +223,7 @@ public class NetworkStack {
private void requestConnector(@NonNull NetworkStackCallback request) {
// TODO: PID check.
final int caller = Binder.getCallingUid();
- if (caller != Process.SYSTEM_UID && caller != Process.BLUETOOTH_UID) {
+ if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
// Don't even attempt to obtain the connector and give a nice error message
throw new SecurityException(
"Only the system server should try to bind to the network stack.");
diff --git a/core/java/com/android/internal/os/AppZygoteInit.java b/core/java/com/android/internal/os/AppZygoteInit.java
index 6ba584d76ee8..0e83e41a7423 100644
--- a/core/java/com/android/internal/os/AppZygoteInit.java
+++ b/core/java/com/android/internal/os/AppZygoteInit.java
@@ -17,13 +17,15 @@
package com.android.internal.os;
import android.app.LoadedApk;
+import android.app.ZygotePreload;
+import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
import android.net.LocalSocket;
import android.util.Log;
import java.io.DataOutputStream;
import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
@@ -76,20 +78,29 @@ class AppZygoteInit {
Zygote.allowAppFilesAcrossFork(appInfo);
- Class<?> cl;
- Method m;
- try {
- cl = Class.forName(appInfo.packageName + ".ZygotePreload", true, loader);
- m = cl.getMethod("doPreload");
- m.setAccessible(true);
- m.invoke(null);
- } catch (ClassNotFoundException e) {
- // Don't treat this as an error since an app may not want to do any preloads
- Log.w(TAG, "No ZygotePreload class found for " + appInfo.packageName);
- } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- Log.e(TAG, "AppZygote application preload failed for "
- + appInfo.packageName, e);
+ if (appInfo.zygotePreloadName != null) {
+ Class<?> cl;
+ Method m;
+ try {
+ ComponentName preloadName = ComponentName.createRelative(appInfo.packageName,
+ appInfo.zygotePreloadName);
+ cl = Class.forName(preloadName.getClassName(), true, loader);
+ if (!ZygotePreload.class.isAssignableFrom(cl)) {
+ Log.e(TAG, preloadName.getClassName() + " does not implement "
+ + ZygotePreload.class.getName());
+ } else {
+ Constructor<?> ctor = cl.getConstructor();
+ ZygotePreload preloadObject = (ZygotePreload) ctor.newInstance();
+ preloadObject.doPreload(appInfo);
+ }
+ } catch (ReflectiveOperationException e) {
+ Log.e(TAG, "AppZygote application preload failed for "
+ + appInfo.zygotePreloadName, e);
+ }
+ } else {
+ Log.i(TAG, "No zygotePreloadName attribute specified.");
}
+
try {
DataOutputStream socketOut = getSocketOutputStream();
socketOut.writeInt(loader != null ? 1 : 0);
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 0abe456c82f9..1eece03e3023 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1116,6 +1116,15 @@
-->
<attr name="classLoader" format="string" />
+ <!-- Name of the class that gets invoked for preloading application code, when starting an
+ {@link android.R.attr#isolatedProcess} service that has
+ {@link android.R.attr#useAppZygote} set to <code>true</code>. This is a fully
+ qualified class name (for example, com.mycompany.myapp.MyZygotePreload); as a
+ short-hand if the first character of the class is a period then it is appended
+ to your package name. The class must implement the {@link android.app.ZygotePreload}
+ interface. -->
+ <attr name="zygotePreloadName" format="string"/>
+
<!-- If set to <code>true</code>, indicates to the platform that this APK is
a 'feature' split and that it implicitly depends on the base APK. This distinguishes
this split APK from a 'configuration' split, which provides resource overrides
@@ -1644,6 +1653,7 @@
<!-- If {@code true} the user is prompted to keep the app's data on uninstall -->
<attr name="hasFragileUserData" />
+ <attr name="zygotePreloadName" />
</declare-styleable>
<!-- The <code>permission</code> tag declares a security permission that can be
used to control access from other packages to specific components or
@@ -2300,17 +2310,18 @@
<!-- If true, and this is an {@link android.R.attr#isolatedProcess} service, the service
will be spawned from an Application Zygote, instead of the regular Zygote.
<p>
- The Application Zygote will pre-initialize the application's class loader,
- and call a static callback into the application to allow it to perform
+ The Application Zygote will first pre-initialize the application's class loader. Then,
+ if the application has defined the {@link android.R.attr#zygotePreloadName} attribute,
+ the Application Zygote will call into that class to allow it to perform
application-specific preloads (such as loading a shared library). Therefore,
spawning from the Application Zygote will typically reduce the service
launch time and reduce its memory usage. The downside of using this flag
is that you will have an additional process (the app zygote itself) that
is taking up memory. Whether actual memory usage is improved therefore strongly
depends on the number of isolated services that an application starts,
- and how much memory those services save by preloading. Therefore, it is
- recommended to measure memory usage under typical workloads to determine
- whether it makes sense to use this flag. -->
+ and how much memory those services save by preloading and sharing memory with
+ the app zygote. Therefore, it is recommended to measure memory usage under
+ typical workloads to determine whether it makes sense to use this flag. -->
<attr name="useAppZygote" format="boolean" />
<!-- If this is a foreground service, specify its category. -->
<attr name="foregroundServiceType" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index ec1bac1a41d6..b5266e247e3a 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2936,6 +2936,7 @@
<public name="minAspectRatio" />
<!-- @hide @SystemApi -->
<public name="inheritShowWhenLocked" />
+ <public name="zygotePreloadName" />
</public-group>
<public-group type="drawable" first-id="0x010800b4">
diff --git a/packages/CaptivePortalLogin/Android.bp b/packages/CaptivePortalLogin/Android.bp
new file mode 100644
index 000000000000..b3e4e8306e29
--- /dev/null
+++ b/packages/CaptivePortalLogin/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2019 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.
+//
+
+android_app {
+ name: "CaptivePortalLogin",
+ srcs: ["src/**/*.java"],
+ platform_apis: true,
+ certificate: "platform",
+ static_libs: [
+ "androidx.legacy_legacy-support-v4",
+ "metrics-constants-protos",
+ ],
+ manifest: "AndroidManifest.xml",
+}
diff --git a/packages/CaptivePortalLogin/Android.mk b/packages/CaptivePortalLogin/Android.mk
deleted file mode 100644
index 8c63f450fda0..000000000000
--- a/packages/CaptivePortalLogin/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_USE_AAPT2 := true
-LOCAL_STATIC_ANDROID_LIBRARIES := androidx.legacy_legacy-support-v4
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := CaptivePortalLogin
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/packages/CaptivePortalLogin/AndroidManifest.xml b/packages/CaptivePortalLogin/AndroidManifest.xml
index 5ab66324930d..e15dca046006 100644
--- a/packages/CaptivePortalLogin/AndroidManifest.xml
+++ b/packages/CaptivePortalLogin/AndroidManifest.xml
@@ -21,9 +21,10 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
- <uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" />
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.NETWORK_SETTINGS" />
+ <uses-permission android:name="android.permission.NETWORK_BYPASS_PRIVATE_DNS" />
<application android:label="@string/app_name"
android:usesCleartextTraffic="true"
diff --git a/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml b/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml
deleted file mode 100644
index d460041e59ae..000000000000
--- a/packages/CaptivePortalLogin/res/layout/ssl_error_msg.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2018 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.
--->
-
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/ssl_error_msg"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:layout_marginStart="20dip"
- android:layout_marginEnd="20dip"
- android:gravity="center_vertical"
- android:layout_marginBottom="4dip"
- android:layout_marginTop="4dip" />
-
diff --git a/packages/CaptivePortalLogin/res/layout/ssl_warning.xml b/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
index ffd57a430662..ce05e78757a1 100644
--- a/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
+++ b/packages/CaptivePortalLogin/res/layout/ssl_warning.xml
@@ -78,7 +78,18 @@
android:id="@+id/certificate_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:orientation="vertical"
android:layout_marginBottom="16dip" >
+ <TextView
+ android:id="@+id/ssl_error_msg"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:layout_marginStart="20dip"
+ android:layout_marginEnd="20dip"
+ android:gravity="center_vertical"
+ android:layout_marginBottom="4dip"
+ android:layout_marginTop="16dip" />
</LinearLayout>
</ScrollView>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index 0a571c5c2736..ce627ce47717 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -20,7 +20,7 @@ import static android.net.ConnectivityManager.EXTRA_CAPTIVE_PORTAL_PROBE_SPEC;
import android.app.Activity;
import android.app.AlertDialog;
-import android.app.LoadedApk;
+import android.app.Application;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
@@ -37,8 +37,9 @@ import android.net.captiveportal.CaptivePortalProbeSpec;
import android.net.http.SslCertificate;
import android.net.http.SslError;
import android.net.wifi.WifiInfo;
-import android.os.Build;
+import android.net.wifi.WifiManager;
import android.os.Bundle;
+import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
@@ -96,6 +97,7 @@ public class CaptivePortalLoginActivity extends Activity {
private CaptivePortal mCaptivePortal;
private NetworkCallback mNetworkCallback;
private ConnectivityManager mCm;
+ private WifiManager mWifiManager;
private boolean mLaunchBrowser = false;
private MyWebViewClient mWebViewClient;
private SwipeRefreshLayout mSwipeRefreshLayout;
@@ -109,7 +111,8 @@ public class CaptivePortalLoginActivity extends Activity {
mCaptivePortal = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL);
logMetricsEvent(MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY);
- mCm = ConnectivityManager.from(this);
+ mCm = getSystemService(ConnectivityManager.class);
+ mWifiManager = getSystemService(WifiManager.class);
mNetwork = getIntent().getParcelableExtra(ConnectivityManager.EXTRA_NETWORK);
mUserAgent =
getIntent().getStringExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_USER_AGENT);
@@ -151,7 +154,6 @@ public class CaptivePortalLoginActivity extends Activity {
// Also initializes proxy system properties.
mNetwork = mNetwork.getPrivateDnsBypassingCopy();
mCm.bindProcessToNetwork(mNetwork);
- mCm.setProcessDefaultNetworkForHostResolution(mNetwork);
// Proxy system properties must be initialized before setContentView is called because
// setContentView initializes the WebView logic which in turn reads the system properties.
@@ -190,9 +192,12 @@ public class CaptivePortalLoginActivity extends Activity {
// Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties.
private void setWebViewProxy() {
- LoadedApk loadedApk = getApplication().mLoadedApk;
+ // TODO: migrate to androidx WebView proxy setting API as soon as it is finalized
try {
- Field receiversField = LoadedApk.class.getDeclaredField("mReceivers");
+ final Field loadedApkField = Application.class.getDeclaredField("mLoadedApk");
+ final Class<?> loadedApkClass = loadedApkField.getType();
+ final Object loadedApk = loadedApkField.get(getApplication());
+ Field receiversField = loadedApkClass.getDeclaredField("mReceivers");
receiversField.setAccessible(true);
ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
for (Object receiverMap : receivers.values()) {
@@ -333,7 +338,11 @@ public class CaptivePortalLoginActivity extends Activity {
private static String sanitizeURL(URL url) {
// In non-Debug build, only show host to avoid leaking private info.
- return Build.IS_DEBUGGABLE ? Objects.toString(url) : host(url);
+ return isDebuggable() ? Objects.toString(url) : host(url);
+ }
+
+ private static boolean isDebuggable() {
+ return SystemProperties.getInt("ro.debuggable", 0) == 1;
}
private void testForCaptivePortal() {
@@ -586,19 +595,18 @@ public class CaptivePortalLoginActivity extends Activity {
}
private void setViewSecurityCertificate(LinearLayout certificateLayout, SslError error) {
+ ((TextView) certificateLayout.findViewById(R.id.ssl_error_msg))
+ .setText(sslErrorMessage(error));
SslCertificate cert = error.getCertificate();
-
- View certificateView = cert.inflateCertificateView(CaptivePortalLoginActivity.this);
- final LinearLayout placeholder = (LinearLayout) certificateView
- .findViewById(com.android.internal.R.id.placeholder);
- LayoutInflater factory = LayoutInflater.from(CaptivePortalLoginActivity.this);
-
- TextView textView = (TextView) factory.inflate(
- R.layout.ssl_error_msg, placeholder, false);
- textView.setText(sslErrorMessage(error));
- placeholder.addView(textView);
-
- certificateLayout.addView(certificateView);
+ // TODO: call the method directly once inflateCertificateView is @SystemApi
+ try {
+ final View certificateView = (View) SslCertificate.class.getMethod(
+ "inflateCertificateView", Context.class)
+ .invoke(cert, CaptivePortalLoginActivity.this);
+ certificateLayout.addView(certificateView);
+ } catch (ReflectiveOperationException | SecurityException e) {
+ Log.e(TAG, "Could not create certificate view", e);
+ }
}
}
@@ -619,11 +627,30 @@ public class CaptivePortalLoginActivity extends Activity {
private String getHeaderTitle() {
NetworkCapabilities nc = mCm.getNetworkCapabilities(mNetwork);
- if (nc == null || TextUtils.isEmpty(nc.getSSID())
- || !nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+ final String ssid = getSsid();
+ if (TextUtils.isEmpty(ssid)
+ || nc == null || !nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
return getString(R.string.action_bar_label);
}
- return getString(R.string.action_bar_title, WifiInfo.removeDoubleQuotes(nc.getSSID()));
+ return getString(R.string.action_bar_title, ssid);
+ }
+
+ // TODO: remove once SSID is obtained from NetworkCapabilities
+ private String getSsid() {
+ if (mWifiManager == null) {
+ return null;
+ }
+ final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+ return removeDoubleQuotes(wifiInfo.getSSID());
+ }
+
+ private static String removeDoubleQuotes(String string) {
+ if (string == null) return null;
+ final int length = string.length();
+ if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) {
+ return string.substring(1, length - 1);
+ }
+ return string;
}
private String getHeaderSubtitle(URL url) {
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index b34efc46f3b4..dbffa6d6bcf2 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -109,6 +109,8 @@ public class NetworkMonitor extends StateMachine {
private static final boolean DBG = true;
private static final boolean VDBG = false;
private static final boolean VDBG_STALL = Log.isLoggable(TAG, Log.DEBUG);
+ // TODO: use another permission for CaptivePortalLoginActivity once it has its own certificate
+ private static final String PERMISSION_NETWORK_SETTINGS = "android.permission.NETWORK_SETTINGS";
// Default configuration values for captive portal detection probes.
// TODO: append a random length parameter to the default HTTPS url.
// TODO: randomize browser version ids in the default User-Agent String.
@@ -682,7 +684,7 @@ public class NetworkMonitor extends StateMachine {
public void appResponse(int response) {
if (response == APP_RETURN_WANTED_AS_IS) {
mContext.enforceCallingPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL,
+ PERMISSION_NETWORK_SETTINGS,
"CaptivePortal");
}
sendMessage(CMD_CAPTIVE_PORTAL_APP_FINISHED, response);
@@ -692,7 +694,7 @@ public class NetworkMonitor extends StateMachine {
public void logEvent(int eventId, String packageName)
throws RemoteException {
mContext.enforceCallingPermission(
- android.Manifest.permission.CONNECTIVITY_INTERNAL,
+ PERMISSION_NETWORK_SETTINGS,
"CaptivePortal");
mCallback.logCaptivePortalLoginEvent(eventId, packageName);
}
diff --git a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
index 82bf038073c7..f6eb900c4910 100644
--- a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
+++ b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
@@ -19,6 +19,7 @@ package com.android.server.util;
import static android.os.Binder.getCallingUid;
import android.os.Process;
+import android.os.UserHandle;
/**
* Utility class to check calling permissions on the network stack.
@@ -32,7 +33,7 @@ public final class PermissionUtil {
public static void checkNetworkStackCallingPermission() {
// TODO: check that the calling PID is the system server.
final int caller = getCallingUid();
- if (caller != Process.SYSTEM_UID && caller != Process.BLUETOOTH_UID) {
+ if (caller != Process.SYSTEM_UID && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) {
throw new SecurityException("Invalid caller: " + caller);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 77cdbb921273..0a04f4d11a6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1334,16 +1334,21 @@ public class NotificationContentView extends FrameLayout {
static SmartRepliesAndActions chooseSmartRepliesAndActions(
SmartReplyConstants smartReplyConstants,
final NotificationEntry entry) {
- boolean enableAppGeneratedSmartReplies = (smartReplyConstants.isEnabled()
- && (!smartReplyConstants.requiresTargetingP()
- || entry.targetSdk >= Build.VERSION_CODES.P));
-
Notification notification = entry.notification.getNotification();
Pair<RemoteInput, Notification.Action> remoteInputActionPair =
notification.findRemoteInputActionPair(false /* freeform */);
Pair<RemoteInput, Notification.Action> freeformRemoteInputActionPair =
notification.findRemoteInputActionPair(true /* freeform */);
+ if (!smartReplyConstants.isEnabled()) {
+ return new SmartRepliesAndActions(null, null, freeformRemoteInputActionPair != null);
+ }
+ // Only use smart replies from the app if they target P or above. We have this check because
+ // the smart reply API has been used for other things (Wearables) in the past. The API to
+ // add smart actions is new in Q so it doesn't require a target-sdk check.
+ boolean enableAppGeneratedSmartReplies = (!smartReplyConstants.requiresTargetingP()
+ || entry.targetSdk >= Build.VERSION_CODES.P);
+
boolean appGeneratedSmartRepliesExist =
enableAppGeneratedSmartReplies
&& remoteInputActionPair != null
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
index d94bf845ca5b..c36fec28459d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
@@ -193,14 +193,32 @@ public class NotificationContentViewTest extends SysuiTestCase {
}
@Test
- public void chooseSmartRepliesAndActions_smartRepliesOff_noAppGeneratedSmartReplies() {
- setupAppGeneratedReplies(new String[] {"Reply1", "Reply2"});
+ public void chooseSmartRepliesAndActions_smartRepliesOff_noAppGeneratedSmartSuggestions() {
+ CharSequence[] smartReplies = new String[] {"Reply1", "Reply2"};
+ List<Notification.Action> smartActions =
+ createActions(new String[] {"Test Action 1", "Test Action 2"});
+ setupAppGeneratedSuggestions(smartReplies, smartActions);
+ when(mSmartReplyConstants.isEnabled()).thenReturn(false);
+
+ NotificationContentView.SmartRepliesAndActions repliesAndActions =
+ NotificationContentView.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
+
+ assertThat(repliesAndActions.smartReplies).isNull();
+ assertThat(repliesAndActions.smartActions).isNull();
+ }
+
+ @Test
+ public void chooseSmartRepliesAndActions_smartRepliesOff_noSystemGeneratedSmartSuggestions() {
+ mEntry.smartReplies = new String[] {"Sys Smart Reply 1", "Sys Smart Reply 2"};
+ mEntry.systemGeneratedSmartActions =
+ createActions(new String[] {"Sys Smart Action 1", "Sys Smart Action 2"});
when(mSmartReplyConstants.isEnabled()).thenReturn(false);
NotificationContentView.SmartRepliesAndActions repliesAndActions =
NotificationContentView.chooseSmartRepliesAndActions(mSmartReplyConstants, mEntry);
assertThat(repliesAndActions.smartReplies).isNull();
+ assertThat(repliesAndActions.smartActions).isNull();
}
@Test
diff --git a/proto/Android.bp b/proto/Android.bp
index f3811bdd7d81..817a54d93268 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -17,3 +17,24 @@ java_library_static {
},
},
}
+
+java_library_static {
+ name: "metrics-constants-protos",
+ host_supported: true,
+ proto: {
+ type: "nano",
+ },
+ srcs: ["src/metrics_constants/metrics_constants.proto"],
+ no_framework_libs: true,
+ sdk_version: "system_current",
+ // Pin java_version until jarjar is certified to support later versions. http://b/72703434
+ java_version: "1.8",
+ target: {
+ android: {
+ jarjar_rules: "jarjar-rules.txt",
+ },
+ host: {
+ static_libs: ["libprotobuf-java-nano"],
+ },
+ },
+}