diff options
| author | 2017-02-08 20:12:50 +0000 | |
|---|---|---|
| committer | 2017-02-08 20:12:54 +0000 | |
| commit | d927a0e24e0810be637c70c9ff44755a0b10323e (patch) | |
| tree | 99447535e97e470e041d0a709e93397c14bdf333 | |
| parent | a0db8b655f2ed7a14ac4bd30f74c567253bd5031 (diff) | |
| parent | a5172f69ca02f5338b4c36ad5e9b57b9fb4fd8d2 (diff) | |
Merge "New internal interface method to get the active scorer metadata."
6 files changed, 143 insertions, 2 deletions
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl index 82432c758fa6..9cc256ec6510 100644 --- a/core/java/android/net/INetworkScoreService.aidl +++ b/core/java/android/net/INetworkScoreService.aidl @@ -18,6 +18,7 @@ package android.net; import android.net.INetworkScoreCache; import android.net.NetworkKey; +import android.net.NetworkScorerAppManager; import android.net.RecommendationRequest; import android.net.RecommendationResult; import android.net.ScoredNetwork; @@ -130,4 +131,6 @@ interface INetworkScoreService */ oneway void requestRecommendationAsync(in RecommendationRequest request, in RemoteCallback remoteCallback); + + NetworkScorerAppManager.NetworkScorerAppData getActiveScorer(); } diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index 57cf1a5c20d3..2875580971ae 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -186,6 +186,20 @@ public class NetworkScoreManager { } /** + * Returns metadata about the active scorer or <code>null</code> if there is no active scorer. + * + * @hide + */ + @Nullable + public NetworkScorerAppData getActiveScorer() { + try { + return mService.getActiveScorer(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Update network scores. * * <p>This may be called at any time to re-score active networks. Scores will generally be diff --git a/core/java/android/net/NetworkScorerAppManager.aidl b/core/java/android/net/NetworkScorerAppManager.aidl new file mode 100644 index 000000000000..d968343141b6 --- /dev/null +++ b/core/java/android/net/NetworkScorerAppManager.aidl @@ -0,0 +1,19 @@ +/** + * 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; + +parcelable NetworkScorerAppManager.NetworkScorerAppData; diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java index 9dcf4f44a559..f3cbb52e500d 100644 --- a/core/java/android/net/NetworkScorerAppManager.java +++ b/core/java/android/net/NetworkScorerAppManager.java @@ -24,6 +24,8 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.os.Parcel; +import android.os.Parcelable; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; @@ -54,7 +56,7 @@ public class NetworkScorerAppManager { /** * Holds metadata about a discovered network scorer/recommendation application. */ - public static class NetworkScorerAppData { + public static final class NetworkScorerAppData implements Parcelable { /** UID of the scorer app. */ public final int packageUid; private final ComponentName mRecommendationService; @@ -64,6 +66,35 @@ public class NetworkScorerAppManager { this.mRecommendationService = recommendationServiceComp; } + protected NetworkScorerAppData(Parcel in) { + packageUid = in.readInt(); + mRecommendationService = ComponentName.readFromParcel(in); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(packageUid); + ComponentName.writeToParcel(mRecommendationService, dest); + } + + @Override + public int describeContents() { + return 0; + } + + public static final Creator<NetworkScorerAppData> CREATOR = + new Creator<NetworkScorerAppData>() { + @Override + public NetworkScorerAppData createFromParcel(Parcel in) { + return new NetworkScorerAppData(in); + } + + @Override + public NetworkScorerAppData[] newArray(int size) { + return new NetworkScorerAppData[size]; + } + }; + public String getRecommendationServicePackageName() { return mRecommendationService.getPackageName(); } diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java index 5fe8b1a8ae9d..0ac51b90249e 100644 --- a/services/core/java/com/android/server/NetworkScoreService.java +++ b/services/core/java/com/android/server/NetworkScoreService.java @@ -53,6 +53,7 @@ import android.os.IBinder; import android.os.IRemoteCallback; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteCallbackList; import android.os.RemoteException; @@ -676,6 +677,10 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } } + private boolean isCallerSystemProcess(int callingUid) { + return callingUid == Process.SYSTEM_UID; + } + /** * Obtain the package name of the current active network scorer. * @@ -692,6 +697,27 @@ public class NetworkScoreService extends INetworkScoreService.Stub { return null; } + + /** + * Returns metadata about the active scorer or <code>null</code> if there is no active scorer. + */ + @Override + public NetworkScorerAppData getActiveScorer() { + // Only the system can access this data. + if (isCallerSystemProcess(getCallingUid()) || callerCanRequestScores()) { + synchronized (mServiceConnectionLock) { + if (mServiceConnection != null) { + return mServiceConnection.mAppData; + } + } + } else { + throw new SecurityException( + "Caller is neither the system process nor a score requester."); + } + + return null; + } + @Override public void disableScoring() { // Only the active scorer or the system should be allowed to disable scoring. diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java index fa9e9a804e61..3a88e9c6303f 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java @@ -829,6 +829,50 @@ public class NetworkScoreServiceTest { assertEquals(expectedList, actualList); } + @Test + public void testGetActiveScorer_notConnected_canRequestScores() throws Exception { + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) + .thenReturn(PackageManager.PERMISSION_GRANTED); + assertNull(mNetworkScoreService.getActiveScorer()); + } + + @Test + public void testGetActiveScorer_notConnected_canNotRequestScores() throws Exception { + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) + .thenReturn(PackageManager.PERMISSION_DENIED); + try { + mNetworkScoreService.getActiveScorer(); + fail("SecurityException expected."); + } catch (SecurityException e) { + // expected + } + } + + @Test + public void testGetActiveScorer_connected_canRequestScores() + throws Exception { + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) + .thenReturn(PackageManager.PERMISSION_GRANTED); + NetworkScorerAppData expectedAppData = + new NetworkScorerAppData(Binder.getCallingUid(), RECOMMENDATION_SERVICE_COMP); + bindToScorer(expectedAppData); + assertEquals(expectedAppData, mNetworkScoreService.getActiveScorer()); + } + + @Test + public void testGetActiveScorer_connected_canNotRequestScores() + throws Exception { + when(mContext.checkCallingOrSelfPermission(permission.REQUEST_NETWORK_SCORES)) + .thenReturn(PackageManager.PERMISSION_DENIED); + bindToScorer(false); + try { + mNetworkScoreService.getActiveScorer(); + fail("SecurityException expected."); + } catch (SecurityException e) { + // expected + } + } + // "injects" the mock INetworkRecommendationProvider into the NetworkScoreService. private void injectProvider() { when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER); @@ -849,9 +893,13 @@ public class NetworkScoreServiceTest { } private void bindToScorer(boolean callerIsScorer) { - final int callingUid = callerIsScorer ? Binder.getCallingUid() : 0; + final int callingUid = callerIsScorer ? Binder.getCallingUid() : Binder.getCallingUid() + 1; NetworkScorerAppData appData = new NetworkScorerAppData(callingUid, RECOMMENDATION_SERVICE_COMP); + bindToScorer(appData); + } + + private void bindToScorer(NetworkScorerAppData appData) { when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(appData); when(mContext.bindServiceAsUser(isA(Intent.class), isA(ServiceConnection.class), anyInt(), isA(UserHandle.class))).thenReturn(true); |