diff options
author | Nate Jiang <qiangjiang@google.com> | 2020-01-09 20:46:55 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-01-09 20:46:55 +0000 |
commit | 09fb659a1c526e3741b3cc9d582503c59a8d551e (patch) | |
tree | 8c6a2452a49916ae043ad8b0a073cf428b190ca4 /service | |
parent | 81a68bf4b288346592a53ff3db45211c88b4083a (diff) | |
parent | 916257387266b8c5002ebf68e699c9e0d794bfe9 (diff) |
Merge "[NetworkSuggestion]carrier privileged exemption"
Diffstat (limited to 'service')
5 files changed, 183 insertions, 65 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 7da4b6fd1..3d6d1b09b 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -3966,6 +3966,7 @@ public class ClientModeImpl extends StateMachine { if (!simPresent) { mWifiConfigManager.resetSimNetworks(); } + mWifiNetworkSuggestionsManager.resetCarrierPrivilegedApps(); break; case CMD_BLUETOOTH_ADAPTER_STATE_CHANGE: // If BT was connected and then turned off, there is no CONNECTION_STATE_CHANGE diff --git a/service/java/com/android/server/wifi/NetworkSuggestionNominator.java b/service/java/com/android/server/wifi/NetworkSuggestionNominator.java index 144703f67..40325989e 100644 --- a/service/java/com/android/server/wifi/NetworkSuggestionNominator.java +++ b/service/java/com/android/server/wifi/NetworkSuggestionNominator.java @@ -98,7 +98,7 @@ public class NetworkSuggestionNominator implements WifiNetworkSelector.NetworkNo for (Pair<ScanDetail, WifiConfiguration> candidate : candidates) { Set<ExtendedWifiNetworkSuggestion> matchingPasspointExtSuggestions = mWifiNetworkSuggestionsManager - .getNetworkSuggestionsForFqfn(candidate.second.FQDN); + .getNetworkSuggestionsForFqdn(candidate.second.FQDN); if (matchingPasspointExtSuggestions == null || matchingPasspointExtSuggestions.isEmpty()) { continue; diff --git a/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java b/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java index ba91579b9..2a4ae353e 100644 --- a/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java +++ b/service/java/com/android/server/wifi/NetworkSuggestionStoreData.java @@ -24,6 +24,7 @@ import android.net.wifi.WifiEnterpriseConfig; import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.hotspot2.PasspointConfiguration; import android.os.Process; +import android.telephony.TelephonyManager; import android.util.Log; import android.util.Pair; @@ -68,6 +69,7 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { private static final String XML_TAG_SUGGESTOR_PACKAGE_NAME = "SuggestorPackageName"; private static final String XML_TAG_SUGGESTOR_FEATURE_ID = "SuggestorFeatureId"; private static final String XML_TAG_SUGGESTOR_HAS_USER_APPROVED = "SuggestorHasUserApproved"; + private static final String XML_TAG_SUGGESTOR_CARRIER_ID = "SuggestorCarrierId"; private static final String XML_TAG_SUGGESTOR_MAX_SIZE = "SuggestorMaxSize"; private static final String XML_TAG_SECTION_HEADER_PASSPOINT_CONFIGURATION = "PasspointConfiguration"; @@ -166,6 +168,7 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { boolean hasUserApproved = entry.getValue().hasUserApproved; int maxSize = entry.getValue().maxSize; int uid = entry.getValue().uid; + int carrierId = entry.getValue().carrierId; Set<ExtendedWifiNetworkSuggestion> networkSuggestions = entry.getValue().extNetworkSuggestions; XmlUtil.writeNextSectionStart(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP); @@ -174,6 +177,7 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_HAS_USER_APPROVED, hasUserApproved); XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_MAX_SIZE, maxSize); XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_UID, uid); + XmlUtil.writeNextValue(out, XML_TAG_SUGGESTOR_CARRIER_ID, carrierId); serializeExtNetworkSuggestions(out, networkSuggestions, encryptionUtil); XmlUtil.writeNextSectionEnd(out, XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION_PER_APP); } @@ -260,6 +264,7 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { boolean hasUserApproved = false; int maxSize = -1; int uid = Process.INVALID_UID; + int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; // Loop through and parse out all the elements from the stream within this section. while (XmlUtils.nextElementWithin(in, outerTagDepth + 1)) { if (in.getAttributeValue(null, "name") != null) { @@ -282,6 +287,9 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { case XML_TAG_SUGGESTOR_UID: uid = (int) value; break; + case XML_TAG_SUGGESTOR_CARRIER_ID: + carrierId = (int) value; + break; default: Log.w(TAG, "Ignoring unknown value name found: " + valueName[0]); break; @@ -302,6 +310,7 @@ public class NetworkSuggestionStoreData implements WifiConfigStore.StoreData { perAppInfo = new PerAppInfo(uid, packageName, featureId); perAppInfo.hasUserApproved = hasUserApproved; perAppInfo.maxSize = maxSize; + perAppInfo.carrierId = carrierId; } switch (tagName) { case XML_TAG_SECTION_HEADER_NETWORK_SUGGESTION: diff --git a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java index 41a67f2d6..082ed0883 100644 --- a/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java +++ b/service/java/com/android/server/wifi/WifiNetworkSuggestionsManager.java @@ -41,11 +41,13 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.net.wifi.WifiNetworkSuggestion; import android.net.wifi.WifiScanner; +import android.net.wifi.hotspot2.PasspointConfiguration; import android.os.Handler; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.Log; @@ -143,6 +145,10 @@ public class WifiNetworkSuggestionsManager { * Whether we have shown the user a notification for this app. */ public boolean hasUserApproved = false; + /** + * Carrier Id of SIM which give app carrier privileges. + */ + public int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID; /** Stores the max size of the {@link #extNetworkSuggestions} list ever for this app */ public int maxSize = 0; @@ -649,8 +655,11 @@ public class WifiNetworkSuggestionsManager { return WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; } if (!validateNetworkSuggestions(networkSuggestions, uid, packageName)) { + Log.e(TAG, "bad wifi suggestion from app: " + packageName); return WifiManager.STATUS_NETWORK_SUGGESTIONS_ERROR_APP_DISALLOWED; } + + int carrierId = mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(packageName); PerAppInfo perAppInfo = mActiveNetworkSuggestionsPerApp.get(packageName); if (perAppInfo == null) { perAppInfo = new PerAppInfo(uid, packageName, featureId); @@ -658,6 +667,9 @@ public class WifiNetworkSuggestionsManager { if (mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid)) { Log.i(TAG, "Setting the carrier provisioning app approved"); perAppInfo.hasUserApproved = true; + } else if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { + Log.i(TAG, "Setting the carrier privileged app approved"); + perAppInfo.carrierId = carrierId; } else { sendUserApprovalNotification(packageName, uid); } @@ -689,8 +701,14 @@ public class WifiNetworkSuggestionsManager { } for (ExtendedWifiNetworkSuggestion ewns: extNetworkSuggestions) { if (ewns.wns.passpointConfiguration == null) { + if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { + ewns.wns.wifiConfiguration.carrierId = carrierId; + } addToScanResultMatchInfoMap(ewns); } else { + if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { + ewns.wns.passpointConfiguration.setCarrierId(carrierId); + } // Install Passpoint config, if failure, ignore that suggestion if (!mWifiInjector.getPasspointManager().addOrUpdateProvider( ewns.wns.passpointConfiguration, uid, @@ -711,17 +729,35 @@ public class WifiNetworkSuggestionsManager { return WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS; } - private boolean validateNetworkSuggestions( - List<WifiNetworkSuggestion> networkSuggestions, int uid, String packageName) { - if (mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid)) { + private boolean validateNetworkSuggestions(List<WifiNetworkSuggestion> networkSuggestions, + int uid, String packageName) { + if (mWifiPermissionsUtil.checkNetworkCarrierProvisioningPermission(uid) + || mTelephonyUtil.getCarrierIdForPackageWithCarrierPrivileges(packageName) + != TelephonyManager.UNKNOWN_CARRIER_ID) { return true; } + // If an app doesn't have carrier privileges or carrier provisioning permission, suggests + // SIM-based network and sets CarrierId are illegal. for (WifiNetworkSuggestion suggestion : networkSuggestions) { - WifiConfiguration config = suggestion.wifiConfiguration; - if (config != null - && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { - Log.e(TAG, "bad wifi suggestion from app: " + packageName); - return false; + if (suggestion.passpointConfiguration == null) { + WifiConfiguration config = suggestion.wifiConfiguration; + if (config != null + && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { + return false; + } + if (config != null && config.enterpriseConfig != null + && config.enterpriseConfig.isAuthenticationSimBased()) { + return false; + } + } else { + PasspointConfiguration config = suggestion.passpointConfiguration; + if (config.getCarrierId() != TelephonyManager.UNKNOWN_CARRIER_ID) { + return false; + } + if (config.getCredential() != null + && config.getCredential().getSimCredential() != null) { + return false; + } } } @@ -968,7 +1004,7 @@ public class WifiNetworkSuggestionsManager { * @param uid app UID * @return true if app is not approved and send notification. */ - public boolean sendUserApprovalNotificationIfNotApproved( + private boolean sendUserApprovalNotificationIfNotApproved( @NonNull String packageName, @NonNull int uid) { if (!mActiveNetworkSuggestionsPerApp.containsKey(packageName)) { Log.wtf(TAG, "AppInfo is missing for " + packageName); @@ -978,10 +1014,11 @@ public class WifiNetworkSuggestionsManager { return false; // already approved. } - Log.i(TAG, "Sending user approval notification for " + packageName); - if (!mUserApprovalNotificationActive) { - sendUserApprovalNotification(packageName, uid); + if (mUserApprovalNotificationActive) { + return false; // has active notification. } + Log.i(TAG, "Sending user approval notification for " + packageName); + sendUserApprovalNotification(packageName, uid); return true; } @@ -1019,30 +1056,19 @@ public class WifiNetworkSuggestionsManager { /** * Returns a set of all network suggestions matching the provided FQDN. */ - public @Nullable Set<ExtendedWifiNetworkSuggestion> getNetworkSuggestionsForFqfn(String fqdn) { + public @Nullable Set<ExtendedWifiNetworkSuggestion> getNetworkSuggestionsForFqdn(String fqdn) { Set<ExtendedWifiNetworkSuggestion> extNetworkSuggestions = getNetworkSuggestionsForFqdnMatch(fqdn); if (extNetworkSuggestions == null) { return null; } - Set<ExtendedWifiNetworkSuggestion> approvedExtNetworkSuggestions = - extNetworkSuggestions - .stream() - .filter(n -> n.perAppInfo.hasUserApproved) - .collect(Collectors.toSet()); - // If there is no active notification, check if we need to get approval for any of the apps - // & send a notification for one of them. If there are multiple packages awaiting approval, - // we end up picking the first one. The others will be reconsidered in the next iteration. - if (!mUserApprovalNotificationActive - && approvedExtNetworkSuggestions.size() != extNetworkSuggestions.size()) { - for (ExtendedWifiNetworkSuggestion extNetworkSuggestion : extNetworkSuggestions) { - if (sendUserApprovalNotificationIfNotApproved( - extNetworkSuggestion.perAppInfo.packageName, - extNetworkSuggestion.perAppInfo.uid)) { - break; - } + Set<ExtendedWifiNetworkSuggestion> approvedExtNetworkSuggestions = new HashSet<>(); + for (ExtendedWifiNetworkSuggestion ewns : extNetworkSuggestions) { + if (isNetworkSuggestionUserApprovedAndAvailableToConnect(ewns)) { + approvedExtNetworkSuggestions.add(ewns); } } + if (approvedExtNetworkSuggestions.isEmpty()) { return null; } @@ -1075,41 +1101,13 @@ public class WifiNetworkSuggestionsManager { if (extNetworkSuggestions == null) { return null; } - Set<ExtendedWifiNetworkSuggestion> approvedExtNetworkSuggestions = extNetworkSuggestions - .stream() - .filter(n -> { - if (!n.perAppInfo.hasUserApproved) { - return false; - } - WifiConfiguration config = n.wns.wifiConfiguration; - if (config != null && config.enterpriseConfig != null - && config.enterpriseConfig.isAuthenticationSimBased()) { - int subId = mTelephonyUtil.getBestMatchSubscriptionId(config); - if (!mTelephonyUtil.isSimPresent(subId) - || (mTelephonyUtil.requiresImsiEncryption(subId) - && !mTelephonyUtil.isImsiEncryptionInfoAvailable(subId))) { - if (mVerboseLoggingEnabled) { - Log.v(TAG, "No SIM is matched or IMSI encryption " - + "info is required, ignore the config."); - } - return false; - } - } - return true; - }).collect(Collectors.toSet()); - // If there is no active notification, check if we need to get approval for any of the apps - // & send a notification for one of them. If there are multiple packages awaiting approval, - // we end up picking the first one. The others will be reconsidered in the next iteration. - if (!mUserApprovalNotificationActive - && approvedExtNetworkSuggestions.size() != extNetworkSuggestions.size()) { - for (ExtendedWifiNetworkSuggestion extNetworkSuggestion : extNetworkSuggestions) { - if (sendUserApprovalNotificationIfNotApproved( - extNetworkSuggestion.perAppInfo.packageName, - extNetworkSuggestion.perAppInfo.uid)) { - break; - } + Set<ExtendedWifiNetworkSuggestion> approvedExtNetworkSuggestions = new HashSet<>(); + for (ExtendedWifiNetworkSuggestion ewns : extNetworkSuggestions) { + if (isNetworkSuggestionUserApprovedAndAvailableToConnect(ewns)) { + approvedExtNetworkSuggestions.add(ewns); } } + if (approvedExtNetworkSuggestions.isEmpty()) { return null; } @@ -1121,6 +1119,57 @@ public class WifiNetworkSuggestionsManager { return approvedExtNetworkSuggestions; } + private boolean isNetworkSuggestionUserApprovedAndAvailableToConnect( + ExtendedWifiNetworkSuggestion ewns) { + if (!ewns.perAppInfo.hasUserApproved + && ewns.perAppInfo.carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) { + sendUserApprovalNotificationIfNotApproved(ewns.perAppInfo.packageName, + ewns.perAppInfo.uid); + return false; + } + WifiConfiguration config = ewns.wns.wifiConfiguration; + PasspointConfiguration passpointConfiguration = ewns.wns.passpointConfiguration; + int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + if (config == null) { + Log.e(TAG, "WifiConfiguration is missing for " + ewns); + return false; + } + if (passpointConfiguration != null) { + // If passpoint config is not SIM based return true. + if (passpointConfiguration.getCredential().getSimCredential() == null) { + return true; + } + subId = mTelephonyUtil.getMatchingSubId(passpointConfiguration.getCarrierId()); + } else { + // If Wifi Config is not SIM based return true. + if (config.enterpriseConfig == null + || !config.enterpriseConfig.isAuthenticationSimBased()) { + return true; + } + subId = mTelephonyUtil.getBestMatchSubscriptionId(config); + } + + if (!mTelephonyUtil.isSimPresent(subId)) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "SIM is not present for subId: " + subId); + } + return false; + } + if (mTelephonyUtil.requiresImsiEncryption(subId) + && !mTelephonyUtil.isImsiEncryptionInfoAvailable(subId)) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "IMSI encryption is required but info is missing for subId: " + + subId); + } + return false; + } + if (!mTelephonyUtil.requiresImsiEncryption(subId)) { + // TODO(142001564): sendImsiProtectionWarningNotification(); + return false; + } + return true; + } + /** * Returns a set of all network suggestions matching the provided the WifiConfiguration. */ @@ -1405,7 +1454,6 @@ public class WifiNetworkSuggestionsManager { default: return WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_UNKNOWN; } - } /** @@ -1447,6 +1495,33 @@ public class WifiNetworkSuggestionsManager { } /** + * When SIM state changes, check if carrier privileges changes for app. + * If app changes from privileged to not privileged, remove all suggestions and reset state. + * If app changes from not privileges to privileged, set target carrier id for all suggestions. + */ + public void resetCarrierPrivilegedApps() { + Log.w(TAG, "SIM state is changed!"); + for (PerAppInfo appInfo : mActiveNetworkSuggestionsPerApp.values()) { + int carrierId = mTelephonyUtil + .getCarrierIdForPackageWithCarrierPrivileges(appInfo.packageName); + if (carrierId == appInfo.carrierId) { + continue; + } + if (carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) { + Log.v(TAG, "Carrier privilege revoked for " + appInfo.packageName); + removeInternal(Collections.EMPTY_LIST, appInfo.packageName, appInfo); + mActiveNetworkSuggestionsPerApp.remove(appInfo.packageName); + continue; + } + appInfo.carrierId = carrierId; + for (ExtendedWifiNetworkSuggestion ewns : appInfo.extNetworkSuggestions) { + ewns.wns.wifiConfiguration.carrierId = carrierId; + } + } + saveToStore(); + } + + /** * Dump of {@link WifiNetworkSuggestionsManager}. */ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { @@ -1457,6 +1532,8 @@ public class WifiNetworkSuggestionsManager { pw.println("Package Name: " + networkSuggestionsEntry.getKey()); PerAppInfo appInfo = networkSuggestionsEntry.getValue(); pw.println("Has user approved: " + appInfo.hasUserApproved); + pw.println("Has carrier privileges: " + + (appInfo.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID)); for (ExtendedWifiNetworkSuggestion extNetworkSuggestion : appInfo.extNetworkSuggestions) { pw.println("Network: " + extNetworkSuggestion); diff --git a/service/java/com/android/server/wifi/util/TelephonyUtil.java b/service/java/com/android/server/wifi/util/TelephonyUtil.java index 22ce92571..30ccefecf 100644 --- a/service/java/com/android/server/wifi/util/TelephonyUtil.java +++ b/service/java/com/android/server/wifi/util/TelephonyUtil.java @@ -217,6 +217,7 @@ public class TelephonyUtil { /** * Gets the SubscriptionId of SIM card which is from the carrier specified in config. + * * @param config the instance of {@link WifiConfiguration} * @return the best match SubscriptionId */ @@ -228,7 +229,13 @@ public class TelephonyUtil { } } - private int getMatchingSubId(int carrierId) { + /** + * Gets the SubscriptionId of SIM card for given carrier Id + * + * @param carrierId carrier id for target carrier + * @return the matched SubscriptionId + */ + public int getMatchingSubId(int carrierId) { List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); if (subInfoList == null || subInfoList.isEmpty()) { return SubscriptionManager.INVALID_SUBSCRIPTION_ID; @@ -1108,4 +1115,28 @@ public class TelephonyUtil { pw.println("mImsiEncryptionRequired=" + mImsiEncryptionRequired); pw.println("mImsiEncryptionInfoAvailable=" + mImsiEncryptionInfoAvailable); } + + /** + * Get the carrier ID {@link TelephonyManager#getSimCarrierId()} of the carrier which give + * target package carrier privileges. + * + * @param packageName target package to check if grant privileges by any carrier. + * @return Carrier ID who give privilege to this package. If package isn't granted privilege + * by any available carrier, will return UNKNOWN_CARRIER_ID. + */ + public int getCarrierIdForPackageWithCarrierPrivileges(String packageName) { + List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); + if (subInfoList == null || subInfoList.isEmpty()) { + return TelephonyManager.UNKNOWN_CARRIER_ID; + } + for (SubscriptionInfo info : subInfoList) { + TelephonyManager specifiedTm = + mTelephonyManager.createForSubscriptionId(info.getSubscriptionId()); + if (specifiedTm.checkCarrierPrivilegesForPackage(packageName) + == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { + return info.getCarrierId(); + } + } + return TelephonyManager.UNKNOWN_CARRIER_ID; + } } |