diff options
author | Remi NGUYEN VAN <reminv@google.com> | 2019-01-30 23:39:24 +0900 |
---|---|---|
committer | Remi NGUYEN VAN <reminv@google.com> | 2019-01-31 18:14:54 +0900 |
commit | 47274275cfda84fc8f0cd7f19b38047edb1d416d (patch) | |
tree | db70375513a56de3ac4796a41190b64b730e5afd | |
parent | 602df1aa8c6d3bef54f9bed1d8593f3cf78e6351 (diff) |
Prepare CaptivePortalLogin for system_current
Includes small changes to stop using non-SystemApi endpoints.
Test: make CaptivePortalLogin
Test: flashed, login works, SSL certificate invalid flow works
Bug: 112869080
Merged-In: Ic6ce98942959705ea7ef14a7a62d33e3abf7eb72
Change-Id: Ie7ea3bab6aa8629ce4c111adee0c0699d95d4b0e
8 files changed, 114 insertions, 66 deletions
diff --git a/packages/CaptivePortalLogin/Android.bp b/packages/CaptivePortalLogin/Android.bp new file mode 100644 index 000000000000..f5e252c61fa1 --- /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: [ + "android-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 7dc23ff8e8b8..000000000000 --- a/packages/CaptivePortalLogin/Android.mk +++ /dev/null @@ -1,13 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional -LOCAL_STATIC_JAVA_LIBRARIES := android-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 c84f3ec68178..e15dca046006 100644 --- a/packages/CaptivePortalLogin/AndroidManifest.xml +++ b/packages/CaptivePortalLogin/AndroidManifest.xml @@ -21,7 +21,8 @@ <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.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" /> 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 08b22c7d518a..9b70ff368afb 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.support.v4.widget.SwipeRefreshLayout; import android.text.TextUtils; import android.util.ArrayMap; @@ -95,6 +96,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; @@ -108,7 +110,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); @@ -150,7 +153,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. @@ -189,9 +191,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()) { @@ -332,7 +337,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() { @@ -585,19 +594,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); + } } } @@ -618,11 +626,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/proto/Android.bp b/proto/Android.bp index f3811bdd7d81..9b7a1c15cf97 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.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"], + }, + }, +} |