Loading api/system-current.txt +2 −1 Original line number Diff line number Diff line Loading @@ -27125,7 +27125,8 @@ package android.net { } public abstract class NetworkRecommendationProvider { ctor public NetworkRecommendationProvider(android.os.Handler); ctor public deprecated NetworkRecommendationProvider(android.os.Handler); ctor public NetworkRecommendationProvider(android.content.Context, java.util.concurrent.Executor); method public final android.os.IBinder getBinder(); method public abstract void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback); method public abstract void onRequestScores(android.net.NetworkKey[]); core/java/android/net/NetworkRecommendationProvider.java +45 −2 Original line number Diff line number Diff line package android.net; import android.Manifest.permission; import android.annotation.SystemApi; import android.content.Context; import android.os.Build; import android.os.Bundle; import android.os.Handler; Loading @@ -10,8 +12,10 @@ import android.os.RemoteException; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; /** Loading @@ -32,6 +36,7 @@ public abstract class NetworkRecommendationProvider { /** * Constructs a new instance. * @param handler indicates which thread to use when handling requests. Cannot be {@code null}. * @deprecated use {@link #NetworkRecommendationProvider(Context, Executor)} */ public NetworkRecommendationProvider(Handler handler) { if (handler == null) { Loading @@ -40,6 +45,17 @@ public abstract class NetworkRecommendationProvider { mService = new ServiceWrapper(handler); } /** * 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 a recommendation has been requested. * Loading Loading @@ -130,17 +146,28 @@ public abstract class NetworkRecommendationProvider { * 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(Handler handler) { mHandler = handler; mExecutor = null; mContext = null; } ServiceWrapper(Context context, Executor executor) { mContext = context; mExecutor = executor; mHandler = null; } @Override public void requestRecommendation(final RecommendationRequest request, final IRemoteCallback callback, final int sequence) throws RemoteException { enforceCallingPermission(); if (VERBOSE) Log.v(TAG, "requestRecommendation(seq=" + sequence + ")"); mHandler.post(new Runnable() { execute(new Runnable() { @Override public void run() { if (VERBOSE) { Loading @@ -154,8 +181,9 @@ public abstract class NetworkRecommendationProvider { @Override public void requestScores(final NetworkKey[] networks) throws RemoteException { enforceCallingPermission(); if (networks != null && networks.length > 0) { mHandler.post(new Runnable() { execute(new Runnable() { @Override public void run() { onRequestScores(networks); Loading @@ -163,5 +191,20 @@ public abstract class NetworkRecommendationProvider { }); } } 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."); } } } } core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java +60 −29 Original line number Diff line number Diff line Loading @@ -3,61 +3,62 @@ package android.net; import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT; import static android.net.NetworkRecommendationProvider.EXTRA_SEQUENCE; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertSame; import static junit.framework.Assert.fail; import static junit.framework.TestCase.assertEquals; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import android.Manifest.permission; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IRemoteCallback; import android.test.InstrumentationTestCase; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; import android.support.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * Unit test for the {@link NetworkRecommendationProvider}. */ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { @RunWith(AndroidJUnit4.class) public class NetworkRecommendationProviderTest { @Mock private IRemoteCallback mMockRemoteCallback; @Mock private Context mContext; private NetworkRecProvider mRecProvider; private Handler mHandler; private INetworkRecommendationProvider mStub; private CountDownLatch mRecRequestLatch; private CountDownLatch mScoreRequestLatch; private NetworkKey[] mTestNetworkKeys; @Override @Before public void setUp() throws Exception { super.setUp(); // Configuration needed to make mockito/dexcache work. final Context context = getInstrumentation().getTargetContext(); System.setProperty("dexmaker.dexcache", context.getCacheDir().getPath()); ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader(); Thread.currentThread().setContextClassLoader(newClassLoader); MockitoAnnotations.initMocks(this); HandlerThread thread = new HandlerThread("NetworkRecommendationProviderTest"); thread.start(); Executor executor = Executors.newSingleThreadExecutor(); mRecRequestLatch = new CountDownLatch(1); mScoreRequestLatch = new CountDownLatch(1); mHandler = new Handler(thread.getLooper()); mRecProvider = new NetworkRecProvider(mHandler, mRecRequestLatch, mScoreRequestLatch); mRecProvider = new NetworkRecProvider(mContext, executor, mRecRequestLatch, mScoreRequestLatch); mStub = INetworkRecommendationProvider.Stub.asInterface(mRecProvider.getBinder()); mTestNetworkKeys = new NetworkKey[2]; mTestNetworkKeys[0] = new NetworkKey(new WifiKey("\"ssid_01\"", "00:00:00:00:00:11")); mTestNetworkKeys[1] = new NetworkKey(new WifiKey("\"ssid_02\"", "00:00:00:00:00:22")); } @MediumTest @Test public void testRecommendationRequestReceived() throws Exception { final RecommendationRequest request = new RecommendationRequest.Builder().build(); final int sequence = 100; Loading @@ -71,7 +72,23 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { assertEquals(expectedResultCallback, mRecProvider.mCapturedCallback); } @SmallTest @Test public void testRecommendationRequest_permissionsEnforced() throws Exception { final RecommendationRequest request = new RecommendationRequest.Builder().build(); final int sequence = 100; Mockito.doThrow(new SecurityException()) .when(mContext) .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString()); try { mStub.requestRecommendation(request, mMockRemoteCallback, sequence); fail("SecurityException expected."); } catch (SecurityException e) { // expected } } @Test public void testResultCallbackOnResult() throws Exception { final int sequence = 100; final NetworkRecommendationProvider.ResultCallback callback = Loading @@ -87,7 +104,7 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { assertSame(result, capturedBundle.getParcelable(EXTRA_RECOMMENDATION_RESULT)); } @SmallTest @Test public void testResultCallbackOnResult_runTwice_throwsException() throws Exception { final int sequence = 100; final NetworkRecommendationProvider.ResultCallback callback = Loading @@ -104,7 +121,7 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { } } @MediumTest @Test public void testScoreRequestReceived() throws Exception { mStub.requestScores(mTestNetworkKeys); Loading @@ -114,7 +131,7 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { assertSame(mTestNetworkKeys, mRecProvider.mCapturedNetworks); } @MediumTest @Test public void testScoreRequest_nullInput() throws Exception { mStub.requestScores(null); Loading @@ -122,7 +139,7 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS)); } @MediumTest @Test public void testScoreRequest_emptyInput() throws Exception { mStub.requestScores(new NetworkKey[0]); Loading @@ -130,6 +147,20 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS)); } @Test public void testScoreRequest_permissionsEnforced() throws Exception { Mockito.doThrow(new SecurityException()) .when(mContext) .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString()); try { mStub.requestScores(mTestNetworkKeys); fail("SecurityException expected."); } catch (SecurityException e) { // expected } } private static class NetworkRecProvider extends NetworkRecommendationProvider { private final CountDownLatch mRecRequestLatch; private final CountDownLatch mScoreRequestLatch; Loading @@ -137,9 +168,9 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { ResultCallback mCapturedCallback; NetworkKey[] mCapturedNetworks; NetworkRecProvider(Handler handler, CountDownLatch recRequestLatch, NetworkRecProvider(Context context, Executor executor, CountDownLatch recRequestLatch, CountDownLatch networkRequestLatch) { super(handler); super(context, executor); mRecRequestLatch = recRequestLatch; mScoreRequestLatch = networkRequestLatch; } Loading Loading
api/system-current.txt +2 −1 Original line number Diff line number Diff line Loading @@ -27125,7 +27125,8 @@ package android.net { } public abstract class NetworkRecommendationProvider { ctor public NetworkRecommendationProvider(android.os.Handler); ctor public deprecated NetworkRecommendationProvider(android.os.Handler); ctor public NetworkRecommendationProvider(android.content.Context, java.util.concurrent.Executor); method public final android.os.IBinder getBinder(); method public abstract void onRequestRecommendation(android.net.RecommendationRequest, android.net.NetworkRecommendationProvider.ResultCallback); method public abstract void onRequestScores(android.net.NetworkKey[]);
core/java/android/net/NetworkRecommendationProvider.java +45 −2 Original line number Diff line number Diff line package android.net; import android.Manifest.permission; import android.annotation.SystemApi; import android.content.Context; import android.os.Build; import android.os.Bundle; import android.os.Handler; Loading @@ -10,8 +12,10 @@ import android.os.RemoteException; import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.Preconditions; import java.util.Objects; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicBoolean; /** Loading @@ -32,6 +36,7 @@ public abstract class NetworkRecommendationProvider { /** * Constructs a new instance. * @param handler indicates which thread to use when handling requests. Cannot be {@code null}. * @deprecated use {@link #NetworkRecommendationProvider(Context, Executor)} */ public NetworkRecommendationProvider(Handler handler) { if (handler == null) { Loading @@ -40,6 +45,17 @@ public abstract class NetworkRecommendationProvider { mService = new ServiceWrapper(handler); } /** * 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 a recommendation has been requested. * Loading Loading @@ -130,17 +146,28 @@ public abstract class NetworkRecommendationProvider { * 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(Handler handler) { mHandler = handler; mExecutor = null; mContext = null; } ServiceWrapper(Context context, Executor executor) { mContext = context; mExecutor = executor; mHandler = null; } @Override public void requestRecommendation(final RecommendationRequest request, final IRemoteCallback callback, final int sequence) throws RemoteException { enforceCallingPermission(); if (VERBOSE) Log.v(TAG, "requestRecommendation(seq=" + sequence + ")"); mHandler.post(new Runnable() { execute(new Runnable() { @Override public void run() { if (VERBOSE) { Loading @@ -154,8 +181,9 @@ public abstract class NetworkRecommendationProvider { @Override public void requestScores(final NetworkKey[] networks) throws RemoteException { enforceCallingPermission(); if (networks != null && networks.length > 0) { mHandler.post(new Runnable() { execute(new Runnable() { @Override public void run() { onRequestScores(networks); Loading @@ -163,5 +191,20 @@ public abstract class NetworkRecommendationProvider { }); } } 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."); } } } }
core/tests/coretests/src/android/net/NetworkRecommendationProviderTest.java +60 −29 Original line number Diff line number Diff line Loading @@ -3,61 +3,62 @@ package android.net; import static android.net.NetworkRecommendationProvider.EXTRA_RECOMMENDATION_RESULT; import static android.net.NetworkRecommendationProvider.EXTRA_SEQUENCE; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertSame; import static junit.framework.Assert.fail; import static junit.framework.TestCase.assertEquals; import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.eq; import android.Manifest.permission; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.os.IRemoteCallback; import android.test.InstrumentationTestCase; import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.SmallTest; import android.support.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * Unit test for the {@link NetworkRecommendationProvider}. */ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { @RunWith(AndroidJUnit4.class) public class NetworkRecommendationProviderTest { @Mock private IRemoteCallback mMockRemoteCallback; @Mock private Context mContext; private NetworkRecProvider mRecProvider; private Handler mHandler; private INetworkRecommendationProvider mStub; private CountDownLatch mRecRequestLatch; private CountDownLatch mScoreRequestLatch; private NetworkKey[] mTestNetworkKeys; @Override @Before public void setUp() throws Exception { super.setUp(); // Configuration needed to make mockito/dexcache work. final Context context = getInstrumentation().getTargetContext(); System.setProperty("dexmaker.dexcache", context.getCacheDir().getPath()); ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader(); Thread.currentThread().setContextClassLoader(newClassLoader); MockitoAnnotations.initMocks(this); HandlerThread thread = new HandlerThread("NetworkRecommendationProviderTest"); thread.start(); Executor executor = Executors.newSingleThreadExecutor(); mRecRequestLatch = new CountDownLatch(1); mScoreRequestLatch = new CountDownLatch(1); mHandler = new Handler(thread.getLooper()); mRecProvider = new NetworkRecProvider(mHandler, mRecRequestLatch, mScoreRequestLatch); mRecProvider = new NetworkRecProvider(mContext, executor, mRecRequestLatch, mScoreRequestLatch); mStub = INetworkRecommendationProvider.Stub.asInterface(mRecProvider.getBinder()); mTestNetworkKeys = new NetworkKey[2]; mTestNetworkKeys[0] = new NetworkKey(new WifiKey("\"ssid_01\"", "00:00:00:00:00:11")); mTestNetworkKeys[1] = new NetworkKey(new WifiKey("\"ssid_02\"", "00:00:00:00:00:22")); } @MediumTest @Test public void testRecommendationRequestReceived() throws Exception { final RecommendationRequest request = new RecommendationRequest.Builder().build(); final int sequence = 100; Loading @@ -71,7 +72,23 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { assertEquals(expectedResultCallback, mRecProvider.mCapturedCallback); } @SmallTest @Test public void testRecommendationRequest_permissionsEnforced() throws Exception { final RecommendationRequest request = new RecommendationRequest.Builder().build(); final int sequence = 100; Mockito.doThrow(new SecurityException()) .when(mContext) .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString()); try { mStub.requestRecommendation(request, mMockRemoteCallback, sequence); fail("SecurityException expected."); } catch (SecurityException e) { // expected } } @Test public void testResultCallbackOnResult() throws Exception { final int sequence = 100; final NetworkRecommendationProvider.ResultCallback callback = Loading @@ -87,7 +104,7 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { assertSame(result, capturedBundle.getParcelable(EXTRA_RECOMMENDATION_RESULT)); } @SmallTest @Test public void testResultCallbackOnResult_runTwice_throwsException() throws Exception { final int sequence = 100; final NetworkRecommendationProvider.ResultCallback callback = Loading @@ -104,7 +121,7 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { } } @MediumTest @Test public void testScoreRequestReceived() throws Exception { mStub.requestScores(mTestNetworkKeys); Loading @@ -114,7 +131,7 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { assertSame(mTestNetworkKeys, mRecProvider.mCapturedNetworks); } @MediumTest @Test public void testScoreRequest_nullInput() throws Exception { mStub.requestScores(null); Loading @@ -122,7 +139,7 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS)); } @MediumTest @Test public void testScoreRequest_emptyInput() throws Exception { mStub.requestScores(new NetworkKey[0]); Loading @@ -130,6 +147,20 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { assertFalse(mScoreRequestLatch.await(200, TimeUnit.MILLISECONDS)); } @Test public void testScoreRequest_permissionsEnforced() throws Exception { Mockito.doThrow(new SecurityException()) .when(mContext) .enforceCallingOrSelfPermission(eq(permission.REQUEST_NETWORK_SCORES), anyString()); try { mStub.requestScores(mTestNetworkKeys); fail("SecurityException expected."); } catch (SecurityException e) { // expected } } private static class NetworkRecProvider extends NetworkRecommendationProvider { private final CountDownLatch mRecRequestLatch; private final CountDownLatch mScoreRequestLatch; Loading @@ -137,9 +168,9 @@ public class NetworkRecommendationProviderTest extends InstrumentationTestCase { ResultCallback mCapturedCallback; NetworkKey[] mCapturedNetworks; NetworkRecProvider(Handler handler, CountDownLatch recRequestLatch, NetworkRecProvider(Context context, Executor executor, CountDownLatch recRequestLatch, CountDownLatch networkRequestLatch) { super(handler); super(context, executor); mRecRequestLatch = recRequestLatch; mScoreRequestLatch = networkRequestLatch; } Loading