NetworkScoreService.java revision 6a4b220f1263d95fdefe6361c2bc87bbb04bbed0
16a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson/* 26a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * Copyright (C) 2014 The Android Open Source Project 36a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * 46a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * Licensed under the Apache License, Version 2.0 (the "License"); 56a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * you may not use this file except in compliance with the License. 66a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * You may obtain a copy of the License at 76a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * 86a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * http://www.apache.org/licenses/LICENSE-2.0 96a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * 106a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * Unless required by applicable law or agreed to in writing, software 116a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * distributed under the License is distributed on an "AS IS" BASIS, 126a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * See the License for the specific language governing permissions and 146a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * limitations under the License 156a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson */ 166a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 176a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonpackage com.android.server; 186a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 196a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport android.Manifest.permission; 206a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport android.content.Context; 216a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport android.content.SharedPreferences; 226a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport android.content.pm.PackageManager; 236a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport android.net.INetworkScoreService; 246a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport android.net.NetworkKey; 256a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport android.net.NetworkScorerAppManager; 266a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport android.net.RssiCurve; 276a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport android.net.ScoredNetwork; 286a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport android.text.TextUtils; 296a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 306a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport com.android.internal.R; 316a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 326a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport java.io.FileDescriptor; 336a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport java.io.PrintWriter; 346a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport java.util.HashMap; 356a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonimport java.util.Map; 366a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 376a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson/** 386a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * Backing service for {@link android.net.NetworkScoreManager}. 396a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson * @hide 406a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson */ 416a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidsonpublic class NetworkScoreService extends INetworkScoreService.Stub { 426a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson private static final String TAG = "NetworkScoreService"; 436a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 446a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson /** SharedPreference bit set to true after the service is first initialized. */ 456a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson private static final String PREF_SCORING_PROVISIONED = "is_provisioned"; 466a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 476a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson private final Context mContext; 486a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 496a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson // TODO: Delete this temporary class once we have a real place for scores. 506a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson private final Map<NetworkKey, RssiCurve> mScoredNetworks; 516a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 526a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson public NetworkScoreService(Context context) { 536a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson mContext = context; 546a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson mScoredNetworks = new HashMap<>(); 556a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 566a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 576a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson /** Called when the system is ready to run third-party code but before it actually does so. */ 586a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson void systemReady() { 596a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson SharedPreferences prefs = mContext.getSharedPreferences(TAG, Context.MODE_PRIVATE); 606a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson if (!prefs.getBoolean(PREF_SCORING_PROVISIONED, false)) { 616a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson // On first run, we try to initialize the scorer to the one configured at build time. 626a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson // This will be a no-op if the scorer isn't actually valid. 636a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson String defaultPackage = mContext.getResources().getString( 646a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson R.string.config_defaultNetworkScorerPackageName); 656a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson if (!TextUtils.isEmpty(defaultPackage)) { 666a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson NetworkScorerAppManager.setActiveScorer(mContext, defaultPackage); 676a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 686a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson prefs.edit().putBoolean(PREF_SCORING_PROVISIONED, true).apply(); 696a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 706a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 716a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 726a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson @Override 736a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson public boolean updateScores(ScoredNetwork[] networks) { 746a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson if (!NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid())) { 756a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson throw new SecurityException("Caller with UID " + getCallingUid() + 766a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson " is not the active scorer."); 776a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 786a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 796a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson // TODO: Propagate these scores down to the network subsystem layer instead of just holding 806a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson // them in memory. 816a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson for (ScoredNetwork network : networks) { 826a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson mScoredNetworks.put(network.networkKey, network.rssiCurve); 836a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 846a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 856a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson return true; 866a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 876a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 886a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson @Override 896a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson public boolean clearScores() { 906a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson // Only the active scorer or the system (who can broadcast BROADCAST_SCORE_NETWORKS) should 916a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson // be allowed to flush all scores. 926a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson if (NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid()) || 936a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson mContext.checkCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS) == 946a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson PackageManager.PERMISSION_GRANTED) { 956a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson clearInternal(); 966a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson return true; 976a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } else { 986a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson throw new SecurityException( 996a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson "Caller is neither the active scorer nor the scorer manager."); 1006a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 1016a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 1026a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 1036a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson @Override 1046a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson public boolean setActiveScorer(String packageName) { 1056a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson mContext.enforceCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS, TAG); 1066a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson // Preemptively clear scores even though the set operation could fail. We do this for safety 1076a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson // as scores should never be compared across apps; in practice, Settings should only be 1086a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson // allowing valid apps to be set as scorers, so failure here should be rare. 1096a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson clearInternal(); 1106a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson return NetworkScorerAppManager.setActiveScorer(mContext, packageName); 1116a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 1126a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 1136a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson /** Clear scores. Callers are responsible for checking permissions as appropriate. */ 1146a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson private void clearInternal() { 1156a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson // TODO: Propagate the flush down to the network subsystem layer. 1166a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson mScoredNetworks.clear(); 1176a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 1186a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson 1196a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson @Override 1206a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1216a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG); 1226a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson String currentScorer = NetworkScorerAppManager.getActiveScorer(mContext); 1236a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson if (currentScorer == null) { 1246a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson writer.println("Scoring is disabled."); 1256a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson return; 1266a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 1276a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson writer.println("Current scorer: " + currentScorer); 1286a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson if (mScoredNetworks.isEmpty()) { 1296a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson writer.println("No networks scored."); 1306a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } else { 1316a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson for (Map.Entry<NetworkKey, RssiCurve> entry : mScoredNetworks.entrySet()) { 1326a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson writer.println(entry.getKey() + ": " + entry.getValue()); 1336a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 1346a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 1356a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson } 1366a4b220f1263d95fdefe6361c2bc87bbb04bbed0Jeff Davidson} 137