Merge "Switch to listening for all network changes."
am: 085ffa76fa
Change-Id: I87157788c5c2dc1015f9518c1c443256cfd30bae
diff --git a/core/java/android/net/IIpConnectivityMetrics.aidl b/core/java/android/net/IIpConnectivityMetrics.aidl
index d36b766..8f634bb 100644
--- a/core/java/android/net/IIpConnectivityMetrics.aidl
+++ b/core/java/android/net/IIpConnectivityMetrics.aidl
@@ -23,8 +23,7 @@
interface IIpConnectivityMetrics {
/**
- * @return the number of remaining available slots in buffer,
- * or -1 if the event was dropped due to rate limiting.
+ * @return number of remaining available slots in buffer.
*/
int logEvent(in ConnectivityMetricsEvent event);
}
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 9db131b..9f7e883 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2723,6 +2723,7 @@
<java-symbol type="bool" name="config_permissionReviewRequired" />
+
<java-symbol type="drawable" name="ic_restart" />
<java-symbol type="drawable" name="emergency_icon" />
diff --git a/core/tests/coretests/src/android/util/TokenBucketTest.java b/core/tests/coretests/src/android/util/TokenBucketTest.java
index f7ac20c..a053ad3 100644
--- a/core/tests/coretests/src/android/util/TokenBucketTest.java
+++ b/core/tests/coretests/src/android/util/TokenBucketTest.java
@@ -177,3 +177,4 @@
interface Fn { void call(); }
}
+
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 3b3ce07..78b33e5 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -760,8 +760,9 @@
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
- if (!isEnabled() && mPermissionReviewRequired) {
- startConsentUi(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ if (!isEnabled() && mPermissionReviewRequired
+ && startConsentUiIfNeeded(packageName, callingUid,
+ BluetoothAdapter.ACTION_REQUEST_ENABLE)) {
return false;
}
}
@@ -795,8 +796,9 @@
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
- if (isEnabled() && mPermissionReviewRequired) {
- startConsentUi(packageName, callingUid, BluetoothAdapter.ACTION_REQUEST_DISABLE);
+ if (isEnabled() && mPermissionReviewRequired
+ && startConsentUiIfNeeded(packageName, callingUid,
+ BluetoothAdapter.ACTION_REQUEST_DISABLE)) {
return false;
}
}
@@ -816,8 +818,8 @@
return true;
}
- private void startConsentUi(String packageName, int callingUid, String intentAction)
- throws RemoteException {
+ private boolean startConsentUiIfNeeded(String packageName,
+ int callingUid, String intentAction) throws RemoteException {
try {
// Validate the package only if we are going to use it
ApplicationInfo applicationInfo = mContext.getPackageManager()
@@ -829,12 +831,16 @@
+ " not in uid " + callingUid);
}
- // Permission review mode, trigger a user prompt
- Intent intent = new Intent(intentAction);
- mContext.startActivity(intent);
+ // Legacy apps in permission review mode trigger a user prompt
+ if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
+ Intent intent = new Intent(intentAction);
+ mContext.startActivity(intent);
+ return true;
+ }
} catch (PackageManager.NameNotFoundException e) {
throw new RemoteException(e.getMessage());
}
+ return false;
}
public void unbindAndFinish() {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 97f913e..4405c1b 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -49,6 +49,7 @@
import android.os.Environment;
import android.os.FileUtils;
import android.os.Handler;
+import android.os.IBinder;
import android.os.IDeviceIdleController;
import android.os.IMaintenanceActivityListener;
import android.os.Looper;
@@ -1237,7 +1238,7 @@
}
}
- public class LocalService {
+ public final class LocalService {
public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
String reason) {
addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index ae1aef6..10a5388 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -369,7 +369,7 @@
// we do not start the service and launch a review activity if the calling app
// is in the foreground passing it a pending intent to start the service when
// review is completed.
- if (mAm.mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
+ if (Build.PERMISSIONS_REVIEW_REQUIRED) {
if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,
callingUid, service, callerFg, userId)) {
return null;
@@ -913,7 +913,7 @@
// we schedule binding to the service but do not start its process, then
// we launch a review activity to which is passed a callback to invoke
// when done to start the bound service's process to completing the binding.
- if (mAm.mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
+ if (Build.PERMISSIONS_REVIEW_REQUIRED) {
if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
s.packageName, s.userId)) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 257ffb4..a9ddb63 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1576,8 +1576,6 @@
// being called for multiwindow assist in a single session.
private int mViSessionId = 1000;
- final boolean mPermissionReviewRequired;
-
final class KillHandler extends Handler {
static final int KILL_PROCESS_GROUP_MSG = 4000;
@@ -2625,9 +2623,6 @@
Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
- mPermissionReviewRequired = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_permissionReviewRequired);
-
mHandlerThread = new ServiceThread(TAG,
android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
mHandlerThread.start();
@@ -10843,7 +10838,7 @@
// If permissions need a review before any of the app components can run,
// we return no provider and launch a review activity if the calling app
// is in the foreground.
- if (mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
+ if (Build.PERMISSIONS_REVIEW_REQUIRED) {
if (!requestTargetProviderPermissionsReviewIfNeededLocked(cpi, r, userId)) {
return null;
}
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 907394e..115971f 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -416,8 +416,7 @@
// If permissions need a review before any of the app components can run, we
// launch the review activity and pass a pending intent to start the activity
// we are to launching now after the review is completed.
- if ((mService.mPermissionReviewRequired
- || Build.PERMISSIONS_REVIEW_REQUIRED) && aInfo != null) {
+ if (Build.PERMISSIONS_REVIEW_REQUIRED && aInfo != null) {
if (mService.getPackageManagerInternalLocked().isPermissionsReviewRequired(
aInfo.packageName, userId)) {
IIntentSender target = mService.getIntentSenderLocked(
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index ea901ce..362a347 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -626,7 +626,7 @@
// the broadcast and if the calling app is in the foreground and the broadcast is
// explicit we launch the review UI passing it a pending intent to send the skipped
// broadcast.
- if (mService.mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
+ if (Build.PERMISSIONS_REVIEW_REQUIRED) {
if (!requestStartTargetPermissionsReviewIfNeededLocked(r, filter.packageName,
filter.owningUserId)) {
r.delivery[index] = BroadcastRecord.DELIVERY_SKIPPED;
@@ -1132,8 +1132,7 @@
// the broadcast and if the calling app is in the foreground and the broadcast is
// explicit we launch the review UI passing it a pending intent to send the skipped
// broadcast.
- if ((mService.mPermissionReviewRequired
- || Build.PERMISSIONS_REVIEW_REQUIRED) && !skip) {
+ if (Build.PERMISSIONS_REVIEW_REQUIRED && !skip) {
if (!requestStartTargetPermissionsReviewIfNeededLocked(r,
info.activityInfo.packageName, UserHandle.getUserId(
info.activityInfo.applicationInfo.uid))) {
diff --git a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
index be68173..642f2e0 100644
--- a/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
+++ b/services/core/java/com/android/server/connectivity/IpConnectivityMetrics.java
@@ -19,19 +19,15 @@
import android.content.Context;
import android.net.ConnectivityMetricsEvent;
import android.net.IIpConnectivityMetrics;
-import android.net.metrics.ApfProgramEvent;
import android.net.metrics.IpConnectivityLog;
import android.os.IBinder;
import android.os.Parcelable;
import android.provider.Settings;
import android.text.TextUtils;
-import android.text.format.DateUtils;
-import android.util.ArrayMap;
import android.util.Base64;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.TokenBucket;
import com.android.server.SystemService;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -60,8 +56,6 @@
// Maximum size of the event buffer.
private static final int MAXIMUM_BUFFER_SIZE = DEFAULT_BUFFER_SIZE * 10;
- private static final int ERROR_RATE_LIMITED = -1;
-
// Lock ensuring that concurrent manipulations of the event buffer are correct.
// There are three concurrent operations to synchronize:
// - appending events to the buffer.
@@ -79,8 +73,6 @@
private int mDropped;
@GuardedBy("mLock")
private int mCapacity;
- @GuardedBy("mLock")
- private final ArrayMap<Class<?>, TokenBucket> mBuckets = makeRateLimitingBuckets();
private final ToIntFunction<Context> mCapacityGetter;
@@ -130,10 +122,6 @@
if (event == null) {
return left;
}
- if (isRateLimited(event)) {
- // Do not count as a dropped event. TODO: consider adding separate counter
- return ERROR_RATE_LIMITED;
- }
if (left == 0) {
mDropped++;
return 0;
@@ -143,11 +131,6 @@
}
}
- private boolean isRateLimited(ConnectivityMetricsEvent event) {
- TokenBucket tb = mBuckets.get(event.data.getClass());
- return (tb != null) && !tb.get();
- }
-
private String flushEncodedOutput() {
final ArrayList<ConnectivityMetricsEvent> events;
final int dropped;
@@ -273,11 +256,4 @@
}
return Math.min(size, MAXIMUM_BUFFER_SIZE);
};
-
- private static ArrayMap<Class<?>, TokenBucket> makeRateLimitingBuckets() {
- ArrayMap<Class<?>, TokenBucket> map = new ArrayMap<>();
- // one token every minute, 50 tokens max: burst of ~50 events every hour.
- map.put(ApfProgramEvent.class, new TokenBucket((int)DateUtils.MINUTE_IN_MILLIS, 50));
- return map;
- }
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 9ffa40b..c6bf4c5 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -27,7 +27,7 @@
import android.os.UserHandle;
import android.telephony.TelephonyManager;
import android.util.Slog;
-import com.android.internal.annotations.VisibleForTesting;
+
import com.android.internal.R;
import static android.net.NetworkCapabilities.*;
@@ -37,8 +37,7 @@
public static enum NotificationType { SIGN_IN, NO_INTERNET, LOST_INTERNET, NETWORK_SWITCH };
- @VisibleForTesting
- static final String NOTIFICATION_ID = "Connectivity.Notification";
+ private static final String NOTIFICATION_ID = "Connectivity.Notification";
private static final String TAG = NetworkNotificationManager.class.getSimpleName();
private static final boolean DBG = true;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 07dbb17..0e696b3 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1148,8 +1148,6 @@
final @NonNull String mServicesSystemSharedLibraryPackageName;
final @NonNull String mSharedSystemSharedLibraryPackageName;
- final boolean mPermissionReviewRequired;
-
private final PackageUsage mPackageUsage = new PackageUsage();
private final CompilerStats mCompilerStats = new CompilerStats();
@@ -2080,10 +2078,6 @@
}
mContext = context;
-
- mPermissionReviewRequired = context.getResources().getBoolean(
- R.bool.config_permissionReviewRequired);
-
mFactoryTest = factoryTest;
mOnlyCore = onlyCore;
mMetrics = new DisplayMetrics();
@@ -4057,7 +4051,7 @@
// their permissions as always granted runtime ones since we need
// to keep the review required permission flag per user while an
// install permission's state is shared across all users.
- if ((mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED)
+ if (Build.PERMISSIONS_REVIEW_REQUIRED
&& pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
&& bp.isRuntime()) {
return;
@@ -4168,7 +4162,7 @@
// their permissions as always granted runtime ones since we need
// to keep the review required permission flag per user while an
// install permission's state is shared across all users.
- if ((mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED)
+ if (Build.PERMISSIONS_REVIEW_REQUIRED
&& pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M
&& bp.isRuntime()) {
return;
@@ -10061,8 +10055,7 @@
// their permissions as always granted runtime ones since we need
// to keep the review required permission flag per user while an
// install permission's state is shared across all users.
- if (!appSupportsRuntimePermissions && !mPermissionReviewRequired
- && !Build.PERMISSIONS_REVIEW_REQUIRED) {
+ if (!appSupportsRuntimePermissions && !Build.PERMISSIONS_REVIEW_REQUIRED) {
// For legacy apps dangerous permissions are install time ones.
grant = GRANT_INSTALL;
} else if (origPermissions.hasInstallPermission(bp.name)) {
@@ -10148,7 +10141,7 @@
changedRuntimePermissionUserIds, userId);
}
// If the app supports runtime permissions no need for a review.
- if ((mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED)
+ if (Build.PERMISSIONS_REVIEW_REQUIRED
&& appSupportsRuntimePermissions
&& (flags & PackageManager
.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
@@ -10157,8 +10150,7 @@
changedRuntimePermissionUserIds = ArrayUtils.appendInt(
changedRuntimePermissionUserIds, userId);
}
- } else if ((mPermissionReviewRequired
- || Build.PERMISSIONS_REVIEW_REQUIRED)
+ } else if (Build.PERMISSIONS_REVIEW_REQUIRED
&& !appSupportsRuntimePermissions) {
// For legacy apps that need a permission review, every new
// runtime permission is granted but it is pending a review.
@@ -16753,7 +16745,7 @@
// If permission review is enabled and this is a legacy app, mark the
// permission as requiring a review as this is the initial state.
int flags = 0;
- if ((mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED)
+ if (Build.PERMISSIONS_REVIEW_REQUIRED
&& ps.pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.M) {
flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
}
@@ -20623,7 +20615,7 @@
// permissions to keep per user flag state whether review is needed.
// Hence, if a new user is added we have to propagate dangerous
// permission grants for these legacy apps.
- if (mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
+ if (Build.PERMISSIONS_REVIEW_REQUIRED) {
updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
| UPDATE_PERMISSIONS_REPLACE_ALL);
}
@@ -21077,7 +21069,7 @@
public boolean isPermissionsReviewRequired(String packageName, int userId) {
synchronized (mPackages) {
// If we do not support permission review, done.
- if (!mPermissionReviewRequired && !Build.PERMISSIONS_REVIEW_REQUIRED) {
+ if (!Build.PERMISSIONS_REVIEW_REQUIRED) {
return false;
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index a545af9..aeeca79 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -16,12 +16,17 @@
package com.android.server;
+import static android.content.Intent.ACTION_UID_REMOVED;
+import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
import static android.net.ConnectivityManager.TYPE_WIFI;
+import static android.net.NetworkPolicy.CYCLE_NONE;
import static android.net.NetworkPolicy.LIMIT_DISABLED;
import static android.net.NetworkPolicy.WARNING_DISABLED;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
+import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
+import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
import static android.net.NetworkPolicyManager.computeNextCycleBoundary;
import static android.net.TrafficStats.KB_IN_BYTES;
@@ -29,42 +34,28 @@
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.Time.TIMEZONE_UTC;
-
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_LIMIT_SNOOZED;
import static com.android.server.net.NetworkPolicyManagerService.TYPE_WARNING;
+import static org.easymock.EasyMock.anyInt;
+import static org.easymock.EasyMock.anyLong;
+import static org.easymock.EasyMock.aryEq;
+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 static org.easymock.EasyMock.isA;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Matchers.isA;
-import static org.mockito.Mockito.atLeastOnce;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.INotificationManager;
-import android.app.IUidObserver;
+import android.app.IProcessObserver;
import android.app.Notification;
-import android.app.usage.UsageStatsManagerInternal;
-import android.content.Context;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
+import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkPolicyListener;
@@ -78,48 +69,40 @@
import android.net.NetworkTemplate;
import android.os.Binder;
import android.os.INetworkManagementService;
-import android.os.PowerManagerInternal;
+import android.os.MessageQueue.IdleHandler;
import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+import android.test.AndroidTestCase;
+import android.test.mock.MockPackageManager;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.Suppress;
import android.text.format.Time;
-import android.util.Log;
import android.util.TrustedTime;
import com.android.internal.util.test.BroadcastInterceptingContext;
-import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.net.NetworkPolicyManagerService;
-
-import libcore.io.IoUtils;
-
import com.google.common.util.concurrent.AbstractFuture;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
import java.io.File;
-import java.util.ArrayList;
+import java.util.Calendar;
import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
+import java.util.TimeZone;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
+import java.util.logging.Handler;
+
+import libcore.io.IoUtils;
/**
* Tests for {@link NetworkPolicyManagerService}.
*/
-@RunWith(AndroidJUnit4.class)
-public class NetworkPolicyManagerServiceTest {
+@LargeTest
+public class NetworkPolicyManagerServiceTest extends AndroidTestCase {
private static final String TAG = "NetworkPolicyManagerServiceTest";
private static final long TEST_START = 1194220800000L;
@@ -131,19 +114,19 @@
private BroadcastInterceptingContext mServiceContext;
private File mPolicyDir;
- private @Mock IActivityManager mActivityManager;
- private @Mock INetworkStatsService mStatsService;
- private @Mock INetworkManagementService mNetworkManager;
- private @Mock TrustedTime mTime;
- private @Mock IConnectivityManager mConnManager;
- private @Mock INotificationManager mNotifManager;
- private @Mock PackageManager mPackageManager;
+ private IActivityManager mActivityManager;
+ private INetworkStatsService mStatsService;
+ private INetworkManagementService mNetworkManager;
+ private INetworkPolicyListener mPolicyListener;
+ private TrustedTime mTime;
+ private IConnectivityManager mConnManager;
+ private INotificationManager mNotifManager;
- private IUidObserver mUidObserver;
+ private NetworkPolicyManagerService mService;
+ private IProcessObserver mProcessObserver;
private INetworkManagementEventObserver mNetworkObserver;
- private NetworkPolicyListenerAnswer mPolicyListener;
- private NetworkPolicyManagerService mService;
+ private Binder mStubBinder = new Binder();
private long mStartTime;
private long mElapsedRealtime;
@@ -156,30 +139,39 @@
private static final int UID_A = UserHandle.getUid(USER_ID, APP_ID_A);
private static final int UID_B = UserHandle.getUid(USER_ID, APP_ID_B);
- private static final String PKG_NAME_A = "name.is.A,pkg.A";
+ private static final int PID_1 = 400;
+ private static final int PID_2 = 401;
+ private static final int PID_3 = 402;
- @BeforeClass
- public static void registerLocalServices() {
- addLocalServiceMock(PowerManagerInternal.class);
- addLocalServiceMock(DeviceIdleController.LocalService.class);
- final UsageStatsManagerInternal usageStats =
- addLocalServiceMock(UsageStatsManagerInternal.class);
- when(usageStats.getIdleUidsForUser(anyInt())).thenReturn(new int[]{});
- }
-
- @Before
- public void callSystemReady() throws Exception {
- MockitoAnnotations.initMocks(this);
-
- final Context context = InstrumentationRegistry.getContext();
+ public void _setUp() throws Exception {
+ super.setUp();
setCurrentTimeMillis(TEST_START);
// intercept various broadcasts, and pretend that uids have packages
- mServiceContext = new BroadcastInterceptingContext(context) {
+ mServiceContext = new BroadcastInterceptingContext(getContext()) {
@Override
public PackageManager getPackageManager() {
- return mPackageManager;
+ return new MockPackageManager() {
+ @Override
+ public String[] getPackagesForUid(int uid) {
+ return new String[] { "com.example" };
+ }
+
+ @Override
+ public PackageInfo getPackageInfo(String packageName, int flags) {
+ final PackageInfo info = new PackageInfo();
+ final Signature signature;
+ if ("android".equals(packageName)) {
+ signature = new Signature("F00D");
+ } else {
+ signature = new Signature("DEAD");
+ }
+ info.signatures = new Signature[] { signature };
+ return info;
+ }
+
+ };
}
@Override
@@ -188,112 +180,229 @@
}
};
- mPolicyDir = context.getFilesDir();
+ mPolicyDir = getContext().getFilesDir();
if (mPolicyDir.exists()) {
IoUtils.deleteContents(mPolicyDir);
}
- doAnswer(new Answer<Void>() {
+ mActivityManager = createMock(IActivityManager.class);
+ mStatsService = createMock(INetworkStatsService.class);
+ mNetworkManager = createMock(INetworkManagementService.class);
+ mPolicyListener = createMock(INetworkPolicyListener.class);
+ mTime = createMock(TrustedTime.class);
+ mConnManager = createMock(IConnectivityManager.class);
+ mNotifManager = createMock(INotificationManager.class);
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- mUidObserver = (IUidObserver) invocation.getArguments()[0];
- Log.d(TAG, "set mUidObserver to " + mUidObserver);
- return null;
- }
- }).when(mActivityManager).registerUidObserver(any(), anyInt());
-
- mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager, mStatsService,
- mNetworkManager, mTime, mPolicyDir, true);
+ mService = new NetworkPolicyManagerService(mServiceContext, mActivityManager,
+ mStatsService, mNetworkManager, mTime, mPolicyDir, true);
mService.bindConnectivityManager(mConnManager);
mService.bindNotificationManager(mNotifManager);
- mPolicyListener = new NetworkPolicyListenerAnswer(mService);
- // Sets some common expectations.
- when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenAnswer(
- new Answer<PackageInfo>() {
+ // RemoteCallbackList needs a binder to use as key
+ expect(mPolicyListener.asBinder()).andReturn(mStubBinder).atLeastOnce();
+ replay();
+ mService.registerListener(mPolicyListener);
+ verifyAndReset();
- @Override
- public PackageInfo answer(InvocationOnMock invocation) throws Throwable {
- final String packageName = (String) invocation.getArguments()[0];
- final PackageInfo info = new PackageInfo();
- final Signature signature;
- if ("android".equals(packageName)) {
- signature = new Signature("F00D");
- } else {
- signature = new Signature("DEAD");
- }
- info.signatures = new Signature[] {
- signature
- };
- return info;
- }
- });
- when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
- .thenReturn(new ApplicationInfo());
- when(mPackageManager.getPackagesForUid(UID_A)).thenReturn(new String[] {PKG_NAME_A});
- when(mNetworkManager.isBandwidthControlEnabled()).thenReturn(true);
- expectCurrentTime();
-
- // Prepare NPMS.
- mService.systemReady();
+ // catch IProcessObserver during systemReady()
+ final Capture<IProcessObserver> processObserver = new Capture<IProcessObserver>();
+ mActivityManager.registerProcessObserver(capture(processObserver));
+ expectLastCall().atLeastOnce();
// catch INetworkManagementEventObserver during systemReady()
- ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
- ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
- verify(mNetworkManager).registerObserver(networkObserver.capture());
+ final Capture<INetworkManagementEventObserver> networkObserver = new Capture<
+ INetworkManagementEventObserver>();
+ mNetworkManager.registerObserver(capture(networkObserver));
+ expectLastCall().atLeastOnce();
+
+ expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce();
+ expectCurrentTime();
+
+ replay();
+ mService.systemReady();
+ verifyAndReset();
+
+ mProcessObserver = processObserver.getValue();
mNetworkObserver = networkObserver.getValue();
+
}
- @After
- public void removeFiles() throws Exception {
+ public void _tearDown() throws Exception {
for (File file : mPolicyDir.listFiles()) {
file.delete();
}
+
+ mServiceContext = null;
+ mPolicyDir = null;
+
+ mActivityManager = null;
+ mStatsService = null;
+ mPolicyListener = null;
+ mTime = null;
+
+ mService = null;
+ mProcessObserver = null;
+
+ super.tearDown();
}
- @After
- public void unregisterLocalServices() throws Exception {
- // Registered by NetworkPolicyManagerService's constructor.
- LocalServices.removeServiceForTest(NetworkPolicyManagerInternal.class);
- }
-
- // NOTE: testPolicyChangeTriggersListener() and testUidForeground() are too superficial, they
- // don't check for side-effects (like calls to NetworkManagementService) neither cover all
- // different modes (Data Saver, Battery Saver, Doze, App idle, etc...).
- // These scenarios are extensively tested on CTS' HostsideRestrictBackgroundNetworkTests.
-
- @Test
- public void testPolicyChangeTriggersListener() throws Exception {
- mPolicyListener.expect().onRestrictBackgroundBlacklistChanged(anyInt(), anyBoolean());
-
+ @Suppress
+ public void testPolicyChangeTriggersBroadcast() throws Exception {
mService.setUidPolicy(APP_ID_A, POLICY_NONE);
+
+ // change background policy and expect broadcast
+ final Future<Intent> backgroundChanged = mServiceContext.nextBroadcastIntent(
+ ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
+
mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
- mPolicyListener.waitAndVerify().onRestrictBackgroundBlacklistChanged(APP_ID_A, true);
+ backgroundChanged.get();
}
- @Test
- public void testUidForeground() throws Exception {
- // push all uids into background
- mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
- mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_SERVICE);
+ @Suppress
+ public void testPidForegroundCombined() throws Exception {
+ IdleFuture idle;
+
+ // push all uid into background
+ idle = expectIdle();
+ mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+ mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
+ mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, false);
+ idle.get();
assertFalse(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
- // push one of the uids into foreground
- mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_TOP);
+ // push one of the shared pids into foreground
+ idle = expectIdle();
+ mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
+ idle.get();
assertTrue(mService.isUidForeground(UID_A));
assertFalse(mService.isUidForeground(UID_B));
// and swap another uid into foreground
- mUidObserver.onUidStateChanged(UID_A, ActivityManager.PROCESS_STATE_SERVICE);
- mUidObserver.onUidStateChanged(UID_B, ActivityManager.PROCESS_STATE_TOP);
+ idle = expectIdle();
+ mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
+ mProcessObserver.onForegroundActivitiesChanged(PID_3, UID_B, true);
+ idle.get();
assertFalse(mService.isUidForeground(UID_A));
assertTrue(mService.isUidForeground(UID_B));
+
+ // push both pid into foreground
+ idle = expectIdle();
+ mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+ mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, true);
+ idle.get();
+ assertTrue(mService.isUidForeground(UID_A));
+
+ // pull one out, should still be foreground
+ idle = expectIdle();
+ mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+ idle.get();
+ assertTrue(mService.isUidForeground(UID_A));
+
+ // pull final pid out, should now be background
+ idle = expectIdle();
+ mProcessObserver.onForegroundActivitiesChanged(PID_2, UID_A, false);
+ idle.get();
+ assertFalse(mService.isUidForeground(UID_A));
}
- @Test
+ @Suppress
+ public void testPolicyNone() throws Exception {
+ Future<Void> future;
+
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
+ expectSetUidForeground(UID_A, true);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ replay();
+ mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+ future.get();
+ verifyAndReset();
+
+ // POLICY_NONE should RULE_ALLOW in foreground
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
+ expectSetUidForeground(UID_A, true);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ replay();
+ mService.setUidPolicy(APP_ID_A, POLICY_NONE);
+ future.get();
+ verifyAndReset();
+
+ // POLICY_NONE should RULE_ALLOW in background
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
+ expectSetUidForeground(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ replay();
+ mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+ future.get();
+ verifyAndReset();
+ }
+
+ @Suppress
+ public void testPolicyReject() throws Exception {
+ Future<Void> future;
+
+ // POLICY_REJECT should RULE_ALLOW in background
+ expectSetUidMeteredNetworkBlacklist(UID_A, true);
+ expectSetUidForeground(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+ replay();
+ mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
+ future.get();
+ verifyAndReset();
+
+ // POLICY_REJECT should RULE_ALLOW in foreground
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
+ expectSetUidForeground(UID_A, true);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ replay();
+ mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, true);
+ future.get();
+ verifyAndReset();
+
+ // POLICY_REJECT should RULE_REJECT in background
+ expectSetUidMeteredNetworkBlacklist(UID_A, true);
+ expectSetUidForeground(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+ replay();
+ mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+ future.get();
+ verifyAndReset();
+ }
+
+ @Suppress
+ public void testPolicyRejectAddRemove() throws Exception {
+ Future<Void> future;
+
+ // POLICY_NONE should have RULE_ALLOW in background
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
+ expectSetUidForeground(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ replay();
+ mProcessObserver.onForegroundActivitiesChanged(PID_1, UID_A, false);
+ mService.setUidPolicy(APP_ID_A, POLICY_NONE);
+ future.get();
+ verifyAndReset();
+
+ // adding POLICY_REJECT should cause RULE_REJECT
+ expectSetUidMeteredNetworkBlacklist(UID_A, true);
+ expectSetUidForeground(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+ replay();
+ mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
+ future.get();
+ verifyAndReset();
+
+ // removing POLICY_REJECT should return us to RULE_ALLOW
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
+ expectSetUidForeground(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ replay();
+ mService.setUidPolicy(APP_ID_A, POLICY_NONE);
+ future.get();
+ verifyAndReset();
+ }
+
public void testLastCycleBoundaryThisMonth() throws Exception {
// assume cycle day of "5th", which should be in same month
final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
@@ -305,7 +414,6 @@
assertTimeEquals(expectedCycle, actualCycle);
}
- @Test
public void testLastCycleBoundaryLastMonth() throws Exception {
// assume cycle day of "20th", which should be in last month
final long currentTime = parseTime("2007-11-14T00:00:00.000Z");
@@ -317,7 +425,6 @@
assertTimeEquals(expectedCycle, actualCycle);
}
- @Test
public void testLastCycleBoundaryThisMonthFebruary() throws Exception {
// assume cycle day of "30th" in february; should go to january
final long currentTime = parseTime("2007-02-14T00:00:00.000Z");
@@ -329,7 +436,6 @@
assertTimeEquals(expectedCycle, actualCycle);
}
- @Test
public void testLastCycleBoundaryLastMonthFebruary() throws Exception {
// assume cycle day of "30th" in february, which should clamp
final long currentTime = parseTime("2007-03-14T00:00:00.000Z");
@@ -341,7 +447,6 @@
assertTimeEquals(expectedCycle, actualCycle);
}
- @Test
public void testCycleBoundaryLeapYear() throws Exception {
final NetworkPolicy policy = new NetworkPolicy(
sTemplateWifi, 29, TIMEZONE_UTC, 1024L, 1024L, false);
@@ -365,7 +470,6 @@
computeNextCycleBoundary(parseTime("2007-03-14T00:00:00.000Z"), policy));
}
- @Test
public void testNextCycleTimezoneAfterUtc() throws Exception {
// US/Central is UTC-6
final NetworkPolicy policy = new NetworkPolicy(
@@ -374,7 +478,6 @@
computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
}
- @Test
public void testNextCycleTimezoneBeforeUtc() throws Exception {
// Israel is UTC+2
final NetworkPolicy policy = new NetworkPolicy(
@@ -383,7 +486,6 @@
computeNextCycleBoundary(parseTime("2012-01-05T00:00:00.000Z"), policy));
}
- @Test
public void testNextCycleSane() throws Exception {
final NetworkPolicy policy = new NetworkPolicy(
sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
@@ -399,7 +501,6 @@
}
}
- @Test
public void testLastCycleSane() throws Exception {
final NetworkPolicy policy = new NetworkPolicy(
sTemplateWifi, 31, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED, false);
@@ -415,7 +516,6 @@
}
}
- @Test
public void testCycleTodayJanuary() throws Exception {
final NetworkPolicy policy = new NetworkPolicy(
sTemplateWifi, 14, "US/Pacific", 1024L, 1024L, false);
@@ -435,7 +535,6 @@
computeLastCycleBoundary(parseTime("2013-01-14T15:11:00.000-08:00"), policy));
}
- @Test
public void testLastCycleBoundaryDST() throws Exception {
final long currentTime = parseTime("1989-01-02T07:30:00.000");
final long expectedCycle = parseTime("1988-12-03T02:00:00.000Z");
@@ -446,7 +545,6 @@
assertTimeEquals(expectedCycle, actualCycle);
}
- @Test
public void testLastCycleBoundaryJanuaryDST() throws Exception {
final long currentTime = parseTime("1989-01-26T21:00:00.000Z");
final long expectedCycle = parseTime("1989-01-01T01:59:59.000Z");
@@ -457,10 +555,11 @@
assertTimeEquals(expectedCycle, actualCycle);
}
- @Test
+ @Suppress
public void testNetworkPolicyAppliedCycleLastMonth() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
+ Future<Void> future;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -471,40 +570,75 @@
// first, pretend that wifi network comes online. no policy active,
// which means we shouldn't push limit to interface.
state = new NetworkState[] { buildWifi() };
- when(mConnManager.getAllNetworkState()).thenReturn(state);
+ expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
expectCurrentTime();
+ expectClearNotifications();
+ expectAdvisePersistThreshold();
+ future = expectMeteredIfacesChanged();
- mPolicyListener.expect().onMeteredIfacesChanged(any());
+ replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
- mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
+ future.get();
+ verifyAndReset();
// now change cycle to be on 15th, and test in early march, to verify we
// pick cycle day in previous month.
- when(mConnManager.getAllNetworkState()).thenReturn(state);
+ expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
expectCurrentTime();
// pretend that 512 bytes total have happened
stats = new NetworkStats(getElapsedRealtime(), 1)
.addIfaceValues(TEST_IFACE, 256L, 2L, 256L, 2L);
- when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
- .thenReturn(stats.getTotalBytes());
-
- mPolicyListener.expect().onMeteredIfacesChanged(any());
- setNetworkPolicies(new NetworkPolicy(
- sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
- mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, TIME_MAR_10))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
+ expectPolicyDataEnable(TYPE_WIFI, true);
// TODO: consider making strongly ordered mock
- verifyPolicyDataEnable(TYPE_WIFI, true);
- verifyRemoveInterfaceQuota(TEST_IFACE);
- verifySetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
+ expectRemoveInterfaceQuota(TEST_IFACE);
+ expectSetInterfaceQuota(TEST_IFACE, (2 * MB_IN_BYTES) - 512);
+
+ expectClearNotifications();
+ expectAdvisePersistThreshold();
+ future = expectMeteredIfacesChanged(TEST_IFACE);
+
+ replay();
+ setNetworkPolicies(new NetworkPolicy(
+ sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1 * MB_IN_BYTES, 2 * MB_IN_BYTES, false));
+ future.get();
+ verifyAndReset();
}
- @Test
+ @Suppress
+ public void testUidRemovedPolicyCleared() throws Exception {
+ Future<Void> future;
+
+ // POLICY_REJECT should RULE_REJECT in background
+ expectSetUidMeteredNetworkBlacklist(UID_A, true);
+ expectSetUidForeground(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
+ replay();
+ mService.setUidPolicy(APP_ID_A, POLICY_REJECT_METERED_BACKGROUND);
+ future.get();
+ verifyAndReset();
+
+ // uninstall should clear RULE_REJECT
+ expectSetUidMeteredNetworkBlacklist(UID_A, false);
+ expectSetUidForeground(UID_A, false);
+ future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
+ replay();
+ final Intent intent = new Intent(ACTION_UID_REMOVED);
+ intent.putExtra(EXTRA_UID, UID_A);
+ mServiceContext.sendBroadcast(intent);
+ future.get();
+ verifyAndReset();
+ }
+
+ @Suppress
public void testOverWarningLimitNotification() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
- Future<String> tagFuture = null;
+ Future<Void> future;
+ Future<String> tagFuture;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -519,15 +653,20 @@
{
expectCurrentTime();
- when(mConnManager.getAllNetworkState()).thenReturn(state);
- when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
- currentTimeMillis())).thenReturn(stats.getTotalBytes());
+ expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
+ expectPolicyDataEnable(TYPE_WIFI, true);
- mPolicyListener.expect().onMeteredIfacesChanged(any());
+ expectClearNotifications();
+ expectAdvisePersistThreshold();
+ future = expectMeteredIfacesChanged();
+
+ replay();
setNetworkPolicies(new NetworkPolicy(sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, 1
* MB_IN_BYTES, 2 * MB_IN_BYTES, false));
- mPolicyListener.waitAndVerify().onMeteredIfacesChanged(any());
- verifyPolicyDataEnable(TYPE_WIFI, true);
+ future.get();
+ verifyAndReset();
}
// bring up wifi network
@@ -538,17 +677,22 @@
{
expectCurrentTime();
- when(mConnManager.getAllNetworkState()).thenReturn(state);
- when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
- currentTimeMillis())).thenReturn(stats.getTotalBytes());
+ expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
+ expectPolicyDataEnable(TYPE_WIFI, true);
- mPolicyListener.expect().onMeteredIfacesChanged(any());
+ expectRemoveInterfaceQuota(TEST_IFACE);
+ expectSetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
+
+ expectClearNotifications();
+ expectAdvisePersistThreshold();
+ future = expectMeteredIfacesChanged(TEST_IFACE);
+
+ replay();
mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION));
- mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
-
- verifyPolicyDataEnable(TYPE_WIFI, true);
- verifyRemoveInterfaceQuota(TEST_IFACE);
- verifySetInterfaceQuota(TEST_IFACE, 2 * MB_IN_BYTES);
+ future.get();
+ verifyAndReset();
}
// go over warning, which should kick notification
@@ -558,15 +702,18 @@
{
expectCurrentTime();
- when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
- currentTimeMillis())).thenReturn(stats.getTotalBytes());
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
+ expectPolicyDataEnable(TYPE_WIFI, true);
+
+ expectForceUpdate();
+ expectClearNotifications();
tagFuture = expectEnqueueNotification();
+ replay();
mNetworkObserver.limitReached(null, TEST_IFACE);
-
assertNotificationType(TYPE_WARNING, tagFuture.get());
- verifyPolicyDataEnable(TYPE_WIFI, true);
-
+ verifyAndReset();
}
// go over limit, which should kick notification and dialog
@@ -576,14 +723,18 @@
{
expectCurrentTime();
- when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
- currentTimeMillis())).thenReturn(stats.getTotalBytes());
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
+ expectPolicyDataEnable(TYPE_WIFI, false);
+
+ expectForceUpdate();
+ expectClearNotifications();
tagFuture = expectEnqueueNotification();
+ replay();
mNetworkObserver.limitReached(null, TEST_IFACE);
-
assertNotificationType(TYPE_LIMIT, tagFuture.get());
- verifyPolicyDataEnable(TYPE_WIFI, false);
+ verifyAndReset();
}
// now snooze policy, which should remove quota
@@ -591,28 +742,35 @@
{
expectCurrentTime();
- when(mConnManager.getAllNetworkState()).thenReturn(state);
- when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
- currentTimeMillis())).thenReturn(stats.getTotalBytes());
- tagFuture = expectEnqueueNotification();
+ expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
+ expectPolicyDataEnable(TYPE_WIFI, true);
- mPolicyListener.expect().onMeteredIfacesChanged(any());
- mService.snoozeLimit(sTemplateWifi);
- mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
-
- assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
// snoozed interface still has high quota so background data is
// still restricted.
- verifyRemoveInterfaceQuota(TEST_IFACE);
- verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
- verifyPolicyDataEnable(TYPE_WIFI, true);
+ expectRemoveInterfaceQuota(TEST_IFACE);
+ expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+ expectAdvisePersistThreshold();
+ expectMeteredIfacesChanged(TEST_IFACE);
+
+ future = expectClearNotifications();
+ tagFuture = expectEnqueueNotification();
+
+ replay();
+ mService.snoozeLimit(sTemplateWifi);
+ assertNotificationType(TYPE_LIMIT_SNOOZED, tagFuture.get());
+ future.get();
+ verifyAndReset();
}
}
- @Test
+ @Suppress
public void testMeteredNetworkWithoutLimit() throws Exception {
NetworkState[] state = null;
NetworkStats stats = null;
+ Future<Void> future;
+ Future<String> tagFuture;
final long TIME_FEB_15 = 1171497600000L;
final long TIME_MAR_10 = 1173484800000L;
@@ -627,19 +785,24 @@
{
expectCurrentTime();
- when(mConnManager.getAllNetworkState()).thenReturn(state);
- when(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15,
- currentTimeMillis())).thenReturn(stats.getTotalBytes());
+ expect(mConnManager.getAllNetworkState()).andReturn(state).atLeastOnce();
+ expect(mStatsService.getNetworkTotalBytes(sTemplateWifi, TIME_FEB_15, currentTimeMillis()))
+ .andReturn(stats.getTotalBytes()).atLeastOnce();
+ expectPolicyDataEnable(TYPE_WIFI, true);
- mPolicyListener.expect().onMeteredIfacesChanged(any());
+ expectRemoveInterfaceQuota(TEST_IFACE);
+ expectSetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+
+ expectClearNotifications();
+ expectAdvisePersistThreshold();
+ future = expectMeteredIfacesChanged(TEST_IFACE);
+
+ replay();
setNetworkPolicies(new NetworkPolicy(
sTemplateWifi, CYCLE_DAY, TIMEZONE_UTC, WARNING_DISABLED, LIMIT_DISABLED,
true));
- mPolicyListener.waitAndVerify().onMeteredIfacesChanged(eq(new String[]{TEST_IFACE}));
-
- verifyPolicyDataEnable(TYPE_WIFI, true);
- verifyRemoveInterfaceQuota(TEST_IFACE);
- verifySetInterfaceQuota(TEST_IFACE, Long.MAX_VALUE);
+ future.get();
+ verifyAndReset();
}
}
@@ -662,36 +825,87 @@
}
private void expectCurrentTime() throws Exception {
- when(mTime.forceRefresh()).thenReturn(false);
- when(mTime.hasCache()).thenReturn(true);
- when(mTime.currentTimeMillis()).thenReturn(currentTimeMillis());
- when(mTime.getCacheAge()).thenReturn(0L);
- when(mTime.getCacheCertainty()).thenReturn(0L);
+ expect(mTime.forceRefresh()).andReturn(false).anyTimes();
+ expect(mTime.hasCache()).andReturn(true).anyTimes();
+ expect(mTime.currentTimeMillis()).andReturn(currentTimeMillis()).anyTimes();
+ expect(mTime.getCacheAge()).andReturn(0L).anyTimes();
+ expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes();
+ }
+
+ private void expectForceUpdate() throws Exception {
+ mStatsService.forceUpdate();
+ expectLastCall().atLeastOnce();
+ }
+
+ private Future<Void> expectClearNotifications() throws Exception {
+ final FutureAnswer future = new FutureAnswer();
+ mNotifManager.cancelNotificationWithTag(
+ isA(String.class), isA(String.class), anyInt(), anyInt());
+ expectLastCall().andAnswer(future).anyTimes();
+ return future;
}
private Future<String> expectEnqueueNotification() throws Exception {
- final FutureAnswer<String> futureAnswer = new FutureAnswer<String>(2);
- doAnswer(futureAnswer).when(mNotifManager).enqueueNotificationWithTag(
- anyString(), anyString(), anyString() /* capture here (index 2)*/,
- anyInt(), isA(Notification.class), isA(int[].class), anyInt());
- return futureAnswer;
+ final FutureCapture<String> tag = new FutureCapture<String>();
+ mNotifManager.enqueueNotificationWithTag(isA(String.class), isA(String.class),
+ capture(tag.capture), anyInt(),
+ isA(Notification.class), isA(int[].class), UserHandle.myUserId());
+ return tag;
}
- private void verifySetInterfaceQuota(String iface, long quotaBytes) throws Exception {
- verify(mNetworkManager, atLeastOnce()).setInterfaceQuota(iface, quotaBytes);
+ private void expectSetInterfaceQuota(String iface, long quotaBytes) throws Exception {
+ mNetworkManager.setInterfaceQuota(iface, quotaBytes);
+ expectLastCall().atLeastOnce();
}
- private void verifyRemoveInterfaceQuota(String iface) throws Exception {
- verify(mNetworkManager, atLeastOnce()).removeInterfaceQuota(iface);
+ private void expectRemoveInterfaceQuota(String iface) throws Exception {
+ mNetworkManager.removeInterfaceQuota(iface);
+ expectLastCall().atLeastOnce();
}
- private Future<Void> verifyPolicyDataEnable(int type, boolean enabled) throws Exception {
+ private void expectSetInterfaceAlert(String iface, long alertBytes) throws Exception {
+ mNetworkManager.setInterfaceAlert(iface, alertBytes);
+ expectLastCall().atLeastOnce();
+ }
+
+ private void expectRemoveInterfaceAlert(String iface) throws Exception {
+ mNetworkManager.removeInterfaceAlert(iface);
+ expectLastCall().atLeastOnce();
+ }
+
+ private void expectSetUidMeteredNetworkBlacklist(int uid, boolean rejectOnQuotaInterfaces)
+ throws Exception {
+ mNetworkManager.setUidMeteredNetworkBlacklist(uid, rejectOnQuotaInterfaces);
+ expectLastCall().atLeastOnce();
+ }
+
+ private void expectSetUidForeground(int uid, boolean uidForeground) throws Exception {
+ mStatsService.setUidForeground(uid, uidForeground);
+ expectLastCall().atLeastOnce();
+ }
+
+ private Future<Void> expectRulesChanged(int uid, int policy) throws Exception {
+ final FutureAnswer future = new FutureAnswer();
+ mPolicyListener.onUidRulesChanged(eq(uid), eq(policy));
+ expectLastCall().andAnswer(future);
+ return future;
+ }
+
+ private Future<Void> expectMeteredIfacesChanged(String... ifaces) throws Exception {
+ final FutureAnswer future = new FutureAnswer();
+ mPolicyListener.onMeteredIfacesChanged(aryEq(ifaces));
+ expectLastCall().andAnswer(future);
+ return future;
+ }
+
+ private Future<Void> expectPolicyDataEnable(int type, boolean enabled) throws Exception {
// TODO: bring back this test
return null;
}
- private void verifyAdvisePersistThreshold() throws Exception {
- verify(mStatsService).advisePersistThreshold(anyLong());
+ private void expectAdvisePersistThreshold() throws Exception {
+ mStatsService.advisePersistThreshold(anyLong());
+ expectLastCall().anyTimes();
}
private static class TestAbstractFuture<T> extends AbstractFuture<T> {
@@ -705,21 +919,50 @@
}
}
- private static class FutureAnswer<T> extends TestAbstractFuture<T> implements Answer<Void> {
- private final int index;
-
- FutureAnswer(int index) {
- this.index = index;
- }
+ private static class FutureAnswer extends TestAbstractFuture<Void> implements IAnswer<Void> {
@Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- @SuppressWarnings("unchecked")
- T captured = (T) invocation.getArguments()[index];
- set(captured);
+ public Void answer() {
+ set(null);
return null;
}
}
+ private static class FutureCapture<T> extends TestAbstractFuture<T> {
+ public Capture<T> capture = new Capture<T>() {
+ @Override
+ public void setValue(T value) {
+ super.setValue(value);
+ set(value);
+ }
+ };
+ }
+
+ private static class IdleFuture extends AbstractFuture<Void> implements IdleHandler {
+ @Override
+ public Void get() throws InterruptedException, ExecutionException {
+ try {
+ return get(5, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean queueIdle() {
+ set(null);
+ return false;
+ }
+ }
+
+ /**
+ * Wait until {@link #mService} internal {@link Handler} is idle.
+ */
+ private IdleFuture expectIdle() {
+ final IdleFuture future = new IdleFuture();
+ mService.addIdleHandler(future);
+ return future;
+ }
+
private static void assertTimeEquals(long expected, long actual) {
if (expected != actual) {
fail("expected " + formatTime(expected) + " but was actually " + formatTime(actual));
@@ -747,7 +990,7 @@
}
private static void assertNotificationType(int expected, String actualTag) {
- assertEquals("notification type mismatch for '" + actualTag +"'",
+ assertEquals(
Integer.toString(expected), actualTag.substring(actualTag.lastIndexOf(':') + 1));
}
@@ -768,59 +1011,15 @@
mElapsedRealtime += duration;
}
- /**
- * Creates a mock and registers it to {@link LocalServices}.
- */
- private static <T> T addLocalServiceMock(Class<T> clazz) {
- final T mock = mock(clazz);
- LocalServices.addService(clazz, mock);
- return mock;
+ private void replay() {
+ EasyMock.replay(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
+ mConnManager, mNotifManager);
}
- /**
- * Custom Mockito answer used to verify async {@link INetworkPolicyListener} calls.
- *
- * <p>Typical usage:
- * <pre><code>
- * mPolicyListener.expect().someCallback(any());
- * // do something on objects under test
- * mPolicyListener.waitAndVerify().someCallback(eq(expectedValue));
- * </code></pre>
- */
- final class NetworkPolicyListenerAnswer implements Answer<Void> {
- private CountDownLatch latch;
- private final INetworkPolicyListener listener;
-
- NetworkPolicyListenerAnswer(NetworkPolicyManagerService service) {
- this.listener = mock(INetworkPolicyListener.class);
- // RemoteCallbackList needs a binder to use as key
- when(listener.asBinder()).thenReturn(new Binder());
- service.registerListener(listener);
- }
-
- @Override
- public Void answer(InvocationOnMock invocation) throws Throwable {
- Log.d(TAG,"counting down on answer: " + invocation);
- latch.countDown();
- return null;
- }
-
- INetworkPolicyListener expect() {
- assertNull("expect() called before waitAndVerify()", latch);
- latch = new CountDownLatch(1);
- return doAnswer(this).when(listener);
- }
-
- INetworkPolicyListener waitAndVerify() {
- assertNotNull("waitAndVerify() called before expect()", latch);
- try {
- assertTrue("callback not called in 5 seconds", latch.await(5, TimeUnit.SECONDS));
- } catch (InterruptedException e) {
- fail("Thread interrupted before callback called");
- } finally {
- latch = null;
- }
- return verify(listener, atLeastOnce());
- }
+ private void verifyAndReset() {
+ EasyMock.verify(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
+ mConnManager, mNotifManager);
+ EasyMock.reset(mActivityManager, mStatsService, mPolicyListener, mNetworkManager, mTime,
+ mConnManager, mNotifManager);
}
}
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index aa491bb..14b5cbe 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -19,7 +19,6 @@
import android.content.Context;
import android.net.ConnectivityMetricsEvent;
import android.net.IIpConnectivityMetrics;
-import android.net.metrics.ApfProgramEvent;
import android.net.metrics.ApfStats;
import android.net.metrics.DefaultNetworkEvent;
import android.net.metrics.DhcpClientEvent;
@@ -113,27 +112,6 @@
assertEquals("", output3);
}
- public void testRateLimiting() {
- final IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
- final ApfProgramEvent ev = new ApfProgramEvent(0, 0, 0, 0, 0);
- final long fakeTimestamp = 1;
-
- int attempt = 100; // More than burst quota, but less than buffer size.
- for (int i = 0; i < attempt; i++) {
- logger.log(ev);
- }
-
- String output1 = getdump("flush");
- assertFalse("".equals(output1));
-
- for (int i = 0; i < attempt; i++) {
- assertFalse("expected event to be dropped", logger.log(fakeTimestamp, ev));
- }
-
- String output2 = getdump("flush");
- assertEquals("", output2);
- }
-
public void testEndToEndLogging() {
IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
deleted file mode 100644
index 813e928..0000000
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2016 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.connectivity;
-
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.telephony.TelephonyManager;
-import android.test.suitebuilder.annotation.SmallTest;
-import com.android.server.connectivity.NetworkNotificationManager.NotificationType;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import junit.framework.TestCase;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.*;
-import static org.mockito.Mockito.any;
-import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class NetworkNotificationManagerTest extends TestCase {
-
- static final String NOTIFICATION_ID = NetworkNotificationManager.NOTIFICATION_ID;
-
- static final NetworkCapabilities CELL_CAPABILITIES = new NetworkCapabilities();
- static final NetworkCapabilities WIFI_CAPABILITIES = new NetworkCapabilities();
- static {
- CELL_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
- CELL_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
-
- WIFI_CAPABILITIES.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
- WIFI_CAPABILITIES.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- }
-
- @Mock Context mCtx;
- @Mock Resources mResources;
- @Mock PackageManager mPm;
- @Mock TelephonyManager mTelephonyManager;
- @Mock NotificationManager mNotificationManager;
- @Mock NetworkAgentInfo mWifiNai;
- @Mock NetworkAgentInfo mCellNai;
- @Mock NetworkInfo mNetworkInfo;
- ArgumentCaptor<Notification> mCaptor;
-
- NetworkNotificationManager mManager;
-
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mCaptor = ArgumentCaptor.forClass(Notification.class);
- mWifiNai.networkCapabilities = WIFI_CAPABILITIES;
- mWifiNai.networkInfo = mNetworkInfo;
- mCellNai.networkCapabilities = CELL_CAPABILITIES;
- mCellNai.networkInfo = mNetworkInfo;
- when(mCtx.getResources()).thenReturn(mResources);
- when(mCtx.getPackageManager()).thenReturn(mPm);
- when(mCtx.getApplicationInfo()).thenReturn(new ApplicationInfo());
- when(mResources.getColor(anyInt(), any())).thenReturn(0xFF607D8B);
-
- mManager = new NetworkNotificationManager(mCtx, mTelephonyManager, mNotificationManager);
- }
-
- @SmallTest
- public void testNotificationsShownAndCleared() {
- final int NETWORK_ID_BASE = 100;
- List<NotificationType> types = Arrays.asList(NotificationType.values());
- List<Integer> ids = new ArrayList<>(types.size());
- for (int i = 0; i < ids.size(); i++) {
- ids.add(NETWORK_ID_BASE + i);
- }
- Collections.shuffle(ids);
- Collections.shuffle(types);
-
- for (int i = 0; i < ids.size(); i++) {
- mManager.showNotification(ids.get(i), types.get(i), mWifiNai, mCellNai, null, false);
- }
-
- Collections.shuffle(ids);
- for (int i = 0; i < ids.size(); i++) {
- mManager.clearNotification(ids.get(i));
- }
-
- for (int i = 0; i < ids.size(); i++) {
- final int expectedId = NETWORK_ID_BASE + i;
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(NOTIFICATION_ID), eq(expectedId), any(), any());
- verify(mNotificationManager, times(1))
- .cancelAsUser(eq(NOTIFICATION_ID), eq(expectedId), any());
- }
- }
-
- @SmallTest
- public void testNoInternetNotificationsNotShownForCellular() {
- mManager.showNotification(100, NO_INTERNET, mCellNai, mWifiNai, null, false);
- mManager.showNotification(101, LOST_INTERNET, mCellNai, mWifiNai, null, false);
-
- verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
-
- mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
-
- verify(mNotificationManager, times(1))
- .notifyAsUser(eq(NOTIFICATION_ID), eq(102), any(), any());
- }
-
- @SmallTest
- public void testNotificationsNotShownIfNoInternetCapability() {
- mWifiNai.networkCapabilities = new NetworkCapabilities();
- mWifiNai.networkCapabilities .addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
- mManager.showNotification(102, NO_INTERNET, mWifiNai, mCellNai, null, false);
- mManager.showNotification(103, LOST_INTERNET, mWifiNai, mCellNai, null, false);
- mManager.showNotification(104, NETWORK_SWITCH, mWifiNai, mCellNai, null, false);
-
- verify(mNotificationManager, never()).notifyAsUser(any(), anyInt(), any(), any());
- }
-}