Handle blacklisted apps on Data Saver whitelist.
am: c2ef27f
* commit 'c2ef27faf4afca6c4f6634b5de975a1bdadf0752':
Handle blacklisted apps on Data Saver whitelist.
Change-Id: Ia5027825b7292f15717a47ed82f242f252ac83d9
This commit is contained in:
@@ -7243,6 +7243,9 @@
|
|||||||
<!-- Button that leads to list of apps with unrestricted data access [CHAR LIMIT=60] -->
|
<!-- Button that leads to list of apps with unrestricted data access [CHAR LIMIT=60] -->
|
||||||
<string name="unrestricted_data_saver">Unrestricted data access</string>
|
<string name="unrestricted_data_saver">Unrestricted data access</string>
|
||||||
|
|
||||||
|
<!-- Description of message shown when app is blacklisted for background data access [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="restrict_background_blacklisted">Background data is turned off</string>
|
||||||
|
|
||||||
<!-- Summary for the Data Saver feature being on [CHAR LIMIT=NONE] -->
|
<!-- Summary for the Data Saver feature being on [CHAR LIMIT=NONE] -->
|
||||||
<string name="data_saver_on">On</string>
|
<string name="data_saver_on">On</string>
|
||||||
|
|
||||||
|
@@ -73,6 +73,7 @@ import android.webkit.IWebViewUpdateService;
|
|||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
||||||
import com.android.internal.os.BatterySipper;
|
import com.android.internal.os.BatterySipper;
|
||||||
import com.android.internal.os.BatteryStatsHelper;
|
import com.android.internal.os.BatteryStatsHelper;
|
||||||
@@ -81,6 +82,7 @@ import com.android.settings.AppHeader;
|
|||||||
import com.android.settings.DeviceAdminAdd;
|
import com.android.settings.DeviceAdminAdd;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.SettingsActivity;
|
import com.android.settings.SettingsActivity;
|
||||||
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
import com.android.settings.Utils;
|
import com.android.settings.Utils;
|
||||||
import com.android.settings.applications.PermissionsSummaryHelper.PermissionsResultCallback;
|
import com.android.settings.applications.PermissionsSummaryHelper.PermissionsResultCallback;
|
||||||
import com.android.settings.datausage.AppDataUsage;
|
import com.android.settings.datausage.AppDataUsage;
|
||||||
@@ -741,14 +743,19 @@ public class InstalledAppDetails extends AppInfoBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void startAppInfoFragment(Class<?> fragment, CharSequence title) {
|
private void startAppInfoFragment(Class<?> fragment, CharSequence title) {
|
||||||
|
startAppInfoFragment(fragment, title, this, mAppEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void startAppInfoFragment(Class<?> fragment, CharSequence title,
|
||||||
|
SettingsPreferenceFragment caller, AppEntry appEntry) {
|
||||||
// start new fragment to display extended information
|
// start new fragment to display extended information
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
args.putString(ARG_PACKAGE_NAME, mAppEntry.info.packageName);
|
args.putString(ARG_PACKAGE_NAME, appEntry.info.packageName);
|
||||||
args.putInt(ARG_PACKAGE_UID, mAppEntry.info.uid);
|
args.putInt(ARG_PACKAGE_UID, appEntry.info.uid);
|
||||||
args.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
|
args.putBoolean(AppHeader.EXTRA_HIDE_INFO_BUTTON, true);
|
||||||
|
|
||||||
SettingsActivity sa = (SettingsActivity) getActivity();
|
SettingsActivity sa = (SettingsActivity) caller.getActivity();
|
||||||
sa.startPreferencePanel(fragment.getName(), args, -1, title, this, SUB_INFO_FRAGMENT);
|
sa.startPreferencePanel(fragment.getName(), args, -1, title, caller, SUB_INFO_FRAGMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -216,7 +216,8 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
if (preference == mRestrictBackground) {
|
if (preference == mRestrictBackground) {
|
||||||
setAppRestrictBackground(!(Boolean) newValue);
|
mDataSaverBackend.setIsBlacklisted(mAppItem.key, mPackageName, !(Boolean) newValue);
|
||||||
|
updatePrefs(); // TODO: should have been notified by NPMS instead
|
||||||
return true;
|
return true;
|
||||||
} else if (preference == mUnrestrictedData) {
|
} else if (preference == mUnrestrictedData) {
|
||||||
mDataSaverBackend.setIsWhitelisted(mAppItem.key, mPackageName, (Boolean) newValue);
|
mDataSaverBackend.setIsWhitelisted(mAppItem.key, mPackageName, (Boolean) newValue);
|
||||||
@@ -287,17 +288,6 @@ public class AppDataUsage extends DataUsageBase implements Preference.OnPreferen
|
|||||||
return (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
|
return (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAppRestrictBackground(boolean restrictBackground) {
|
|
||||||
final int uid = mAppItem.key;
|
|
||||||
services.mPolicyManager.setUidPolicy(
|
|
||||||
uid, restrictBackground ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
|
|
||||||
updatePrefs(); // TODO: should have been notified by NPMS instead
|
|
||||||
if (restrictBackground) {
|
|
||||||
MetricsLogger.action(getContext(),
|
|
||||||
MetricsEvent.ACTION_DATA_SAVER_BLACKLIST, mPackageName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
@@ -37,20 +37,24 @@ public class AppStateDataUsageBridge extends AppStateBaseBridge {
|
|||||||
final int N = apps.size();
|
final int N = apps.size();
|
||||||
for (int i = 0; i < N; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
AppEntry app = apps.get(i);
|
AppEntry app = apps.get(i);
|
||||||
app.extraInfo = new DataUsageState(mDataSaverBackend.isWhitelisted(app.info.uid));
|
app.extraInfo = new DataUsageState(mDataSaverBackend.isWhitelisted(app.info.uid),
|
||||||
|
mDataSaverBackend.isBlacklisted(app.info.uid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
|
protected void updateExtraInfo(AppEntry app, String pkg, int uid) {
|
||||||
app.extraInfo = new DataUsageState(mDataSaverBackend.isWhitelisted(uid));
|
app.extraInfo = new DataUsageState(mDataSaverBackend.isWhitelisted(uid),
|
||||||
|
mDataSaverBackend.isBlacklisted(uid));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DataUsageState {
|
public static class DataUsageState {
|
||||||
public boolean isDataSaverWhitelisted;
|
public boolean isDataSaverWhitelisted;
|
||||||
|
public boolean isDataSaverBlacklisted;
|
||||||
|
|
||||||
public DataUsageState(boolean isDataSaverWhitelisted) {
|
public DataUsageState(boolean isDataSaverWhitelisted, boolean isDataSaverBlacklisted) {
|
||||||
this.isDataSaverWhitelisted = isDataSaverWhitelisted;
|
this.isDataSaverWhitelisted = isDataSaverWhitelisted;
|
||||||
|
this.isDataSaverBlacklisted = isDataSaverBlacklisted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,9 @@ import com.android.internal.logging.MetricsProto.MetricsEvent;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import static android.net.NetworkPolicyManager.POLICY_NONE;
|
||||||
|
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
|
||||||
|
|
||||||
public class DataSaverBackend {
|
public class DataSaverBackend {
|
||||||
|
|
||||||
private static final String TAG = "DataSaverBackend";
|
private static final String TAG = "DataSaverBackend";
|
||||||
@@ -40,6 +43,7 @@ public class DataSaverBackend {
|
|||||||
private final INetworkPolicyManager mIPolicyManager;
|
private final INetworkPolicyManager mIPolicyManager;
|
||||||
private final ArrayList<Listener> mListeners = new ArrayList<>();
|
private final ArrayList<Listener> mListeners = new ArrayList<>();
|
||||||
private SparseBooleanArray mWhitelist;
|
private SparseBooleanArray mWhitelist;
|
||||||
|
private SparseBooleanArray mBlacklist;
|
||||||
|
|
||||||
// TODO: Staticize into only one.
|
// TODO: Staticize into only one.
|
||||||
public DataSaverBackend(Context context) {
|
public DataSaverBackend(Context context) {
|
||||||
@@ -121,6 +125,35 @@ public class DataSaverBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void refreshBlacklist() {
|
||||||
|
loadBlacklist();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsBlacklisted(int uid, String packageName, boolean blacklisted) {
|
||||||
|
mPolicyManager.setUidPolicy(
|
||||||
|
uid, blacklisted ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE);
|
||||||
|
if (blacklisted) {
|
||||||
|
MetricsLogger.action(mContext, MetricsEvent.ACTION_DATA_SAVER_BLACKLIST, packageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBlacklisted(int uid) {
|
||||||
|
if (mBlacklist == null) {
|
||||||
|
loadBlacklist();
|
||||||
|
}
|
||||||
|
return mBlacklist.get(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadBlacklist() {
|
||||||
|
mBlacklist = new SparseBooleanArray();
|
||||||
|
try {
|
||||||
|
for (int uid : mIPolicyManager.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) {
|
||||||
|
mBlacklist.put(uid, true);
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleRestrictBackgroundChanged(boolean isDataSaving) {
|
private void handleRestrictBackgroundChanged(boolean isDataSaving) {
|
||||||
for (int i = 0; i < mListeners.size(); i++) {
|
for (int i = 0; i < mListeners.size(); i++) {
|
||||||
mListeners.get(i).onDataSaverChanged(isDataSaving);
|
mListeners.get(i).onDataSaverChanged(isDataSaving);
|
||||||
@@ -129,7 +162,8 @@ public class DataSaverBackend {
|
|||||||
|
|
||||||
private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
|
private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void onUidRulesChanged(int i, int i1) throws RemoteException {
|
public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
|
||||||
|
// TODO: update UI accordingly
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -70,6 +70,7 @@ public class DataSaverSummary extends SettingsPreferenceFragment
|
|||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
mDataSaverBackend.refreshWhitelist();
|
mDataSaverBackend.refreshWhitelist();
|
||||||
|
mDataSaverBackend.refreshBlacklist();
|
||||||
mDataSaverBackend.addListener(this);
|
mDataSaverBackend.addListener(this);
|
||||||
mSession.resume();
|
mSession.resume();
|
||||||
mDataUsageBridge.resume();
|
mDataUsageBridge.resume();
|
||||||
|
@@ -24,10 +24,15 @@ import android.view.Menu;
|
|||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.MetricsProto.MetricsEvent;
|
||||||
|
import com.android.settings.AppHeader;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.SettingsActivity;
|
||||||
import com.android.settings.SettingsPreferenceFragment;
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
|
import com.android.settings.applications.AppInfoBase;
|
||||||
import com.android.settings.applications.AppStateBaseBridge;
|
import com.android.settings.applications.AppStateBaseBridge;
|
||||||
|
import com.android.settings.applications.InstalledAppDetails;
|
||||||
import com.android.settings.datausage.AppStateDataUsageBridge.DataUsageState;
|
import com.android.settings.datausage.AppStateDataUsageBridge.DataUsageState;
|
||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||||
@@ -40,6 +45,7 @@ public class UnrestrictedDataAccess extends SettingsPreferenceFragment
|
|||||||
|
|
||||||
private static final int MENU_SHOW_SYSTEM = Menu.FIRST + 42;
|
private static final int MENU_SHOW_SYSTEM = Menu.FIRST + 42;
|
||||||
private static final String EXTRA_SHOW_SYSTEM = "show_system";
|
private static final String EXTRA_SHOW_SYSTEM = "show_system";
|
||||||
|
|
||||||
private ApplicationsState mApplicationsState;
|
private ApplicationsState mApplicationsState;
|
||||||
private AppStateDataUsageBridge mDataUsageBridge;
|
private AppStateDataUsageBridge mDataUsageBridge;
|
||||||
private ApplicationsState.Session mSession;
|
private ApplicationsState.Session mSession;
|
||||||
@@ -144,11 +150,11 @@ public class UnrestrictedDataAccess extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> apps) {
|
public void onRebuildComplete(ArrayList<AppEntry> apps) {
|
||||||
cacheRemoveAllPrefs(getPreferenceScreen());
|
cacheRemoveAllPrefs(getPreferenceScreen());
|
||||||
final int N = apps.size();
|
final int N = apps.size();
|
||||||
for (int i = 0; i < N; i++) {
|
for (int i = 0; i < N; i++) {
|
||||||
ApplicationsState.AppEntry entry = apps.get(i);
|
AppEntry entry = apps.get(i);
|
||||||
String key = entry.info.packageName + "|" + entry.info.uid;
|
String key = entry.info.packageName + "|" + entry.info.uid;
|
||||||
AccessPreference preference = (AccessPreference) getCachedPreference(key);
|
AccessPreference preference = (AccessPreference) getCachedPreference(key);
|
||||||
if (preference == null) {
|
if (preference == null) {
|
||||||
@@ -202,32 +208,60 @@ public class UnrestrictedDataAccess extends SettingsPreferenceFragment
|
|||||||
boolean whitelisted = newValue == Boolean.TRUE;
|
boolean whitelisted = newValue == Boolean.TRUE;
|
||||||
mDataSaverBackend.setIsWhitelisted(accessPreference.mEntry.info.uid,
|
mDataSaverBackend.setIsWhitelisted(accessPreference.mEntry.info.uid,
|
||||||
accessPreference.mEntry.info.packageName, whitelisted);
|
accessPreference.mEntry.info.packageName, whitelisted);
|
||||||
((AppStateDataUsageBridge.DataUsageState) accessPreference.mEntry.extraInfo)
|
accessPreference.mState.isDataSaverWhitelisted = whitelisted;
|
||||||
.isDataSaverWhitelisted = whitelisted;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AccessPreference extends SwitchPreference {
|
private class AccessPreference extends SwitchPreference {
|
||||||
private final ApplicationsState.AppEntry mEntry;
|
private final AppEntry mEntry;
|
||||||
|
private final DataUsageState mState;
|
||||||
|
|
||||||
public AccessPreference(Context context, ApplicationsState.AppEntry entry) {
|
public AccessPreference(final Context context, AppEntry entry) {
|
||||||
super(context);
|
super(context);
|
||||||
mEntry = entry;
|
mEntry = entry;
|
||||||
|
mState = (DataUsageState) mEntry.extraInfo;
|
||||||
mEntry.ensureLabel(getContext());
|
mEntry.ensureLabel(getContext());
|
||||||
setTitle(entry.label);
|
setState();
|
||||||
final DataUsageState state = (DataUsageState) entry.extraInfo;
|
|
||||||
setChecked(state != null && state.isDataSaverWhitelisted);
|
|
||||||
if (mEntry.icon != null) {
|
if (mEntry.icon != null) {
|
||||||
setIcon(mEntry.icon);
|
setIcon(mEntry.icon);
|
||||||
}
|
}
|
||||||
|
setOnPreferenceClickListener( new OnPreferenceClickListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference pref) {
|
||||||
|
if (mState.isDataSaverBlacklisted) {
|
||||||
|
InstalledAppDetails.startAppInfoFragment(AppDataUsage.class,
|
||||||
|
context.getString(R.string.app_data_usage),
|
||||||
|
UnrestrictedDataAccess.this,
|
||||||
|
mEntry);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets UI state based on whitelist/blacklist status.
|
||||||
|
private void setState() {
|
||||||
|
setTitle(mEntry.label);
|
||||||
|
// TODO: state is cached, so if blacklist/whitelist changes, it's not updated.
|
||||||
|
// For example, if the initial state is blacklisted, the user taps the preference,
|
||||||
|
// removes the blacklist, and then taps back, the state is not refreshed.
|
||||||
|
// The proper fix for this problem is to implement onUidRulesChanged() on
|
||||||
|
// DataSaverBackend and update the UI accordingly.
|
||||||
|
if (mState != null) {
|
||||||
|
setChecked(mState.isDataSaverWhitelisted);
|
||||||
|
if (mState.isDataSaverBlacklisted) {
|
||||||
|
setSummary(R.string.restrict_background_blacklisted);
|
||||||
|
}
|
||||||
|
// TODO: might need to reset summary once it listens to onUidRulesChanged()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reuse() {
|
public void reuse() {
|
||||||
setTitle(mEntry.label);
|
setState();
|
||||||
final DataUsageState state = (DataUsageState) mEntry.extraInfo;
|
notifyChanged();
|
||||||
setChecked(state != null && state.isDataSaverWhitelisted);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -244,7 +278,10 @@ public class UnrestrictedDataAccess extends SettingsPreferenceFragment
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
holder.findViewById(android.R.id.widget_frame)
|
||||||
|
.setVisibility(mState.isDataSaverBlacklisted ? View.INVISIBLE : View.VISIBLE);
|
||||||
super.onBindViewHolder(holder);
|
super.onBindViewHolder(holder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user