Home | History | Annotate | Download | only in net
      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