fixup! Fix background data clobbering other policies

* Rename variables/arguments to clarify that we are working with policy
  flags, meaning that there can be multiple policies described by a
  uid policy, not just one.
* When checking policies for a policy flag, do a proper flag check,
  rather than a direct comparison that assumes one single policy.
* Only alter the displayed setting for the "Background network access"
  and "Unrestricted mobile data usage" toggles in response to underlying
  policy changes, to ensure their state represents the current reality.
* Add a couple explanatory comments.

Test: Manual: Install an app that does not have INTERNET permission.
Open the "Unrestricted mobile data" page of Settings. Try to activate
the toggle for such an app. The toggle should activate successfully
without needing to be tapped twice.

Issue: calyxos#2547
Change-Id: I9f2f028be4a21158a68c60982253d85586f60cdb
This commit is contained in:
Tommy Webb
2025-02-20 21:39:15 +00:00
committed by Joey
parent 241740eada
commit ec595b5b38
2 changed files with 31 additions and 30 deletions

View File

@@ -244,27 +244,23 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC
if (preference == mRestrictBackground) { if (preference == mRestrictBackground) {
mDataSaverBackend.setIsDenylisted(mAppItem.key, mPackageName, !(Boolean) newValue); mDataSaverBackend.setIsDenylisted(mAppItem.key, mPackageName, !(Boolean) newValue);
updatePrefs(); updatePrefs();
return true;
} else if (preference == mRestrictAll) { } else if (preference == mRestrictAll) {
setAppRestrictAll(!(Boolean) newValue); setAppRestrictAll(!(Boolean) newValue);
updatePrefs(); updatePrefs();
return true;
} else if (preference == mRestrictCellular) { } else if (preference == mRestrictCellular) {
setAppRestrictCellular(!(Boolean) newValue); setAppRestrictCellular(!(Boolean) newValue);
updatePrefs(); updatePrefs();
return true;
} else if (preference == mRestrictVpn) { } else if (preference == mRestrictVpn) {
setAppRestrictVpn(!(Boolean) newValue); setAppRestrictVpn(!(Boolean) newValue);
updatePrefs(); updatePrefs();
return true;
} else if (preference == mRestrictWifi) { } else if (preference == mRestrictWifi) {
setAppRestrictWifi(!(Boolean) newValue); setAppRestrictWifi(!(Boolean) newValue);
updatePrefs(); updatePrefs();
return true;
} else if (preference == mUnrestrictedData) { } else if (preference == mUnrestrictedData) {
mDataSaverBackend.setIsAllowlisted(mAppItem.key, mPackageName, (Boolean) newValue); mDataSaverBackend.setIsAllowlisted(mAppItem.key, mPackageName, (Boolean) newValue);
return true; updatePrefs();
} }
// updatePrefs() will alter toggle states based on the actual underlying value.
return false; return false;
} }

View File

@@ -122,57 +122,62 @@ public class DataSaverBackend {
mPolicyManager.removeUidPolicy(uid, POLICY_ALLOW_METERED_BACKGROUND); mPolicyManager.removeUidPolicy(uid, POLICY_ALLOW_METERED_BACKGROUND);
} }
private void loadUidPolicies(int policy) { private void loadUidPolicies(int policyFlag) {
final int[] uidsWithPolicyArray = mPolicyManager.getUidsWithPolicy(policy); final int[] uidsWithPolicyArray = mPolicyManager.getUidsWithPolicy(policyFlag);
final ArrayList<Integer> uidsWithPolicy = new ArrayList<>(uidsWithPolicyArray.length); final ArrayList<Integer> uidsWithPolicyFlag = new ArrayList<>(uidsWithPolicyArray.length);
// Convert from int[] to a list of Integer.
for (final int uid : uidsWithPolicyArray) { for (final int uid : uidsWithPolicyArray) {
uidsWithPolicy.add(uid); uidsWithPolicyFlag.add(uid);
} }
// Update existing cached UID policies. // Update existing cached UID policies.
for (int i = 0; i < mUidPolicies.size(); i++) { for (int i = 0; i < mUidPolicies.size(); i++) {
final Integer cachedEntryUid = mUidPolicies.keyAt(i); final Integer cachedEntryUid = mUidPolicies.keyAt(i);
if (uidsWithPolicy.remove(cachedEntryUid)) { if (uidsWithPolicyFlag.remove(cachedEntryUid)) {
// UID had the policy. It was removed so we don't have to process it twice. // UID had the policy. It was removed so we don't have to process it twice.
setCachedUidPolicyFlagAt(i, policy, true); setCachedUidPolicyFlagAt(i, policyFlag, true);
} else { } else {
// UID does not have the policy. // UID does not have the policy.
setCachedUidPolicyFlagAt(i, policy, false); setCachedUidPolicyFlagAt(i, policyFlag, false);
} }
} }
// Add policies for remaining UIDs, which did not have cached policies, so we're it. // Add policies for remaining UIDs, which did not have cached policies, so we're it.
for (final int uid : uidsWithPolicy) { for (final int uid : uidsWithPolicyFlag) {
mUidPolicies.put(uid, policy); mUidPolicies.put(uid, policyFlag);
} }
} }
private void setCachedUidPolicyFlag(int uid, int policy, boolean add) { private void setCachedUidPolicyFlag(int uid, int policyFlag, boolean add) {
final int index = mUidPolicies.indexOfKey(uid); final int index = mUidPolicies.indexOfKey(uid);
if (index < 0) { if (index < 0) {
if (add) { if (add) {
mUidPolicies.put(uid, policy); mUidPolicies.put(uid, policyFlag);
} }
return; return;
} }
setCachedUidPolicyFlagAt(index, policy, add); setCachedUidPolicyFlagAt(index, policyFlag, add);
} }
private void setCachedUidPolicyFlagAt(int index, int policy, boolean add) { private void setCachedUidPolicyFlagAt(int index, int policyFlag, boolean add) {
final int currentPolicy = mUidPolicies.valueAt(index); final int currentPolicy = mUidPolicies.valueAt(index);
final int newPolicy = add ? (currentPolicy | policy) : (currentPolicy & ~policy); final int newPolicy = add ? (currentPolicy | policyFlag) : (currentPolicy & ~policyFlag);
mUidPolicies.setValueAt(index, newPolicy); mUidPolicies.setValueAt(index, newPolicy);
} }
private void setUidPolicyFlag(int uid, int policy, boolean add) { private void setUidPolicyFlag(int uid, int policyFlag, boolean add) {
if (add) { if (add) {
mPolicyManager.addUidPolicy(uid, policy); mPolicyManager.addUidPolicy(uid, policyFlag);
} else { } else {
mPolicyManager.removeUidPolicy(uid, policy); mPolicyManager.removeUidPolicy(uid, policyFlag);
} }
setCachedUidPolicyFlag(uid, policy, add); setCachedUidPolicyFlag(uid, policyFlag, add);
} }
private boolean isUidPolicyFlagSet(int uid, int policy) { private boolean isUidPolicyFlagSet(int uid, int policyFlag) {
return (mUidPolicies.get(uid, POLICY_NONE) & policy) == policy; return isFlagSet(mUidPolicies.get(uid, POLICY_NONE), policyFlag);
}
private static boolean isFlagSet(int overallPolicy, int policyFlag) {
return (overallPolicy & policyFlag) == policyFlag;
} }
public boolean isDenylisted(int uid) { public boolean isDenylisted(int uid) {
@@ -220,10 +225,10 @@ public class DataSaverBackend {
mUidPolicies.put(uid, newPolicy); mUidPolicies.put(uid, newPolicy);
} }
final boolean wasAllowlisted = oldPolicy == POLICY_ALLOW_METERED_BACKGROUND; final boolean wasAllowlisted = isFlagSet(oldPolicy, POLICY_ALLOW_METERED_BACKGROUND);
final boolean wasDenylisted = oldPolicy == POLICY_REJECT_METERED_BACKGROUND; final boolean wasDenylisted = isFlagSet(oldPolicy, POLICY_REJECT_METERED_BACKGROUND);
final boolean isAllowlisted = newPolicy == POLICY_ALLOW_METERED_BACKGROUND; final boolean isAllowlisted = isFlagSet(newPolicy, POLICY_ALLOW_METERED_BACKGROUND);
final boolean isDenylisted = newPolicy == POLICY_REJECT_METERED_BACKGROUND; final boolean isDenylisted = isFlagSet(newPolicy, POLICY_REJECT_METERED_BACKGROUND);
if (wasAllowlisted != isAllowlisted) { if (wasAllowlisted != isAllowlisted) {
handleAllowlistChanged(uid, isAllowlisted); handleAllowlistChanged(uid, isAllowlisted);