| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License |
| */ |
| |
| package android.net; |
| |
| import android.Manifest.permission; |
| import android.annotation.SystemApi; |
| import android.content.Context; |
| import android.os.Build; |
| import android.os.Handler; |
| import android.os.IBinder; |
| import android.os.RemoteException; |
| import android.util.Log; |
| |
| import com.android.internal.util.Preconditions; |
| |
| import java.util.concurrent.Executor; |
| |
| /** |
| * The base class for implementing a network recommendation provider. |
| * <p> |
| * A network recommendation provider is any application which: |
| * <ul> |
| * <li>Is granted the {@link permission#SCORE_NETWORKS} permission. |
| * <li>Is granted the {@link permission#ACCESS_COARSE_LOCATION} permission. |
| * <li>Includes a Service for the {@link NetworkScoreManager#ACTION_RECOMMEND_NETWORKS} intent |
| * which is protected by the {@link permission#BIND_NETWORK_RECOMMENDATION_SERVICE} permission. |
| * </ul> |
| * <p> |
| * Implementations are required to implement the abstract methods in this class and return the |
| * result of {@link #getBinder()} from the <code>onBind()</code> method in their Service. |
| * <p> |
| * The default network recommendation provider is controlled via the |
| * <code>config_defaultNetworkRecommendationProviderPackage</code> config key. |
| * @hide |
| */ |
| @SystemApi |
| public abstract class NetworkRecommendationProvider { |
| private static final String TAG = "NetworkRecProvider"; |
| private static final boolean VERBOSE = Build.IS_DEBUGGABLE && Log.isLoggable(TAG, Log.VERBOSE); |
| private final IBinder mService; |
| |
| /** |
| * Constructs a new instance. |
| * @param context the current context instance. Cannot be {@code null}. |
| * @param executor used to execute the incoming requests. Cannot be {@code null}. |
| */ |
| public NetworkRecommendationProvider(Context context, Executor executor) { |
| Preconditions.checkNotNull(context); |
| Preconditions.checkNotNull(executor); |
| mService = new ServiceWrapper(context, executor); |
| } |
| |
| /** |
| * Invoked when network scores have been requested. |
| * <p> |
| * Use {@link NetworkScoreManager#updateScores(ScoredNetwork[])} to respond to score requests. |
| * |
| * @param networks a non-empty array of {@link NetworkKey}s to score. |
| */ |
| public abstract void onRequestScores(NetworkKey[] networks); |
| |
| /** |
| * Services that can handle {@link NetworkScoreManager#ACTION_RECOMMEND_NETWORKS} should |
| * return this Binder from their <code>onBind()</code> method. |
| */ |
| public final IBinder getBinder() { |
| return mService; |
| } |
| |
| /** |
| * A wrapper around INetworkRecommendationProvider that dispatches to the provided Handler. |
| */ |
| private final class ServiceWrapper extends INetworkRecommendationProvider.Stub { |
| private final Context mContext; |
| private final Executor mExecutor; |
| private final Handler mHandler; |
| |
| ServiceWrapper(Context context, Executor executor) { |
| mContext = context; |
| mExecutor = executor; |
| mHandler = null; |
| } |
| |
| @Override |
| public void requestScores(final NetworkKey[] networks) throws RemoteException { |
| enforceCallingPermission(); |
| if (networks != null && networks.length > 0) { |
| execute(new Runnable() { |
| @Override |
| public void run() { |
| onRequestScores(networks); |
| } |
| }); |
| } |
| } |
| |
| private void execute(Runnable command) { |
| if (mExecutor != null) { |
| mExecutor.execute(command); |
| } else { |
| mHandler.post(command); |
| } |
| } |
| |
| private void enforceCallingPermission() { |
| if (mContext != null) { |
| mContext.enforceCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES, |
| "Permission denied."); |
| } |
| } |
| } |
| } |