diff options
8 files changed, 255 insertions, 38 deletions
diff --git a/core/jni/android_os_HwBinder.cpp b/core/jni/android_os_HwBinder.cpp index c3978e7556ee..577cd49cbaec 100644 --- a/core/jni/android_os_HwBinder.cpp +++ b/core/jni/android_os_HwBinder.cpp @@ -276,7 +276,8 @@ static jobject JHwBinder_native_getService( jstring ifaceNameObj, jstring serviceNameObj) { - using ::android::vintf::operator<<; + using ::android::hidl::base::V1_0::IBase; + using ::android::hidl::manager::V1_0::IServiceManager; if (ifaceNameObj == NULL) { jniThrowException(env, "java/lang/NullPointerException", NULL); @@ -318,13 +319,20 @@ static jobject JHwBinder_native_getService( << "/" << serviceName; - ::android::vintf::Transport transport = - ::android::hardware::getTransport(ifaceName, serviceName); - if ( transport != ::android::vintf::Transport::EMPTY - && transport != ::android::vintf::Transport::HWBINDER) { + Return<IServiceManager::Transport> transportRet = + manager->getTransport(ifaceNameHStr, serviceNameHStr); + + if (!transportRet.isOk()) { + signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */); + return NULL; + } + + IServiceManager::Transport transport = transportRet; + + if ( transport != IServiceManager::Transport::EMPTY + && transport != IServiceManager::Transport::HWBINDER) { LOG(ERROR) << "service " << ifaceName << " declares transport method " - << transport << " but framework expects " - << ::android::vintf::Transport::HWBINDER; + << toString(transport) << " but framework expects hwbinder."; signalExceptionForError(env, UNKNOWN_ERROR, true /* canThrowRemoteException */); return NULL; } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 460d466a13bd..9991a20a9b82 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1257,6 +1257,13 @@ <permission android:name="android.permission.REQUEST_NETWORK_SCORES" android:protectionLevel="signature" /> + <!-- Allows network stack services (Connectivity and Wifi) to coordinate + <p>Not for use by third-party or privileged applications. + @hide This should only be used by Connectivity and Wifi Services. + --> + <permission android:name="android.permission.NETWORK_STACK" + android:protectionLevel="signature" /> + <!-- ======================================= --> <!-- Permissions for short range, peripheral networks --> <!-- ======================================= --> diff --git a/packages/PrintRecommendationService/res/values/strings.xml b/packages/PrintRecommendationService/res/values/strings.xml index b6c45b7a23c8..2bab1b65529b 100644 --- a/packages/PrintRecommendationService/res/values/strings.xml +++ b/packages/PrintRecommendationService/res/values/strings.xml @@ -18,6 +18,7 @@ --> <resources> + <string name="plugin_vendor_google_cloud_print">Cloud Print</string> <string name="plugin_vendor_hp">HP</string> <string name="plugin_vendor_lexmark">Lexmark</string> <string name="plugin_vendor_brother">Brother</string> diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java index 1fe5a2a4d40b..8edd0eccf742 100644 --- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/RecommendationServiceImpl.java @@ -21,6 +21,8 @@ import android.printservice.recommendation.RecommendationInfo; import android.printservice.recommendation.RecommendationService; import android.printservice.PrintService; import android.util.Log; + +import com.android.printservice.recommendation.plugin.google.CloudPrintPlugin; import com.android.printservice.recommendation.plugin.hp.HPRecommendationPlugin; import com.android.printservice.recommendation.plugin.mdnsFilter.MDNSFilterPlugin; import com.android.printservice.recommendation.plugin.mdnsFilter.VendorConfig; @@ -61,6 +63,14 @@ public class RecommendationServiceImpl extends RecommendationService } try { + mPlugins.add(new RemotePrintServicePlugin(new CloudPrintPlugin(this), this, + true)); + } catch (Exception e) { + Log.e(LOG_TAG, "Could not initiate " + + getString(R.string.plugin_vendor_google_cloud_print) + " plugin", e); + } + + try { mPlugins.add(new RemotePrintServicePlugin(new HPRecommendationPlugin(this), this, false)); } catch (Exception e) { diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java new file mode 100644 index 000000000000..05b0c862ebd5 --- /dev/null +++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/google/CloudPrintPlugin.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.printservice.recommendation.plugin.google; + +import static com.android.printservice.recommendation.util.MDNSUtils.ATTRIBUTE_TY; + +import android.annotation.NonNull; +import android.annotation.StringRes; +import android.content.Context; +import android.util.ArrayMap; +import android.util.Log; + +import com.android.printservice.recommendation.PrintServicePlugin; +import com.android.printservice.recommendation.R; +import com.android.printservice.recommendation.util.MDNSFilteredDiscovery; + +import java.net.Inet4Address; +import java.net.InetAddress; +import java.nio.charset.StandardCharsets; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Plugin detecting <a href="https://developers.google.com/cloud-print/docs/privet">Google Cloud + * Print</a> printers. + */ +public class CloudPrintPlugin implements PrintServicePlugin { + private static final String LOG_TAG = CloudPrintPlugin.class.getSimpleName(); + private static final boolean DEBUG = false; + + private static final String ATTRIBUTE_TXTVERS = "txtvers"; + private static final String ATTRIBUTE_URL = "url"; + private static final String ATTRIBUTE_TYPE = "type"; + private static final String ATTRIBUTE_ID = "id"; + private static final String ATTRIBUTE_CS = "cs"; + + private static final String TYPE = "printer"; + + private static final String PRIVET_SERVICE = "_privet._tcp"; + + /** The required mDNS service types */ + private static final Set<String> PRINTER_SERVICE_TYPE = new HashSet<String>() {{ + // Not checking _printer_._sub + add(PRIVET_SERVICE); + }}; + + /** All possible connection states */ + private static final Set<String> POSSIBLE_CONNECTION_STATES = new HashSet<String>() {{ + add("online"); + add("offline"); + add("connecting"); + add("not-configured"); + }}; + + private static final byte SUPPORTED_TXTVERS = '1'; + + /** The mDNS filtered discovery */ + private final MDNSFilteredDiscovery mMDNSFilteredDiscovery; + + /** + * Create a plugin detecting Google Cloud Print printers. + * + * @param context The context the plugin runs in + */ + public CloudPrintPlugin(@NonNull Context context) { + mMDNSFilteredDiscovery = new MDNSFilteredDiscovery(context, PRINTER_SERVICE_TYPE, + nsdServiceInfo -> { + // The attributes are case insensitive. For faster searching create a clone of + // the map with the attribute-keys all in lower case. + ArrayMap<String, byte[]> caseInsensitiveAttributes = + new ArrayMap<>(nsdServiceInfo.getAttributes().size()); + for (Map.Entry<String, byte[]> entry : nsdServiceInfo.getAttributes() + .entrySet()) { + caseInsensitiveAttributes.put(entry.getKey().toLowerCase(), + entry.getValue()); + } + + if (DEBUG) { + Log.i(LOG_TAG, nsdServiceInfo.getServiceName() + ":"); + Log.i(LOG_TAG, "type: " + nsdServiceInfo.getServiceType()); + Log.i(LOG_TAG, "host: " + nsdServiceInfo.getHost()); + for (Map.Entry<String, byte[]> entry : caseInsensitiveAttributes.entrySet()) { + if (entry.getValue() == null) { + Log.i(LOG_TAG, entry.getKey() + "= null"); + } else { + Log.i(LOG_TAG, entry.getKey() + "=" + new String(entry.getValue(), + StandardCharsets.UTF_8)); + } + } + } + + byte[] txtvers = caseInsensitiveAttributes.get(ATTRIBUTE_TXTVERS); + if (txtvers == null || txtvers.length != 1 || txtvers[0] != SUPPORTED_TXTVERS) { + // The spec requires this to be the first attribute, but at this time we + // lost the order of the attributes + return false; + } + + if (caseInsensitiveAttributes.get(ATTRIBUTE_TY) == null) { + return false; + } + + byte[] url = caseInsensitiveAttributes.get(ATTRIBUTE_URL); + if (url == null || url.length == 0) { + return false; + } + + byte[] type = caseInsensitiveAttributes.get(ATTRIBUTE_TYPE); + if (type == null || !TYPE.equals( + new String(type, StandardCharsets.UTF_8).toLowerCase())) { + return false; + } + + if (caseInsensitiveAttributes.get(ATTRIBUTE_ID) == null) { + return false; + } + + byte[] cs = caseInsensitiveAttributes.get(ATTRIBUTE_CS); + if (cs == null || !POSSIBLE_CONNECTION_STATES.contains( + new String(cs, StandardCharsets.UTF_8).toLowerCase())) { + return false; + } + + InetAddress address = nsdServiceInfo.getHost(); + if (!(address instanceof Inet4Address)) { + // Not checking for link local address + return false; + } + + return true; + }); + } + + @Override + @NonNull public CharSequence getPackageName() { + return "com.google.android.apps.cloudprint"; + } + + @Override + public void start(@NonNull PrinterDiscoveryCallback callback) throws Exception { + mMDNSFilteredDiscovery.start(callback); + } + + @Override + @StringRes public int getName() { + return R.string.plugin_vendor_google_cloud_print; + } + + @Override + public void stop() throws Exception { + mMDNSFilteredDiscovery.stop(); + } +} diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index a81e6b755fd4..7031662172dc 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -1303,13 +1303,16 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public LinkProperties getLinkProperties(Network network) { enforceAccessPermission(); - NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); - if (nai != null) { - synchronized (nai) { - return new LinkProperties(nai.linkProperties); - } + return getLinkProperties(getNetworkAgentInfoForNetwork(network)); + } + + private LinkProperties getLinkProperties(NetworkAgentInfo nai) { + if (nai == null) { + return null; + } + synchronized (nai) { + return new LinkProperties(nai.linkProperties); } - return null; } private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) { @@ -3133,7 +3136,8 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceAccessPermission(); enforceInternetPermission(); - NetworkAgentInfo nai; + // TODO: execute this logic on ConnectivityService handler. + final NetworkAgentInfo nai; if (network == null) { nai = getDefaultNetwork(); } else { @@ -3144,21 +3148,24 @@ public class ConnectivityService extends IConnectivityManager.Stub return; } // Revalidate if the app report does not match our current validated state. - if (hasConnectivity == nai.lastValidated) return; + if (hasConnectivity == nai.lastValidated) { + return; + } final int uid = Binder.getCallingUid(); if (DBG) { log("reportNetworkConnectivity(" + nai.network.netId + ", " + hasConnectivity + ") by " + uid); } - synchronized (nai) { - // Validating a network that has not yet connected could result in a call to - // rematchNetworkAndRequests() which is not meant to work on such networks. - if (!nai.everConnected) return; - - if (isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, false)) return; - - nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid); + // Validating a network that has not yet connected could result in a call to + // rematchNetworkAndRequests() which is not meant to work on such networks. + if (!nai.everConnected) { + return; + } + LinkProperties lp = getLinkProperties(nai); + if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) { + return; } + nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid); } private ProxyInfo getDefaultProxy() { diff --git a/services/core/java/com/android/server/connectivity/NetworkMonitor.java b/services/core/java/com/android/server/connectivity/NetworkMonitor.java index 97669d242f06..6cf8f37b7604 100644 --- a/services/core/java/com/android/server/connectivity/NetworkMonitor.java +++ b/services/core/java/com/android/server/connectivity/NetworkMonitor.java @@ -301,6 +301,11 @@ public class NetworkMonitor extends StateMachine { if (DBG) Log.d(TAG + "/" + mNetworkAgentInfo.name(), s); } + private void validationLog(int probeType, Object url, String msg) { + String probeName = ValidationProbeEvent.getProbeName(probeType); + validationLog(String.format("%s %s %s", probeName, url, msg)); + } + private void validationLog(String s) { if (DBG) log(s); validationLogs.log(s); @@ -752,20 +757,19 @@ public class NetworkMonitor extends StateMachine { String connectInfo; try { InetAddress[] addresses = mNetworkAgentInfo.network.getAllByName(host); - result = ValidationProbeEvent.DNS_SUCCESS; - StringBuffer buffer = new StringBuffer(host).append("="); + StringBuffer buffer = new StringBuffer(); for (InetAddress address : addresses) { - buffer.append(address.getHostAddress()); - if (address != addresses[addresses.length-1]) buffer.append(","); + buffer.append(',').append(address.getHostAddress()); } - connectInfo = buffer.toString(); + result = ValidationProbeEvent.DNS_SUCCESS; + connectInfo = "OK " + buffer.substring(1); } catch (UnknownHostException e) { result = ValidationProbeEvent.DNS_FAILURE; - connectInfo = host; + connectInfo = "FAIL"; } final long latency = watch.stop(); - String resultString = (ValidationProbeEvent.DNS_SUCCESS == result) ? "OK" : "FAIL"; - validationLog(String.format("%s %s %dms, %s", name, resultString, latency, connectInfo)); + validationLog(ValidationProbeEvent.PROBE_DNS, host, + String.format("%dms %s", latency, connectInfo)); logValidationProbe(latency, ValidationProbeEvent.PROBE_DNS, result); } @@ -787,7 +791,7 @@ public class NetworkMonitor extends StateMachine { urlConnection.setUseCaches(false); final String userAgent = getCaptivePortalUserAgent(mContext); if (userAgent != null) { - urlConnection.setRequestProperty("User-Agent", userAgent); + urlConnection.setRequestProperty("User-Agent", userAgent); } // cannot read request header after connection String requestHeader = urlConnection.getRequestProperties().toString(); @@ -801,8 +805,7 @@ public class NetworkMonitor extends StateMachine { // Time how long it takes to get a response to our request long responseTimestamp = SystemClock.elapsedRealtime(); - validationLog(ValidationProbeEvent.getProbeName(probeType) + " " + url + - " time=" + (responseTimestamp - requestTimestamp) + "ms" + + validationLog(probeType, url, "time=" + (responseTimestamp - requestTimestamp) + "ms" + " ret=" + httpResponseCode + " request=" + requestHeader + " headers=" + urlConnection.getHeaderFields()); @@ -814,27 +817,29 @@ public class NetworkMonitor extends StateMachine { // proxy server. if (httpResponseCode == 200) { if (probeType == ValidationProbeEvent.PROBE_PAC) { - validationLog("PAC fetch 200 response interpreted as 204 response."); + validationLog( + probeType, url, "PAC fetch 200 response interpreted as 204 response."); httpResponseCode = 204; } else if (urlConnection.getContentLengthLong() == 0) { // Consider 200 response with "Content-length=0" to not be a captive portal. // There's no point in considering this a captive portal as the user cannot // sign-in to an empty page. Probably the result of a broken transparent proxy. // See http://b/9972012. - validationLog( + validationLog(probeType, url, "200 response with Content-length=0 interpreted as 204 response."); httpResponseCode = 204; } else if (urlConnection.getContentLengthLong() == -1) { // When no Content-length (default value == -1), attempt to read a byte from the // response. Do not use available() as it is unreliable. See http://b/33498325. if (urlConnection.getInputStream().read() == -1) { - validationLog("Empty 200 response interpreted as 204 response."); + validationLog( + probeType, url, "Empty 200 response interpreted as 204 response."); httpResponseCode = 204; } } } } catch (IOException e) { - validationLog("Probably not a portal: exception " + e); + validationLog(probeType, url, "Probably not a portal: exception " + e); if (httpResponseCode == 599) { // TODO: Ping gateway and DNS server and log results. } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 8800f8e67d35..7e0fbb9cc70f 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -721,6 +721,16 @@ public class CarrierConfigManager { public static final String KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL = "hide_preferred_network_type_bool"; /** + * String array for package names that need to be enabled for this carrier. + * If user has explicitly disabled some packages in the list, won't re-enable. + * Other carrier specific apps which are not in this list may be disabled for current carrier, + * and only be re-enabled when this config for another carrier includes it. + * + * @hide + */ + public static final String KEY_ENABLE_APPS_STRING_ARRAY = "enable_apps_string_array"; + + /** * Determine whether user can switch Wi-Fi preferred or Cellular preferred in calling preference. * Some operators support Wi-Fi Calling only, not VoLTE. * They don't need "Cellular preferred" option. @@ -1387,6 +1397,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_HIDE_IMS_APN_BOOL, false); sDefaults.putBoolean(KEY_HIDE_PREFERRED_NETWORK_TYPE_BOOL, false); sDefaults.putBoolean(KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL, false); + sDefaults.putStringArray(KEY_ENABLE_APPS_STRING_ARRAY, null); sDefaults.putBoolean(KEY_EDITABLE_WFC_MODE_BOOL, true); sDefaults.putStringArray(KEY_WFC_OPERATOR_ERROR_CODES_STRING_ARRAY, null); sDefaults.putInt(KEY_WFC_SPN_FORMAT_IDX_INT, 0); |