2 * Copyright (C) 2016 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5 * except in compliance with the License. You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11 * KIND, either express or implied. See the License for the specific language governing
12 * permissions and limitations under the License.
15 package com.android.settings.datausage;
17 import android.app.Application;
18 import android.content.Context;
19 import android.os.Bundle;
20 import android.support.v14.preference.SwitchPreference;
21 import android.support.v7.preference.Preference;
22 import android.support.v7.preference.PreferenceViewHolder;
23 import android.view.Menu;
24 import android.view.MenuInflater;
25 import android.view.MenuItem;
26 import android.view.View;
28 import com.android.internal.logging.MetricsProto.MetricsEvent;
29 import com.android.settings.AppHeader;
30 import com.android.settings.R;
31 import com.android.settings.SettingsActivity;
32 import com.android.settings.SettingsPreferenceFragment;
33 import com.android.settings.applications.AppInfoBase;
34 import com.android.settings.applications.AppStateBaseBridge;
35 import com.android.settings.applications.InstalledAppDetails;
36 import com.android.settings.datausage.AppStateDataUsageBridge.DataUsageState;
37 import com.android.settingslib.applications.ApplicationsState;
38 import com.android.settingslib.applications.ApplicationsState.AppEntry;
39 import com.android.settingslib.applications.ApplicationsState.AppFilter;
41 import java.util.ArrayList;
43 public class UnrestrictedDataAccess extends SettingsPreferenceFragment
44 implements ApplicationsState.Callbacks, AppStateBaseBridge.Callback,
45 Preference.OnPreferenceChangeListener {
47 private static final int MENU_SHOW_SYSTEM = Menu.FIRST + 42;
48 private static final String EXTRA_SHOW_SYSTEM = "show_system";
50 private ApplicationsState mApplicationsState;
51 private AppStateDataUsageBridge mDataUsageBridge;
52 private ApplicationsState.Session mSession;
53 private DataSaverBackend mDataSaverBackend;
54 private boolean mShowSystem;
55 private boolean mExtraLoaded;
56 private AppFilter mFilter;
59 public void onCreate(Bundle icicle) {
60 super.onCreate(icicle);
61 setAnimationAllowed(true);
62 setPreferenceScreen(getPreferenceManager().createPreferenceScreen(getContext()));
63 mApplicationsState = ApplicationsState.getInstance(
64 (Application) getContext().getApplicationContext());
65 mDataSaverBackend = new DataSaverBackend(getContext());
66 mDataUsageBridge = new AppStateDataUsageBridge(mApplicationsState, this, mDataSaverBackend);
67 mSession = mApplicationsState.newSession(this);
68 mShowSystem = icicle != null && icicle.getBoolean(EXTRA_SHOW_SYSTEM);
69 mFilter = mShowSystem ? ApplicationsState.FILTER_ALL_ENABLED
70 : ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER;
71 setHasOptionsMenu(true);
75 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
76 menu.add(Menu.NONE, MENU_SHOW_SYSTEM, Menu.NONE,
77 mShowSystem ? R.string.menu_hide_system : R.string.menu_show_system);
78 super.onCreateOptionsMenu(menu, inflater);
82 public boolean onOptionsItemSelected(MenuItem item) {
83 switch (item.getItemId()) {
84 case MENU_SHOW_SYSTEM:
85 mShowSystem = !mShowSystem;
86 item.setTitle(mShowSystem ? R.string.menu_hide_system : R.string.menu_show_system);
87 mFilter = mShowSystem ? ApplicationsState.FILTER_ALL_ENABLED
88 : ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER;
94 return super.onOptionsItemSelected(item);
98 public void onSaveInstanceState(Bundle outState) {
99 super.onSaveInstanceState(outState);
100 outState.putBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
104 public void onViewCreated(View view, Bundle savedInstanceState) {
105 super.onViewCreated(view, savedInstanceState);
106 setLoading(true, false);
110 public void onResume() {
113 mDataUsageBridge.resume();
117 public void onPause() {
119 mDataUsageBridge.pause();
124 public void onDestroy() {
127 mDataUsageBridge.release();
131 public void onExtraInfoUpdated() {
137 protected int getHelpResource() {
138 return R.string.help_url_unrestricted_data_access;
141 private void rebuild() {
142 ArrayList<AppEntry> apps = mSession.rebuild(mFilter, ApplicationsState.ALPHA_COMPARATOR);
144 onRebuildComplete(apps);
149 public void onRunningStateChanged(boolean running) {
154 public void onPackageListChanged() {
159 public void onRebuildComplete(ArrayList<AppEntry> apps) {
160 if (getContext() == null) return;
161 cacheRemoveAllPrefs(getPreferenceScreen());
162 final int N = apps.size();
163 for (int i = 0; i < N; i++) {
164 AppEntry entry = apps.get(i);
165 String key = entry.info.packageName + "|" + entry.info.uid;
166 AccessPreference preference = (AccessPreference) getCachedPreference(key);
167 if (preference == null) {
168 preference = new AccessPreference(getPrefContext(), entry);
169 preference.setKey(key);
170 preference.setOnPreferenceChangeListener(this);
171 getPreferenceScreen().addPreference(preference);
175 preference.setOrder(i);
177 setLoading(false, true);
178 removeCachedPrefs(getPreferenceScreen());
182 public void onPackageIconChanged() {
187 public void onPackageSizeChanged(String packageName) {
192 public void onAllSizesComputed() {
197 public void onLauncherInfoChanged() {
202 public void onLoadEntriesCompleted() {
207 protected int getMetricsCategory() {
208 return MetricsEvent.DATA_USAGE_UNRESTRICTED_ACCESS;
212 public boolean onPreferenceChange(Preference preference, Object newValue) {
213 if (preference instanceof AccessPreference) {
214 AccessPreference accessPreference = (AccessPreference) preference;
215 boolean whitelisted = newValue == Boolean.TRUE;
216 mDataSaverBackend.setIsWhitelisted(accessPreference.mEntry.info.uid,
217 accessPreference.mEntry.info.packageName, whitelisted);
218 accessPreference.mState.isDataSaverWhitelisted = whitelisted;
224 private class AccessPreference extends SwitchPreference implements DataSaverBackend.Listener {
225 private final AppEntry mEntry;
226 private final DataUsageState mState;
228 public AccessPreference(final Context context, AppEntry entry) {
231 mState = (DataUsageState) mEntry.extraInfo;
232 mEntry.ensureLabel(getContext());
234 if (mEntry.icon != null) {
235 setIcon(mEntry.icon);
240 public void onAttached() {
242 mDataSaverBackend.addListener(this);
246 public void onDetached() {
247 mDataSaverBackend.remListener(this);
252 protected void onClick() {
253 if (mState != null && mState.isDataSaverBlacklisted) {
254 // app is blacklisted, launch App Data Usage screen
255 InstalledAppDetails.startAppInfoFragment(AppDataUsage.class,
256 getContext().getString(R.string.app_data_usage),
257 UnrestrictedDataAccess.this,
260 // app is not blacklisted, let superclass handle toggle switch
265 // Sets UI state based on whitelist/blacklist status.
266 private void setState() {
267 setTitle(mEntry.label);
268 if (mState != null) {
269 setChecked(mState.isDataSaverWhitelisted);
270 if (mState.isDataSaverBlacklisted) {
271 setSummary(R.string.restrict_background_blacklisted);
278 public void reuse() {
284 public void onBindViewHolder(PreferenceViewHolder holder) {
285 if (mEntry.icon == null) {
286 holder.itemView.post(new Runnable() {
289 // Ensure we have an icon before binding.
290 mApplicationsState.ensureIcon(mEntry);
291 // This might trigger us to bind again, but it gives an easy way to only
292 // load the icon once its needed, so its probably worth it.
293 setIcon(mEntry.icon);
297 holder.findViewById(android.R.id.widget_frame)
298 .setVisibility(mState != null && mState.isDataSaverBlacklisted
299 ? View.INVISIBLE : View.VISIBLE);
300 super.onBindViewHolder(holder);
304 public void onDataSaverChanged(boolean isDataSaving) {
308 public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) {
309 if (mState != null && mEntry.info.uid == uid) {
310 mState.isDataSaverWhitelisted = isWhitelisted;
316 public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) {
317 if (mState != null && mEntry.info.uid == uid) {
318 mState.isDataSaverBlacklisted = isBlacklisted;