1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package android.net; 18 19 import android.Manifest.permission; 20 import android.annotation.IntDef; 21 import android.annotation.Nullable; 22 import android.annotation.RequiresPermission; 23 import android.annotation.SdkConstant; 24 import android.annotation.SdkConstant.SdkConstantType; 25 import android.annotation.SystemApi; 26 import android.annotation.SystemService; 27 import android.content.Context; 28 import android.os.RemoteException; 29 import android.os.ServiceManager; 30 import android.os.ServiceManager.ServiceNotFoundException; 31 32 import java.lang.annotation.Retention; 33 import java.lang.annotation.RetentionPolicy; 34 import java.util.List; 35 36 /** 37 * Class that manages communication between network subsystems and a network scorer. 38 * 39 * <p>A network scorer is any application which: 40 * <ul> 41 * <li>Is granted the {@link permission#SCORE_NETWORKS} permission. 42 * <li>Is granted the {@link permission#ACCESS_COARSE_LOCATION} permission. 43 * <li>Include a Service for the {@link #ACTION_RECOMMEND_NETWORKS} action 44 * protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE} 45 * permission. 46 * </ul> 47 * 48 * @hide 49 */ 50 @SystemApi 51 @SystemService(Context.NETWORK_SCORE_SERVICE) 52 public class NetworkScoreManager { 53 /** 54 * Activity action: ask the user to change the active network scorer. This will show a dialog 55 * that asks the user whether they want to replace the current active scorer with the one 56 * specified in {@link #EXTRA_PACKAGE_NAME}. The activity will finish with RESULT_OK if the 57 * active scorer was changed or RESULT_CANCELED if it failed for any reason. 58 */ 59 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 60 public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE"; 61 62 /** 63 * Extra used with {@link #ACTION_CHANGE_ACTIVE} to specify the new scorer package. Set with 64 * {@link android.content.Intent#putExtra(String, String)}. 65 */ 66 public static final String EXTRA_PACKAGE_NAME = "packageName"; 67 68 /** 69 * Broadcast action: new network scores are being requested. This intent will only be delivered 70 * to the current active scorer app. That app is responsible for scoring the networks and 71 * calling {@link #updateScores} when complete. The networks to score are specified in 72 * {@link #EXTRA_NETWORKS_TO_SCORE}, and will generally consist of all networks which have been 73 * configured by the user as well as any open networks. 74 * 75 * <p class="note">This is a protected intent that can only be sent by the system. 76 */ 77 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 78 public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS"; 79 80 /** 81 * Extra used with {@link #ACTION_SCORE_NETWORKS} to specify the networks to be scored, as an 82 * array of {@link NetworkKey}s. Can be obtained with 83 * {@link android.content.Intent#getParcelableArrayExtra(String)}}. 84 */ 85 public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore"; 86 87 /** 88 * Activity action: launch an activity for configuring a provider for the feature that connects 89 * and secures open wifi networks available before enabling it. Applications that enable this 90 * feature must provide an activity for this action. The framework will launch this activity 91 * which must return RESULT_OK if the feature should be enabled. 92 */ 93 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 94 public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE"; 95 96 /** 97 * Meta-data specified on a {@link NetworkRecommendationProvider} that provides a user-visible 98 * label of the recommendation service. 99 * @hide 100 */ 101 public static final String RECOMMENDATION_SERVICE_LABEL_META_DATA = 102 "android.net.scoring.recommendation_service_label"; 103 104 /** 105 * Meta-data specified on a {@link NetworkRecommendationProvider} that specified the package 106 * name of the application that connects and secures open wifi networks automatically. The 107 * specified package must provide an Activity for {@link #ACTION_CUSTOM_ENABLE}. 108 * @hide 109 */ 110 public static final String USE_OPEN_WIFI_PACKAGE_META_DATA = 111 "android.net.wifi.use_open_wifi_package"; 112 113 /** 114 * Meta-data specified on a {@link NetworkRecommendationProvider} that specifies the 115 * {@link android.app.NotificationChannel} ID used to post open network notifications. 116 * @hide 117 */ 118 public static final String NETWORK_AVAILABLE_NOTIFICATION_CHANNEL_ID_META_DATA = 119 "android.net.wifi.notification_channel_id_network_available"; 120 121 /** 122 * Broadcast action: the active scorer has been changed. Scorer apps may listen to this to 123 * perform initialization once selected as the active scorer, or clean up unneeded resources 124 * if another scorer has been selected. This is an explicit broadcast only sent to the 125 * previous scorer and new scorer. Note that it is unnecessary to clear existing scores as 126 * this is handled by the system. 127 * 128 * <p>The new scorer will be specified in {@link #EXTRA_NEW_SCORER}. 129 * 130 * <p class="note">This is a protected intent that can only be sent by the system. 131 */ 132 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 133 public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED"; 134 135 /** 136 * Service action: Used to discover and bind to a network recommendation provider. 137 * Implementations should return {@link NetworkRecommendationProvider#getBinder()} from 138 * their <code>onBind()</code> method. 139 */ 140 @SdkConstant(SdkConstantType.SERVICE_ACTION) 141 public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS"; 142 143 /** 144 * Extra used with {@link #ACTION_SCORER_CHANGED} to specify the newly selected scorer's package 145 * name. Will be null if scoring was disabled. Can be obtained with 146 * {@link android.content.Intent#getStringExtra(String)}. 147 */ 148 public static final String EXTRA_NEW_SCORER = "newScorer"; 149 150 /** @hide */ 151 @IntDef({CACHE_FILTER_NONE, CACHE_FILTER_CURRENT_NETWORK, CACHE_FILTER_SCAN_RESULTS}) 152 @Retention(RetentionPolicy.SOURCE) 153 public @interface CacheUpdateFilter {} 154 155 /** 156 * Do not filter updates sent to the cache. 157 * @hide 158 */ 159 public static final int CACHE_FILTER_NONE = 0; 160 161 /** 162 * Only send cache updates when the network matches the connected network. 163 * @hide 164 */ 165 public static final int CACHE_FILTER_CURRENT_NETWORK = 1; 166 167 /** 168 * Only send cache updates when the network is part of the current scan result set. 169 * @hide 170 */ 171 public static final int CACHE_FILTER_SCAN_RESULTS = 2; 172 173 /** @hide */ 174 @IntDef({RECOMMENDATIONS_ENABLED_FORCED_OFF, RECOMMENDATIONS_ENABLED_OFF, 175 RECOMMENDATIONS_ENABLED_ON}) 176 @Retention(RetentionPolicy.SOURCE) 177 public @interface RecommendationsEnabledSetting {} 178 179 /** 180 * Recommendations have been forced off. 181 * <p> 182 * This value is never set by any of the NetworkScore classes, it must be set via other means. 183 * This state is also "sticky" and we won't transition out of this state once entered. To move 184 * to a different state this value has to be explicitly set to a different value via 185 * other means. 186 * @hide 187 */ 188 public static final int RECOMMENDATIONS_ENABLED_FORCED_OFF = -1; 189 190 /** 191 * Recommendations are not enabled. 192 * <p> 193 * This is a transient state that can be entered when the default recommendation app is enabled 194 * but no longer valid. This state will transition to RECOMMENDATIONS_ENABLED_ON when a valid 195 * recommendation app is enabled. 196 * @hide 197 */ 198 public static final int RECOMMENDATIONS_ENABLED_OFF = 0; 199 200 /** 201 * Recommendations are enabled. 202 * <p> 203 * This is a transient state that means a valid recommendation app is active. This state will 204 * transition to RECOMMENDATIONS_ENABLED_OFF if the current and default recommendation apps 205 * become invalid. 206 * @hide 207 */ 208 public static final int RECOMMENDATIONS_ENABLED_ON = 1; 209 210 private final Context mContext; 211 private final INetworkScoreService mService; 212 213 /** @hide */ 214 public NetworkScoreManager(Context context) throws ServiceNotFoundException { 215 mContext = context; 216 mService = INetworkScoreService.Stub 217 .asInterface(ServiceManager.getServiceOrThrow(Context.NETWORK_SCORE_SERVICE)); 218 } 219 220 /** 221 * Obtain the package name of the current active network scorer. 222 * 223 * <p>At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS} 224 * broadcasts and be allowed to call {@link #updateScores}. Applications may use this method to 225 * determine the current scorer and offer the user the ability to select a different scorer via 226 * the {@link #ACTION_CHANGE_ACTIVE} intent. 227 * @return the full package name of the current active scorer, or null if there is no active 228 * scorer. 229 * @throws SecurityException if the caller doesn't hold either {@link permission#SCORE_NETWORKS} 230 * or {@link permission#REQUEST_NETWORK_SCORES} permissions. 231 */ 232 @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS, 233 android.Manifest.permission.REQUEST_NETWORK_SCORES}) 234 public String getActiveScorerPackage() { 235 try { 236 return mService.getActiveScorerPackage(); 237 } catch (RemoteException e) { 238 throw e.rethrowFromSystemServer(); 239 } 240 } 241 242 /** 243 * Returns metadata about the active scorer or <code>null</code> if there is no active scorer. 244 * 245 * @throws SecurityException if the caller does not hold the 246 * {@link permission#REQUEST_NETWORK_SCORES} permission. 247 * @hide 248 */ 249 @Nullable 250 @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) 251 public NetworkScorerAppData getActiveScorer() { 252 try { 253 return mService.getActiveScorer(); 254 } catch (RemoteException e) { 255 throw e.rethrowFromSystemServer(); 256 } 257 } 258 259 /** 260 * Returns the list of available scorer apps. The list will be empty if there are 261 * no valid scorers. 262 * 263 * @throws SecurityException if the caller does not hold the 264 * {@link permission#REQUEST_NETWORK_SCORES} permission. 265 * @hide 266 */ 267 @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) 268 public List<NetworkScorerAppData> getAllValidScorers() { 269 try { 270 return mService.getAllValidScorers(); 271 } catch (RemoteException e) { 272 throw e.rethrowFromSystemServer(); 273 } 274 } 275 276 /** 277 * Update network scores. 278 * 279 * <p>This may be called at any time to re-score active networks. Scores will generally be 280 * updated quickly, but if this method is called too frequently, the scores may be held and 281 * applied at a later time. 282 * 283 * @param networks the networks which have been scored by the scorer. 284 * @return whether the update was successful. 285 * @throws SecurityException if the caller is not the active scorer. 286 */ 287 @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) 288 public boolean updateScores(ScoredNetwork[] networks) throws SecurityException { 289 try { 290 return mService.updateScores(networks); 291 } catch (RemoteException e) { 292 throw e.rethrowFromSystemServer(); 293 } 294 } 295 296 /** 297 * Clear network scores. 298 * 299 * <p>Should be called when all scores need to be invalidated, i.e. because the scoring 300 * algorithm has changed and old scores can no longer be compared to future scores. 301 * 302 * <p>Note that scores will be cleared automatically when the active scorer changes, as scores 303 * from one scorer cannot be compared to those from another scorer. 304 * 305 * @return whether the clear was successful. 306 * @throws SecurityException if the caller is not the active scorer or if the caller doesn't 307 * hold the {@link permission#REQUEST_NETWORK_SCORES} permission. 308 */ 309 @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS, 310 android.Manifest.permission.REQUEST_NETWORK_SCORES}) 311 public boolean clearScores() throws SecurityException { 312 try { 313 return mService.clearScores(); 314 } catch (RemoteException e) { 315 throw e.rethrowFromSystemServer(); 316 } 317 } 318 319 /** 320 * Set the active scorer to a new package and clear existing scores. 321 * 322 * <p>Should never be called directly without obtaining user consent. This can be done by using 323 * the {@link #ACTION_CHANGE_ACTIVE} broadcast, or using a custom configuration activity. 324 * 325 * @return true if the operation succeeded, or false if the new package is not a valid scorer. 326 * @throws SecurityException if the caller doesn't hold either {@link permission#SCORE_NETWORKS} 327 * or {@link permission#REQUEST_NETWORK_SCORES} permissions. 328 * @hide 329 */ 330 @SystemApi 331 @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS, 332 android.Manifest.permission.REQUEST_NETWORK_SCORES}) 333 public boolean setActiveScorer(String packageName) throws SecurityException { 334 try { 335 return mService.setActiveScorer(packageName); 336 } catch (RemoteException e) { 337 throw e.rethrowFromSystemServer(); 338 } 339 } 340 341 /** 342 * Turn off network scoring. 343 * 344 * <p>May only be called by the current scorer app, or the system. 345 * 346 * @throws SecurityException if the caller is not the active scorer or if the caller doesn't 347 * hold the {@link permission#REQUEST_NETWORK_SCORES} permission. 348 */ 349 @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS, 350 android.Manifest.permission.REQUEST_NETWORK_SCORES}) 351 public void disableScoring() throws SecurityException { 352 try { 353 mService.disableScoring(); 354 } catch (RemoteException e) { 355 throw e.rethrowFromSystemServer(); 356 } 357 } 358 359 /** 360 * Request scoring for networks. 361 * 362 * @return true if the broadcast was sent, or false if there is no active scorer. 363 * @throws SecurityException if the caller does not hold the 364 * {@link permission#REQUEST_NETWORK_SCORES} permission. 365 * @hide 366 */ 367 @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) 368 public boolean requestScores(NetworkKey[] networks) throws SecurityException { 369 try { 370 return mService.requestScores(networks); 371 } catch (RemoteException e) { 372 throw e.rethrowFromSystemServer(); 373 } 374 } 375 376 /** 377 * Register a network score cache. 378 * 379 * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. 380 * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. 381 * @throws SecurityException if the caller does not hold the 382 * {@link permission#REQUEST_NETWORK_SCORES} permission. 383 * @throws IllegalArgumentException if a score cache is already registered for this type. 384 * @deprecated equivalent to registering for cache updates with CACHE_FILTER_NONE. 385 * @hide 386 */ 387 @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) 388 @Deprecated // migrate to registerNetworkScoreCache(int, INetworkScoreCache, int) 389 public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { 390 registerNetworkScoreCache(networkType, scoreCache, CACHE_FILTER_NONE); 391 } 392 393 /** 394 * Register a network score cache. 395 * 396 * @param networkType the type of network this cache can handle. See {@link NetworkKey#type} 397 * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores 398 * @param filterType the {@link CacheUpdateFilter} to apply 399 * @throws SecurityException if the caller does not hold the 400 * {@link permission#REQUEST_NETWORK_SCORES} permission. 401 * @throws IllegalArgumentException if a score cache is already registered for this type. 402 * @hide 403 */ 404 @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) 405 public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache, 406 @CacheUpdateFilter int filterType) { 407 try { 408 mService.registerNetworkScoreCache(networkType, scoreCache, filterType); 409 } catch (RemoteException e) { 410 throw e.rethrowFromSystemServer(); 411 } 412 } 413 414 /** 415 * Unregister a network score cache. 416 * 417 * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. 418 * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. 419 * @throws SecurityException if the caller does not hold the 420 * {@link permission#REQUEST_NETWORK_SCORES} permission. 421 * @throws IllegalArgumentException if a score cache is already registered for this type. 422 * @hide 423 */ 424 @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) 425 public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { 426 try { 427 mService.unregisterNetworkScoreCache(networkType, scoreCache); 428 } catch (RemoteException e) { 429 throw e.rethrowFromSystemServer(); 430 } 431 } 432 433 /** 434 * Determine whether the application with the given UID is the enabled scorer. 435 * 436 * @param callingUid the UID to check 437 * @return true if the provided UID is the active scorer, false otherwise. 438 * @throws SecurityException if the caller does not hold the 439 * {@link permission#REQUEST_NETWORK_SCORES} permission. 440 * @hide 441 */ 442 @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) 443 public boolean isCallerActiveScorer(int callingUid) { 444 try { 445 return mService.isCallerActiveScorer(callingUid); 446 } catch (RemoteException e) { 447 throw e.rethrowFromSystemServer(); 448 } 449 } 450 } 451