diff options
author | Jeff Sharkey <jsharkey@android.com> | 2011-05-22 14:59:31 -0700 |
---|---|---|
committer | Jeff Sharkey <jsharkey@android.com> | 2011-06-01 17:26:30 -0700 |
commit | 9599cc5f21152860af9d18015b1398b50743da76 (patch) | |
tree | b3cd1d7e6b97c81f9c72d86869062acdc0387a5d /services/tests | |
parent | 1b861278a2051f53ce7955fb7992fa536dc975d9 (diff) | |
download | frameworks_base-9599cc5f21152860af9d18015b1398b50743da76.zip frameworks_base-9599cc5f21152860af9d18015b1398b50743da76.tar.gz frameworks_base-9599cc5f21152860af9d18015b1398b50743da76.tar.bz2 |
Tests for NetworkPolicyManager rule generation.
Verifies that policy changes trigger rule updates that respect current
foregroundActivities status. Also verifies logic that promotes a UID
based on its most-foreground PID. Verifies that policy changes result
in immediate rule changes.
Also verifies that BACKGROUND_DATA_SETTING_CHANGED broadcasts are sent
by policy changes.
Change-Id: I4fd0dad9e1dbccee2c5968244bb1814e6cb2c6e1
Diffstat (limited to 'services/tests')
4 files changed, 409 insertions, 75 deletions
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml index f8d1426..295d569 100644 --- a/services/tests/servicestests/AndroidManifest.xml +++ b/services/tests/servicestests/AndroidManifest.xml @@ -24,7 +24,9 @@ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.BROADCAST_STICKY" /> <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" /> - + <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" /> + <uses-permission android:name="android.permission.MANAGE_APP_TOKENS" /> + <application> <uses-library android:name="android.test.runner" /> diff --git a/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java b/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java new file mode 100644 index 0000000..fe88793 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/BroadcastInterceptingContext.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2011 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 com.android.server; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Handler; + +import com.google.common.collect.Lists; +import com.google.common.util.concurrent.AbstractFuture; + +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.Future; + +/** + * {@link ContextWrapper} that can attach listeners for upcoming + * {@link Context#sendBroadcast(Intent)}. + */ +public class BroadcastInterceptingContext extends ContextWrapper { + private static final String TAG = "WatchingContext"; + + private final List<BroadcastInterceptor> mInterceptors = Lists.newArrayList(); + + public class BroadcastInterceptor extends AbstractFuture<Intent> { + private final BroadcastReceiver mReceiver; + private final IntentFilter mFilter; + + public BroadcastInterceptor(BroadcastReceiver receiver, IntentFilter filter) { + mReceiver = receiver; + mFilter = filter; + } + + public boolean dispatchBroadcast(Intent intent) { + if (mFilter.match(getContentResolver(), intent, false, TAG) > 0) { + if (mReceiver != null) { + final Context context = BroadcastInterceptingContext.this; + mReceiver.onReceive(context, intent); + return false; + } else { + set(intent); + return true; + } + } else { + return false; + } + } + } + + public BroadcastInterceptingContext(Context base) { + super(base); + } + + public Future<Intent> nextBroadcastIntent(String action) { + return nextBroadcastIntent(new IntentFilter(action)); + } + + public Future<Intent> nextBroadcastIntent(IntentFilter filter) { + final BroadcastInterceptor interceptor = new BroadcastInterceptor(null, filter); + synchronized (mInterceptors) { + mInterceptors.add(interceptor); + } + return interceptor; + } + + @Override + public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { + synchronized (mInterceptors) { + mInterceptors.add(new BroadcastInterceptor(receiver, filter)); + } + return null; + } + + @Override + public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, + String broadcastPermission, Handler scheduler) { + return registerReceiver(receiver, filter); + } + + @Override + public void unregisterReceiver(BroadcastReceiver receiver) { + synchronized (mInterceptors) { + final Iterator<BroadcastInterceptor> i = mInterceptors.iterator(); + while (i.hasNext()) { + final BroadcastInterceptor interceptor = i.next(); + if (receiver.equals(interceptor.mReceiver)) { + i.remove(); + } + } + } + } + + @Override + public void sendBroadcast(Intent intent) { + synchronized (mInterceptors) { + final Iterator<BroadcastInterceptor> i = mInterceptors.iterator(); + while (i.hasNext()) { + final BroadcastInterceptor interceptor = i.next(); + if (interceptor.dispatchBroadcast(intent)) { + i.remove(); + } + } + } + } + + @Override + public void sendStickyBroadcast(Intent intent) { + sendBroadcast(intent); + } + + @Override + public void removeStickyBroadcast(Intent intent) { + // ignored + } +} diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java new file mode 100644 index 0000000..cf1171f --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2011 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 com.android.server; + +import static android.net.NetworkPolicyManager.POLICY_NONE; +import static android.net.NetworkPolicyManager.POLICY_REJECT_PAID_BACKGROUND; +import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; +import static android.net.NetworkPolicyManager.RULE_REJECT_PAID; +import static org.easymock.EasyMock.capture; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.eq; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.expectLastCall; + +import android.app.IActivityManager; +import android.app.IProcessObserver; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.ConnectivityManager; +import android.net.INetworkPolicyListener; +import android.os.Binder; +import android.os.IPowerManager; +import android.test.AndroidTestCase; +import android.test.mock.MockPackageManager; +import android.test.suitebuilder.annotation.LargeTest; +import android.test.suitebuilder.annotation.Suppress; + +import com.android.server.net.NetworkPolicyManagerService; + +import org.easymock.Capture; +import org.easymock.EasyMock; + +import java.util.concurrent.Future; + +/** + * Tests for {@link NetworkPolicyManagerService}. + */ +@LargeTest +public class NetworkPolicyManagerServiceTest extends AndroidTestCase { + private static final String TAG = "NetworkPolicyManagerServiceTest"; + + private BroadcastInterceptingContext mServiceContext; + + private IActivityManager mActivityManager; + private IPowerManager mPowerManager; + private INetworkPolicyListener mPolicyListener; + + private NetworkPolicyManagerService mService; + private IProcessObserver mProcessObserver; + + private Binder mStubBinder = new Binder(); + + private static final int UID_A = 800; + private static final int UID_B = 801; + + private static final int PID_1 = 400; + private static final int PID_2 = 401; + private static final int PID_3 = 402; + + @Override + public void setUp() throws Exception { + super.setUp(); + + // intercept various broadcasts, and pretend that uids have packages + mServiceContext = new BroadcastInterceptingContext(getContext()) { + @Override + public PackageManager getPackageManager() { + return new MockPackageManager() { + @Override + public String[] getPackagesForUid(int uid) { + return new String[] { "com.example" }; + } + }; + } + }; + + mActivityManager = createMock(IActivityManager.class); + mPowerManager = createMock(IPowerManager.class); + mPolicyListener = createMock(INetworkPolicyListener.class); + + mService = new NetworkPolicyManagerService( + mServiceContext, mActivityManager, mPowerManager); + + // RemoteCallbackList needs a binder to use as key + expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce(); + replay(); + mService.registerListener(mPolicyListener); + verifyAndReset(); + + // catch the registered IProcessObserver during systemReady() + final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>(); + mActivityManager.registerProcessObserver(capture(processObserver)); + expectLastCall().atLeastOnce(); + + // expect to answer screen status during systemReady() + expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce(); + + replay(); + mService.systemReady(); + verifyAndReset(); + + mProcessObserver = processObserver.getValue(); + + } + + @Override + public void tearDown() throws Exception { + mServiceContext = null; + + mActivityManager = null; + mPowerManager = null; + mPolicyListener = null; + + mService = null; + mProcessObserver = null; + + super.tearDown(); + } + + @Suppress + public void testPolicyChangeTriggersBroadcast() throws Exception { + mService.setUidPolicy(UID_A, POLICY_NONE); + + // change background policy and expect broadcast + final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent( + ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED); + + mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND); + + backgroundChanged.get(); + } + + public void testPidForegroundCombined() throws Exception { + // push all uid into background + mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false); + mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false); + mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false); + assertFalse(mService.isUidForeground(UID_A)); + assertFalse(mService.isUidForeground(UID_B)); + + // push one of the shared pids into foreground + mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true); + assertTrue(mService.isUidForeground(UID_A)); + assertFalse(mService.isUidForeground(UID_B)); + + // and swap another uid into foreground + mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false); + mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true); + assertFalse(mService.isUidForeground(UID_A)); + assertTrue(mService.isUidForeground(UID_B)); + + // push both pid into foreground + mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true); + mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true); + assertTrue(mService.isUidForeground(UID_A)); + + // pull one out, should still be foreground + mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false); + assertTrue(mService.isUidForeground(UID_A)); + + // pull final pid out, should now be background + mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false); + assertFalse(mService.isUidForeground(UID_A)); + } + + public void testScreenChangesRules() throws Exception { + // push strict policy for foreground uid, verify ALLOW rule + expectRulesChanged(UID_A, RULE_ALLOW_ALL); + replay(); + mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true); + mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND); + verifyAndReset(); + + // now turn screen off and verify REJECT rule + expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce(); + expectRulesChanged(UID_A, RULE_REJECT_PAID); + replay(); + mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_OFF)); + verifyAndReset(); + + // and turn screen back on, verify ALLOW rule restored + expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce(); + expectRulesChanged(UID_A, RULE_ALLOW_ALL); + replay(); + mServiceContext.sendBroadcast(new Intent(Intent.ACTION_SCREEN_ON)); + verifyAndReset(); + } + + public void testPolicyNone() throws Exception { + // POLICY_NONE should RULE_ALLOW in foreground + expectRulesChanged(UID_A, RULE_ALLOW_ALL); + replay(); + mService.setUidPolicy(UID_A, POLICY_NONE); + mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true); + verifyAndReset(); + + // POLICY_NONE should RULE_ALLOW in background + expectRulesChanged(UID_A, RULE_ALLOW_ALL); + replay(); + mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false); + verifyAndReset(); + } + + public void testPolicyReject() throws Exception { + // POLICY_REJECT should RULE_ALLOW in background + expectRulesChanged(UID_A, RULE_REJECT_PAID); + replay(); + mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND); + verifyAndReset(); + + // POLICY_REJECT should RULE_ALLOW in foreground + expectRulesChanged(UID_A, RULE_ALLOW_ALL); + replay(); + mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true); + verifyAndReset(); + + // POLICY_REJECT should RULE_REJECT in background + expectRulesChanged(UID_A, RULE_REJECT_PAID); + replay(); + mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false); + verifyAndReset(); + } + + public void testPolicyRejectAddRemove() throws Exception { + // POLICY_NONE should have RULE_ALLOW in background + expectRulesChanged(UID_A, RULE_ALLOW_ALL); + replay(); + mService.setUidPolicy(UID_A, POLICY_NONE); + mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false); + verifyAndReset(); + + // adding POLICY_REJECT should cause RULE_REJECT + expectRulesChanged(UID_A, RULE_REJECT_PAID); + replay(); + mService.setUidPolicy(UID_A, POLICY_REJECT_PAID_BACKGROUND); + verifyAndReset(); + + // removing POLICY_REJECT should return us to RULE_ALLOW + expectRulesChanged(UID_A, RULE_ALLOW_ALL); + replay(); + mService.setUidPolicy(UID_A, POLICY_NONE); + verifyAndReset(); + } + + private void expectRulesChanged(int uid, int policy) throws Exception { + mPolicyListener.onRulesChanged(eq(uid), eq(policy)); + expectLastCall().atLeastOnce(); + } + + private void replay() { + EasyMock.replay(mActivityManager, mPowerManager, mPolicyListener); + } + + private void verifyAndReset() { + EasyMock.verify(mActivityManager, mPowerManager, mPolicyListener); + EasyMock.reset(mActivityManager, mPowerManager, mPolicyListener); + } +} diff --git a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java index ca33d32..d1ee4f6 100644 --- a/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/ThrottleServiceTest.java @@ -25,14 +25,9 @@ import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.reset; import static org.easymock.EasyMock.verify; -import com.google.common.collect.Lists; -import com.google.common.util.concurrent.AbstractFuture; - import android.content.ContentResolver; import android.content.Context; -import android.content.ContextWrapper; import android.content.Intent; -import android.content.IntentFilter; import android.net.INetworkManagementEventObserver; import android.net.NetworkStats; import android.net.ThrottleManager; @@ -48,8 +43,6 @@ import android.text.format.DateUtils; import android.util.Log; import android.util.TrustedTime; -import java.util.Iterator; -import java.util.List; import java.util.concurrent.Future; /** @@ -66,7 +59,7 @@ public class ThrottleServiceTest extends AndroidTestCase { private static final String TEST_IFACE = "test0"; - private WatchingContext mWatchingContext; + private BroadcastInterceptingContext mWatchingContext; private INetworkManagementService mMockNMService; private TrustedTime mMockTime; @@ -76,7 +69,7 @@ public class ThrottleServiceTest extends AndroidTestCase { public void setUp() throws Exception { super.setUp(); - mWatchingContext = new WatchingContext(getContext()); + mWatchingContext = new BroadcastInterceptingContext(getContext()); mMockNMService = createMock(INetworkManagementService.class); mMockTime = createMock(TrustedTime.class); @@ -354,69 +347,4 @@ public class ThrottleServiceTest extends AndroidTestCase { pollAction.get(); } - - - /** - * {@link ContextWrapper} that can attach listeners for upcoming - * {@link Context#sendBroadcast(Intent)}. - */ - private static class WatchingContext extends ContextWrapper { - private List<LocalBroadcastReceiver> mReceivers = Lists.newArrayList(); - - public class LocalBroadcastReceiver extends AbstractFuture<Intent> { - private IntentFilter mFilter; - - public LocalBroadcastReceiver(IntentFilter filter) { - mFilter = filter; - } - - public boolean dispatchBroadcast(Intent intent) { - if (mFilter.match(getContentResolver(), intent, false, TAG) > 0) { - set(intent); - return true; - } else { - return false; - } - } - } - - public WatchingContext(Context base) { - super(base); - } - - public Future<Intent> nextBroadcastIntent(String action) { - return nextBroadcastIntent(new IntentFilter(action)); - } - - public Future<Intent> nextBroadcastIntent(IntentFilter filter) { - final LocalBroadcastReceiver receiver = new LocalBroadcastReceiver(filter); - synchronized (mReceivers) { - mReceivers.add(receiver); - } - return receiver; - } - - @Override - public void sendBroadcast(Intent intent) { - synchronized (mReceivers) { - final Iterator<LocalBroadcastReceiver> i = mReceivers.iterator(); - while (i.hasNext()) { - final LocalBroadcastReceiver receiver = i.next(); - if (receiver.dispatchBroadcast(intent)) { - i.remove(); - } - } - } - } - - @Override - public void sendStickyBroadcast(Intent intent) { - sendBroadcast(intent); - } - - @Override - public void removeStickyBroadcast(Intent intent) { - // ignored - } - } } |