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