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>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