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:
Felipe Leme
2016-04-18 22:38:26 +00:00
committed by android-build-merger
7 changed files with 108 additions and 32 deletions

View File

@@ -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>

View File

@@ -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);
} }
/* /*

View File

@@ -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);

View File

@@ -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;
} }
} }
} }

View File

@@ -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

View File

@@ -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();

View File

@@ -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);
} }
} }
} }