DynamicDenylistManager shall not exist

Remove DynamicDenylistManager to avoid its conflicting behavior
with our firewall. This stops the resetting of firewall policies
on boot and for other reasons. The user is in control of these
policies and doesn't need them to be unexpectedly reset.

Issue: calyxos#2211
Test: Manual: Turn off Background network access for any app. Then,
in Firewall, turn off another toggle like Wi-Fi. Reboot, and check
the toggles. Background network access and Wi-Fi should still be off.
Change-Id: Ie62ddfa3a893c9adf5d4fd0c8670235a5a51e03f
This commit is contained in:
Tommy Webb
2024-03-21 14:46:34 +00:00
committed by Michael Bestas
parent 668fe20d73
commit a8f79a720f
7 changed files with 1 additions and 736 deletions

View File

@@ -53,7 +53,6 @@ import androidx.preference.PreferenceCategory;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settings.deviceinfo.StorageWizardMoveConfirm;
import com.android.settings.fuelgauge.datasaver.DynamicDenylistManager;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.applications.AppUtils;
import com.android.settingslib.applications.ApplicationsState.Callbacks;
@@ -362,8 +361,6 @@ public class AppStorageSettings extends AppInfoWithHeader
mButtonsPref.setButton1Enabled(false);
// Invoke uninstall or clear user data based on sysPackage
String packageName = mAppEntry.info.packageName;
DynamicDenylistManager.getInstance(getContext())
.resetDenylistIfNeeded(packageName, /* force= */ false);
Log.i(TAG, "Clearing user data for package : " + packageName);
if (mClearDataObserver == null) {
mClearDataObserver = new ClearUserDataObserver();

View File

@@ -39,7 +39,6 @@ import androidx.appcompat.app.AlertDialog;
import com.android.settings.R;
import com.android.settings.fuelgauge.BatteryOptimizeUtils;
import com.android.settings.fuelgauge.datasaver.DynamicDenylistManager;
import java.util.Arrays;
import java.util.List;
@@ -156,8 +155,6 @@ public class ResetAppsHelper implements DialogInterface.OnClickListener,
}
mAom.resetAllModes();
BatteryOptimizeUtils.resetAppOptimizationMode(mContext, mIPm, mAom);
DynamicDenylistManager.getInstance(mContext)
.resetDenylistIfNeeded(/* packageName= */ null, /* force= */ true);
final int[] restrictedUids = mNpm.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND);
final int currentUserId = ActivityManager.getCurrentUser();
for (int uid : restrictedUids) {

View File

@@ -50,7 +50,6 @@ import com.android.settings.R;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.datausage.lib.AppDataUsageDetailsRepository;
import com.android.settings.datausage.lib.NetworkTemplates;
import com.android.settings.fuelgauge.datasaver.DynamicDenylistManager;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.AppItem;

View File

@@ -23,7 +23,6 @@ import android.content.Context;
import android.net.NetworkPolicyManager;
import android.util.SparseIntArray;
import com.android.settings.fuelgauge.datasaver.DynamicDenylistManager;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.ThreadUtils;
@@ -40,7 +39,6 @@ public class DataSaverBackend {
private final MetricsFeatureProvider mMetricsFeatureProvider;
private final NetworkPolicyManager mPolicyManager;
private final DynamicDenylistManager mDynamicDenylistManager;
private final ArrayList<Listener> mListeners = new ArrayList<>();
private SparseIntArray mUidPolicies = new SparseIntArray();
private boolean mAllowlistInitialized;
@@ -52,7 +50,6 @@ public class DataSaverBackend {
mContext = context.getApplicationContext();
mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
mPolicyManager = NetworkPolicyManager.from(mContext);
mDynamicDenylistManager = DynamicDenylistManager.getInstance(mContext);
}
public void addListener(Listener listener) {
@@ -132,8 +129,7 @@ public class DataSaverBackend {
public boolean isDenylisted(int uid) {
loadDenylist();
return mUidPolicies.get(uid, POLICY_NONE) == POLICY_REJECT_METERED_BACKGROUND
&& mDynamicDenylistManager.isInManualDenylist(uid);
return mUidPolicies.get(uid, POLICY_NONE) == POLICY_REJECT_METERED_BACKGROUND;
}
private void loadDenylist() {

View File

@@ -26,7 +26,6 @@ import android.util.Log;
import androidx.annotation.VisibleForTesting;
import com.android.settings.fuelgauge.batterysaver.BatterySaverScheduleRadioButtonsController;
import com.android.settings.fuelgauge.datasaver.DynamicDenylistManager;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
import java.util.List;
@@ -51,7 +50,6 @@ public final class BatterySettingsMigrateChecker extends BroadcastReceiver {
context = context.getApplicationContext();
verifySaverConfiguration(context);
verifyBatteryOptimizeModes(context);
DynamicDenylistManager.getInstance(context).onBootComplete();
}
/** Avoid users set important apps into the unexpected battery optimize modes */

View File

@@ -1,276 +0,0 @@
/*
* Copyright (C) 2023 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.settings.fuelgauge.datasaver;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.NetworkPolicyManager;
import android.util.ArraySet;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/** A class to dynamically manage per apps {@link NetworkPolicyManager} POLICY_ flags. */
public class DynamicDenylistManager {
private static final String TAG = "DynamicDenylistManager";
private static final String PREF_KEY_MANUAL_DENY = "manual_denylist_preference";
private static final String PREF_KEY_DYNAMIC_DENY = "dynamic_denylist_preference";
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
public static DynamicDenylistManager sInstance = null;
private final Context mContext;
private final NetworkPolicyManager mNetworkPolicyManager;
private final Object mLock = new Object();
@VisibleForTesting
static final String PREF_KEY_MANUAL_DENYLIST_SYNCED = "manual_denylist_synced";
/** @return a DynamicDenylistManager object */
public static DynamicDenylistManager getInstance(Context context) {
synchronized (DynamicDenylistManager.class) {
if (sInstance == null) {
sInstance = new DynamicDenylistManager(
context, NetworkPolicyManager.from(context));
}
return sInstance;
}
}
@VisibleForTesting
DynamicDenylistManager(Context context, NetworkPolicyManager networkPolicyManager) {
mContext = context.getApplicationContext();
mNetworkPolicyManager = networkPolicyManager;
syncPolicyIfNeeded();
}
/** Sync the policy from {@link NetworkPolicyManager} if needed. */
private void syncPolicyIfNeeded() {
if (getManualDenylistPref().contains(PREF_KEY_MANUAL_DENYLIST_SYNCED)) {
Log.i(TAG, "syncPolicyIfNeeded() ignore synced manual denylist");
return;
}
if (mNetworkPolicyManager == null) {
Log.w(TAG, "syncPolicyIfNeeded: invalid mNetworkPolicyManager");
return;
}
final SharedPreferences.Editor editor = getManualDenylistPref().edit();
final int[] existedUids = mNetworkPolicyManager
.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND);
if (existedUids != null && existedUids.length != 0) {
for (int uid : existedUids) {
editor.putInt(String.valueOf(uid), POLICY_REJECT_METERED_BACKGROUND);
}
}
editor.putInt(PREF_KEY_MANUAL_DENYLIST_SYNCED, POLICY_NONE).apply();
}
/** Set policy flags for specific UID. */
public void setUidPolicyLocked(int uid, int policy) {
if (mNetworkPolicyManager == null) {
Log.w(TAG, "setUidPolicyLocked: invalid mNetworkPolicyManager");
return;
}
Log.i(TAG, "setUidPolicyLocked: uid=" + uid + " policy=" + policy);
synchronized (mLock) {
mNetworkPolicyManager.setUidPolicy(uid, policy);
}
updateDenylistPref(uid, policy);
}
/** Suggest a list of package to set as POLICY_REJECT. */
public void setDenylist(Set<Integer> denylistTargetUids) {
if (denylistTargetUids == null || mNetworkPolicyManager == null) {
return;
}
final Set<Integer> manualDenylistUids = getDenylistAllUids(getManualDenylistPref());
denylistTargetUids.removeAll(manualDenylistUids);
final Set<Integer> lastDynamicDenylistUids = getDenylistAllUids(getDynamicDenylistPref());
if (lastDynamicDenylistUids.equals(denylistTargetUids)) {
Log.i(TAG, "setDenylist() ignore the same denylist with size: "
+ lastDynamicDenylistUids.size());
return;
}
final ArraySet<Integer> failedUids = new ArraySet<>();
synchronized (mLock) {
// Set new added UIDs into REJECT policy.
for (Integer uidInteger : denylistTargetUids) {
if (uidInteger == null) {
continue;
}
final int uid = uidInteger.intValue();
if (!lastDynamicDenylistUids.contains(uid)) {
try {
mNetworkPolicyManager.setUidPolicy(uid, POLICY_REJECT_METERED_BACKGROUND);
} catch (Exception e) {
Log.e(TAG, "failed to setUidPolicy(REJECT) for " + uid, e);
failedUids.add(uid);
}
}
}
// Unset removed UIDs back to NONE policy.
for (int uid : lastDynamicDenylistUids) {
if (!denylistTargetUids.contains(uid)) {
try {
mNetworkPolicyManager.setUidPolicy(uid, POLICY_NONE);
} catch (Exception e) {
Log.e(TAG, "failed to setUidPolicy(NONE) for " + uid, e);
}
}
}
}
// Store target denied uids into DynamicDenylistPref.
final SharedPreferences.Editor editor = getDynamicDenylistPref().edit();
editor.clear();
denylistTargetUids.forEach(uid -> {
if (!failedUids.contains(uid)) {
editor.putInt(String.valueOf(uid), POLICY_REJECT_METERED_BACKGROUND);
}
});
editor.apply();
}
/** Return true if the target uid is in {@link #getManualDenylistPref()}. */
public boolean isInManualDenylist(int uid) {
return getManualDenylistPref().contains(String.valueOf(uid));
}
/** Reset the UIDs in the denylist if needed. */
public void resetDenylistIfNeeded(String packageName, boolean force) {
if (!force && !SETTINGS_PACKAGE_NAME.equals(packageName)) {
Log.w(TAG, "resetDenylistIfNeeded: invalid conditions");
return;
}
if (mNetworkPolicyManager == null) {
Log.w(TAG, "setUidPolicyLocked: invalid mNetworkPolicyManager");
return;
}
synchronized (mLock) {
final int[] uids = mNetworkPolicyManager
.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND);
if (uids != null && uids.length != 0) {
Log.i(TAG, "resetDenylistIfNeeded: " + Arrays.toString(uids));
for (int uid : uids) {
if (!getDenylistAllUids(getManualDenylistPref()).contains(uid)) {
mNetworkPolicyManager.setUidPolicy(uid, POLICY_NONE);
}
}
} else {
Log.w(TAG, "resetDenylistIfNeeded: there is no valid UIDs");
}
}
clearSharedPreferences();
}
/** Reset the POLICY_REJECT_METERED uids when device is boot completed. */
public void onBootComplete() {
resetDenylistIfNeeded(/* packageName= */ null, /* force= */ true);
syncPolicyIfNeeded();
}
/** Dump the data stored in the {@link SharedPreferences}. */
public void dump(PrintWriter writer) {
writer.println("Dump of DynamicDenylistManager:");
final List<String> manualDenyList =
getPackageNames(mContext, getDenylistAllUids(getManualDenylistPref()));
writer.println("\tManualDenylist:");
if (manualDenyList != null) {
manualDenyList.forEach(packageName -> writer.println("\t\t" + packageName));
writer.flush();
}
final List<String> dynamicDenyList =
getPackageNames(mContext, getDenylistAllUids(getDynamicDenylistPref()));
writer.println("\tDynamicDenylist:");
if (dynamicDenyList != null) {
dynamicDenyList.forEach(packageName -> writer.println("\t\t" + packageName));
writer.flush();
}
}
private Set<Integer> getDenylistAllUids(SharedPreferences sharedPreferences) {
final ArraySet<Integer> uids = new ArraySet<>();
for (String key : sharedPreferences.getAll().keySet()) {
if (PREF_KEY_MANUAL_DENYLIST_SYNCED.equals(key)) {
continue;
}
try {
uids.add(Integer.parseInt(key));
} catch (NumberFormatException e) {
Log.e(TAG, "getDenylistAllUids() unexpected format for " + key);
}
}
return uids;
}
void updateDenylistPref(int uid, int policy) {
final String uidString = String.valueOf(uid);
if (policy != POLICY_REJECT_METERED_BACKGROUND) {
getManualDenylistPref().edit().remove(uidString).apply();
} else {
getManualDenylistPref().edit().putInt(uidString, policy).apply();
}
getDynamicDenylistPref().edit().remove(uidString).apply();
}
void clearSharedPreferences() {
Log.i(TAG, "clearSharedPreferences()");
getManualDenylistPref().edit().clear().apply();
getDynamicDenylistPref().edit().clear().apply();
}
@VisibleForTesting
SharedPreferences getManualDenylistPref() {
return mContext.getSharedPreferences(PREF_KEY_MANUAL_DENY, Context.MODE_PRIVATE);
}
@VisibleForTesting
SharedPreferences getDynamicDenylistPref() {
return mContext.getSharedPreferences(PREF_KEY_DYNAMIC_DENY, Context.MODE_PRIVATE);
}
private static List<String> getPackageNames(Context context, Set<Integer> uids) {
if (uids == null || uids.isEmpty()) {
return null;
}
final PackageManager pm = context.getPackageManager();
final List<String> packageNames = new ArrayList<>(uids.size());
uids.forEach(uid -> packageNames.add(pm.getNameForUid(uid)));
return packageNames;
}
}

View File

@@ -1,446 +0,0 @@
/*
* Copyright (C) 2023 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.settings.fuelgauge.datasaver;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
import static com.android.settings.fuelgauge.datasaver.DynamicDenylistManager.PREF_KEY_MANUAL_DENYLIST_SYNCED;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.NetworkPolicyManager;
import android.util.ArraySet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.List;
import java.util.Set;
@RunWith(RobolectricTestRunner.class)
public class DynamicDenylistManagerTest {
private static final int[] EMPTY_ARRAY = new int[] {};
private static final String FAKE_UID_1 = "1001";
private static final String FAKE_UID_2 = "1002";
private static final int FAKE_UID_1_INT = Integer.parseInt(FAKE_UID_1);
private static final int FAKE_UID_2_INT = Integer.parseInt(FAKE_UID_2);
private SharedPreferences mManualDenyListPref;
private SharedPreferences mDynamicDenyListPref;
private DynamicDenylistManager mDynamicDenylistManager;
@Mock
private NetworkPolicyManager mNetworkPolicyManager;
@Mock
private PackageManager mPackageManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
}
@After
public void tearDown() {
mDynamicDenylistManager.clearSharedPreferences();
}
@Test
public void init_withoutExistedRejectPolicy_createWithExpectedValue() {
initDynamicDenylistManager(EMPTY_ARRAY);
assertThat(mManualDenyListPref.getAll()).hasSize(1);
assertTrue(mManualDenyListPref.contains(PREF_KEY_MANUAL_DENYLIST_SYNCED));
}
@Test
public void init_withExistedRejectPolicy_createWithExpectedValue() {
initDynamicDenylistManager(new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT});
assertThat(mManualDenyListPref.getAll()).hasSize(3);
assertTrue(mManualDenyListPref.contains(PREF_KEY_MANUAL_DENYLIST_SYNCED));
assertTrue(mManualDenyListPref.contains(FAKE_UID_1));
assertTrue(mManualDenyListPref.contains(FAKE_UID_2));
}
@Test
public void getManualDenylistPref_initiated_containsExpectedValue() {
initDynamicDenylistManager(EMPTY_ARRAY);
setupPreference(mManualDenyListPref, FAKE_UID_1);
assertTrue(mManualDenyListPref.contains(FAKE_UID_1));
}
@Test
public void getDynamicDenylistPref_initiated_containsExpectedValue() {
initDynamicDenylistManager(EMPTY_ARRAY);
setupPreference(mDynamicDenyListPref, FAKE_UID_1);
assertTrue(mDynamicDenyListPref.contains(FAKE_UID_1));
}
@Test
public void updateManualDenylist_policyReject_addsUid() {
initDynamicDenylistManager(EMPTY_ARRAY);
mDynamicDenylistManager.updateDenylistPref(FAKE_UID_1_INT,
POLICY_REJECT_METERED_BACKGROUND);
assertTrue(mManualDenyListPref.contains(FAKE_UID_1));
}
@Test
public void updateManualDenylist_policyNone_removesUid() {
initDynamicDenylistManager(EMPTY_ARRAY);
setupPreference(mManualDenyListPref, FAKE_UID_1);
assertTrue(mManualDenyListPref.contains(FAKE_UID_1));
mDynamicDenylistManager.updateDenylistPref(FAKE_UID_1_INT, POLICY_NONE);
assertFalse(mManualDenyListPref.contains(FAKE_UID_1));
}
@Test
public void updateManualDenylist_samePolicy_doNothing() {
initDynamicDenylistManager(EMPTY_ARRAY);
setupPreference(mManualDenyListPref, FAKE_UID_1);
assertTrue(mManualDenyListPref.contains(FAKE_UID_1));
assertThat(mManualDenyListPref.getAll()).hasSize(2);
mDynamicDenylistManager.updateDenylistPref(FAKE_UID_1_INT,
POLICY_REJECT_METERED_BACKGROUND);
assertThat(mManualDenyListPref.getAll()).hasSize(2);
}
@Test
public void setUidPolicyLocked_invokeSetUidPolicy() {
initDynamicDenylistManager(EMPTY_ARRAY);
mDynamicDenylistManager.setUidPolicyLocked(FAKE_UID_1_INT,
POLICY_REJECT_METERED_BACKGROUND);
assertTrue(mManualDenyListPref.contains(FAKE_UID_1));
verify(mNetworkPolicyManager).setUidPolicy(eq(FAKE_UID_1_INT),
eq(POLICY_REJECT_METERED_BACKGROUND));
}
@Test
public void setDenylist_emptyListAndNoData_doNothing() {
initDynamicDenylistManager(EMPTY_ARRAY);
setDenylist(Collections.emptySet());
verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), anyInt());
}
@Test
public void setDenylist_uidDeniedAlready_doNothing() {
initDynamicDenylistManager(new int[] {FAKE_UID_1_INT});
final ArraySet uids = new ArraySet<>();
uids.add(FAKE_UID_1_INT);
uids.add(null);
setDenylist(uids);
verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), anyInt());
}
@Test
public void setDenylist_sameList_doNothing() {
initDynamicDenylistManager(EMPTY_ARRAY);
setupPreference(mDynamicDenyListPref, FAKE_UID_2, FAKE_UID_1);
setDenylist(new ArraySet<>(List.of(FAKE_UID_1_INT, FAKE_UID_2_INT)));
verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), anyInt());
}
@Test
public void setDenylist_newListWithOldData_modifyPolicyNoneAndReject() {
initDynamicDenylistManager(EMPTY_ARRAY);
setupPreference(mDynamicDenyListPref, FAKE_UID_2);
setDenylist(new ArraySet<>(List.of(FAKE_UID_1_INT)));
verify(mNetworkPolicyManager).setUidPolicy(FAKE_UID_2_INT, POLICY_NONE);
verify(mNetworkPolicyManager).setUidPolicy(FAKE_UID_1_INT,
POLICY_REJECT_METERED_BACKGROUND);
assertThat(mDynamicDenyListPref.getAll()).hasSize(1);
assertTrue(mDynamicDenyListPref.contains(FAKE_UID_1));
}
@Test
public void setDenylist_newListWithoutOldData_modifyPolicyReject() {
initDynamicDenylistManager(EMPTY_ARRAY);
setDenylist(new ArraySet<>(List.of(FAKE_UID_1_INT)));
verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), eq(POLICY_NONE));
verify(mNetworkPolicyManager).setUidPolicy(FAKE_UID_1_INT,
POLICY_REJECT_METERED_BACKGROUND);
assertThat(mDynamicDenyListPref.getAll()).hasSize(1);
assertTrue(mDynamicDenyListPref.contains(FAKE_UID_1));
}
@Test
public void setDenylist_emptyListWithOldData_modifyPolicyNone() {
initDynamicDenylistManager(EMPTY_ARRAY);
setupPreference(mDynamicDenyListPref, FAKE_UID_2);
setDenylist(Collections.emptySet());
verify(mNetworkPolicyManager).setUidPolicy(FAKE_UID_2_INT, POLICY_NONE);
verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(),
eq(POLICY_REJECT_METERED_BACKGROUND));
assertThat(mDynamicDenyListPref.getAll()).isEmpty();
}
@Test
public void isInManualDenylist_returnsFalse() {
initDynamicDenylistManager(EMPTY_ARRAY);
assertFalse(mDynamicDenylistManager.isInManualDenylist(FAKE_UID_1_INT));
}
@Test
public void isInManualDenylist_incorrectUid_returnsFalse() {
initDynamicDenylistManager(EMPTY_ARRAY);
mManualDenyListPref.edit().putInt(FAKE_UID_2, POLICY_REJECT_METERED_BACKGROUND).apply();
assertFalse(mDynamicDenylistManager.isInManualDenylist(FAKE_UID_1_INT));
}
@Test
public void isInManualDenylist_initiated_returnsTrue() {
initDynamicDenylistManager(EMPTY_ARRAY);
mManualDenyListPref.edit().putInt(FAKE_UID_1, POLICY_REJECT_METERED_BACKGROUND).apply();
assertTrue(mDynamicDenylistManager.isInManualDenylist(FAKE_UID_1_INT));
}
@Test
public void resetDenylistIfNeeded_nullPackageName_doNothing() {
initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT});
mDynamicDenylistManager.resetDenylistIfNeeded(null, false);
assertThat(mManualDenyListPref.getAll()).hasSize(1);
verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), eq(POLICY_NONE));
}
@Test
public void resetDenylistIfNeeded_invalidPackageName_doNothing() {
initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT});
mDynamicDenylistManager.resetDenylistIfNeeded("invalid_package_name", false);
assertThat(mManualDenyListPref.getAll()).hasSize(1);
verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), eq(POLICY_NONE));
}
@Test
public void resetDenylistIfNeeded_denylistUnchanged_doNothingWithPolicy() {
initDynamicDenylistManager(new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT});
mDynamicDenylistManager.resetDenylistIfNeeded(SETTINGS_PACKAGE_NAME, false);
verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), eq(POLICY_NONE));
}
@Test
public void resetDenylistIfNeeded_denylistChanged_resetAndClear() {
initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT});
mDynamicDenylistManager.resetDenylistIfNeeded(SETTINGS_PACKAGE_NAME, false);
assertThat(mManualDenyListPref.getAll()).isEmpty();
verify(mNetworkPolicyManager, times(2)).setUidPolicy(anyInt(), eq(POLICY_NONE));
}
@Test
public void resetDenylistIfNeeded_forceResetWithNullPackageName_resetAndClear() {
initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_2_INT});
mDynamicDenylistManager.resetDenylistIfNeeded(null, true);
assertThat(mManualDenyListPref.getAll()).isEmpty();
verify(mNetworkPolicyManager).setUidPolicy(eq(FAKE_UID_2_INT), eq(POLICY_NONE));
}
@Test
public void resetDenylistIfNeeded_forceResetWithInvalidPackageName_resetAndClear() {
initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT});
mDynamicDenylistManager.resetDenylistIfNeeded("invalid_package_name", true);
assertThat(mManualDenyListPref.getAll()).isEmpty();
verify(mNetworkPolicyManager, times(2)).setUidPolicy(anyInt(), eq(POLICY_NONE));
}
@Test
public void resetDenylistIfNeeded_forceResetButDenylistUnchanged_doNothingWithPolicy() {
initDynamicDenylistManager(new int[] {FAKE_UID_1_INT});
mDynamicDenylistManager.resetDenylistIfNeeded(SETTINGS_PACKAGE_NAME, true);
assertThat(mManualDenyListPref.getAll()).isEmpty();
verify(mNetworkPolicyManager, never()).setUidPolicy(anyInt(), eq(POLICY_NONE));
}
@Test
public void resetDenylistIfNeeded_forceResetWithDenylistChanged_resetAndClear() {
initDynamicDenylistManager(new int[0], new int[] {FAKE_UID_1_INT, FAKE_UID_2_INT});
mDynamicDenylistManager.resetDenylistIfNeeded(SETTINGS_PACKAGE_NAME, true);
assertThat(mManualDenyListPref.getAll()).isEmpty();
verify(mNetworkPolicyManager, times(2)).setUidPolicy(anyInt(), eq(POLICY_NONE));
}
@Test
public void clearSharedPreferences_manualDenyListPrefIsEmpty() {
initDynamicDenylistManager(EMPTY_ARRAY);
mManualDenyListPref.edit().putInt(FAKE_UID_1, POLICY_REJECT_METERED_BACKGROUND).apply();
assertThat(mManualDenyListPref.getAll()).hasSize(2);
assertTrue(mManualDenyListPref.contains(FAKE_UID_1));
assertTrue(mManualDenyListPref.contains(PREF_KEY_MANUAL_DENYLIST_SYNCED));
mDynamicDenylistManager.clearSharedPreferences();
assertThat(mManualDenyListPref.getAll()).isEmpty();
}
@Test
public void clearSharedPreferences_dynamicDenyListPrefIsEmpty() {
initDynamicDenylistManager(EMPTY_ARRAY);
mDynamicDenyListPref.edit().putInt(FAKE_UID_1, POLICY_REJECT_METERED_BACKGROUND).apply();
assertThat(mDynamicDenyListPref.getAll()).hasSize(1);
assertTrue(mDynamicDenyListPref.contains(FAKE_UID_1));
mDynamicDenylistManager.clearSharedPreferences();
assertThat(mDynamicDenyListPref.getAll()).isEmpty();
}
@Test
public void dump_dumpExpectedResult() {
initDynamicDenylistManager(EMPTY_ARRAY);
setupPreference(mManualDenyListPref, FAKE_UID_1);
setupPreference(mDynamicDenyListPref, FAKE_UID_2);
final StringWriter stringWriter = new StringWriter();
final PrintWriter printWriter = new PrintWriter(stringWriter);
when(mPackageManager.getNameForUid(FAKE_UID_1_INT)).thenReturn("app1");
when(mPackageManager.getNameForUid(FAKE_UID_2_INT)).thenReturn("app2");
mDynamicDenylistManager.dump(printWriter);
final String dumpResults = stringWriter.toString();
assertThat(dumpResults.contains("\tManualDenylist:\n\t\tapp1")).isTrue();
assertThat(dumpResults.contains("\tDynamicDenylist:\n\t\tapp2")).isTrue();
}
@Test
public void dump_withEmptySharedPreferences_dumpExpectedResult() {
initDynamicDenylistManager(EMPTY_ARRAY, EMPTY_ARRAY);
mDynamicDenylistManager.clearSharedPreferences();
final StringWriter stringWriter = new StringWriter();
final PrintWriter printWriter = new PrintWriter(stringWriter);
mDynamicDenylistManager.dump(printWriter);
final String dumpResults = stringWriter.toString();
assertThat(dumpResults.contains("Dump of DynamicDenylistManager:")).isTrue();
assertThat(dumpResults.contains("\tManualDenylist:\n\tDynamicDenylist:")).isTrue();
}
@Test
public void onBootComplete_resetIntoManualMode() {
initDynamicDenylistManager(new int[] {FAKE_UID_1_INT});
setDenylist(new ArraySet<>(List.of(FAKE_UID_2_INT)));
// Ensure the testing environment for manual denylist.
assertThat(mManualDenyListPref.getAll()).hasSize(2);
assertTrue(mManualDenyListPref.contains(PREF_KEY_MANUAL_DENYLIST_SYNCED));
assertTrue(mManualDenyListPref.contains(FAKE_UID_1));
// Ensure the testing environment for dynamic denylist.
assertThat(mDynamicDenyListPref.getAll()).hasSize(1);
mDynamicDenylistManager.onBootComplete();
// Keep the users set uids in the manual denylist.
assertThat(mManualDenyListPref.getAll()).hasSize(2);
assertTrue(mManualDenyListPref.contains(PREF_KEY_MANUAL_DENYLIST_SYNCED));
assertTrue(mManualDenyListPref.contains(FAKE_UID_1));
// Clear the uids in the dynamic denylist.
assertThat(mDynamicDenyListPref.getAll()).isEmpty();
}
private void initDynamicDenylistManager(int[] preload) {
initDynamicDenylistManager(preload, preload);
}
private void initDynamicDenylistManager(int[] preload1, int[] preload2) {
final Context context = spy(RuntimeEnvironment.application.getApplicationContext());
when(context.getApplicationContext()).thenReturn(context);
when(context.getPackageManager()).thenReturn(mPackageManager);
when(mNetworkPolicyManager.getUidsWithPolicy(anyInt()))
.thenReturn(preload1).thenReturn(preload2);
mDynamicDenylistManager = new DynamicDenylistManager(context, mNetworkPolicyManager);
mManualDenyListPref = mDynamicDenylistManager.getManualDenylistPref();
mDynamicDenyListPref = mDynamicDenylistManager.getDynamicDenylistPref();
}
private void setDenylist(Set<Integer> packageNameList) {
mDynamicDenylistManager.setDenylist(packageNameList);
}
private void setupPreference(SharedPreferences sharedPreferences, String... uids) {
final SharedPreferences.Editor editor = sharedPreferences.edit();
for (String uid : uids) {
editor.putInt(uid, POLICY_REJECT_METERED_BACKGROUND);
}
editor.apply();
}
}