1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 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 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 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. 13 */ 14 15 package com.android.car.developeroptions.datausage; 16 17 import android.app.Application; 18 import android.app.settings.SettingsEnums; 19 import android.content.Context; 20 import android.os.Bundle; 21 import android.provider.SearchIndexableResource; 22 import android.telephony.SubscriptionManager; 23 import android.widget.Switch; 24 25 import androidx.preference.Preference; 26 27 import com.android.car.developeroptions.R; 28 import com.android.car.developeroptions.SettingsActivity; 29 import com.android.car.developeroptions.SettingsPreferenceFragment; 30 import com.android.car.developeroptions.applications.AppStateBaseBridge.Callback; 31 import com.android.car.developeroptions.datausage.DataSaverBackend.Listener; 32 import com.android.car.developeroptions.search.BaseSearchIndexProvider; 33 import com.android.car.developeroptions.widget.SwitchBar; 34 import com.android.car.developeroptions.widget.SwitchBar.OnSwitchChangeListener; 35 import com.android.settingslib.applications.ApplicationsState; 36 import com.android.settingslib.applications.ApplicationsState.AppEntry; 37 import com.android.settingslib.applications.ApplicationsState.Callbacks; 38 import com.android.settingslib.applications.ApplicationsState.Session; 39 import com.android.settingslib.search.Indexable; 40 import com.android.settingslib.search.SearchIndexable; 41 42 import java.util.ArrayList; 43 import java.util.List; 44 45 @SearchIndexable 46 public class DataSaverSummary extends SettingsPreferenceFragment 47 implements OnSwitchChangeListener, Listener, Callback, Callbacks { 48 49 private static final String KEY_UNRESTRICTED_ACCESS = "unrestricted_access"; 50 51 private SwitchBar mSwitchBar; 52 private DataSaverBackend mDataSaverBackend; 53 private Preference mUnrestrictedAccess; 54 private ApplicationsState mApplicationsState; 55 private AppStateDataUsageBridge mDataUsageBridge; 56 private Session mSession; 57 58 // Flag used to avoid infinite loop due if user switch it on/off too quicky. 59 private boolean mSwitching; 60 61 @Override onCreate(Bundle icicle)62 public void onCreate(Bundle icicle) { 63 super.onCreate(icicle); 64 65 addPreferencesFromResource(R.xml.data_saver); 66 mUnrestrictedAccess = findPreference(KEY_UNRESTRICTED_ACCESS); 67 mApplicationsState = ApplicationsState.getInstance( 68 (Application) getContext().getApplicationContext()); 69 mDataSaverBackend = new DataSaverBackend(getContext()); 70 mDataUsageBridge = new AppStateDataUsageBridge(mApplicationsState, this, mDataSaverBackend); 71 mSession = mApplicationsState.newSession(this, getSettingsLifecycle()); 72 } 73 74 @Override onActivityCreated(Bundle savedInstanceState)75 public void onActivityCreated(Bundle savedInstanceState) { 76 super.onActivityCreated(savedInstanceState); 77 mSwitchBar = ((SettingsActivity) getActivity()).getSwitchBar(); 78 mSwitchBar.setSwitchBarText( 79 R.string.data_saver_switch_title, 80 R.string.data_saver_switch_title); 81 mSwitchBar.show(); 82 mSwitchBar.addOnSwitchChangeListener(this); 83 } 84 85 @Override onResume()86 public void onResume() { 87 super.onResume(); 88 mDataSaverBackend.refreshWhitelist(); 89 mDataSaverBackend.refreshBlacklist(); 90 mDataSaverBackend.addListener(this); 91 mDataUsageBridge.resume(); 92 } 93 94 @Override onPause()95 public void onPause() { 96 super.onPause(); 97 mDataSaverBackend.remListener(this); 98 mDataUsageBridge.pause(); 99 } 100 101 @Override onSwitchChanged(Switch switchView, boolean isChecked)102 public void onSwitchChanged(Switch switchView, boolean isChecked) { 103 synchronized (this) { 104 if (mSwitching) { 105 return; 106 } 107 mSwitching = true; 108 mDataSaverBackend.setDataSaverEnabled(isChecked); 109 } 110 } 111 112 @Override getMetricsCategory()113 public int getMetricsCategory() { 114 return SettingsEnums.DATA_SAVER_SUMMARY; 115 } 116 117 @Override getHelpResource()118 public int getHelpResource() { 119 return R.string.help_url_data_saver; 120 } 121 122 @Override onDataSaverChanged(boolean isDataSaving)123 public void onDataSaverChanged(boolean isDataSaving) { 124 synchronized (this) { 125 mSwitchBar.setChecked(isDataSaving); 126 mSwitching = false; 127 } 128 } 129 130 @Override onWhitelistStatusChanged(int uid, boolean isWhitelisted)131 public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) { 132 } 133 134 @Override onBlacklistStatusChanged(int uid, boolean isBlacklisted)135 public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) { 136 } 137 138 @Override onExtraInfoUpdated()139 public void onExtraInfoUpdated() { 140 if (!isAdded()) { 141 return; 142 } 143 int count = 0; 144 final ArrayList<AppEntry> allApps = mSession.getAllApps(); 145 final int N = allApps.size(); 146 for (int i = 0; i < N; i++) { 147 final AppEntry entry = allApps.get(i); 148 if (!ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER.filterApp(entry)) { 149 continue; 150 } 151 if (entry.extraInfo != null && ((AppStateDataUsageBridge.DataUsageState) 152 entry.extraInfo).isDataSaverWhitelisted) { 153 count++; 154 } 155 } 156 mUnrestrictedAccess.setSummary(getResources().getQuantityString( 157 R.plurals.data_saver_unrestricted_summary, count, count)); 158 } 159 160 @Override onRunningStateChanged(boolean running)161 public void onRunningStateChanged(boolean running) { 162 163 } 164 165 @Override onPackageListChanged()166 public void onPackageListChanged() { 167 168 } 169 170 @Override onRebuildComplete(ArrayList<AppEntry> apps)171 public void onRebuildComplete(ArrayList<AppEntry> apps) { 172 173 } 174 175 @Override onPackageIconChanged()176 public void onPackageIconChanged() { 177 178 } 179 180 @Override onPackageSizeChanged(String packageName)181 public void onPackageSizeChanged(String packageName) { 182 183 } 184 185 @Override onAllSizesComputed()186 public void onAllSizesComputed() { 187 188 } 189 190 @Override onLauncherInfoChanged()191 public void onLauncherInfoChanged() { 192 193 } 194 195 @Override onLoadEntriesCompleted()196 public void onLoadEntriesCompleted() { 197 198 } 199 200 public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 201 new BaseSearchIndexProvider() { 202 @Override 203 public List<SearchIndexableResource> getXmlResourcesToIndex(Context context, 204 boolean enabled) { 205 final ArrayList<SearchIndexableResource> result = new ArrayList<>(); 206 207 final SearchIndexableResource sir = new SearchIndexableResource(context); 208 sir.xmlResId = R.xml.data_saver; 209 result.add(sir); 210 return result; 211 } 212 213 @Override 214 protected boolean isPageSearchEnabled(Context context) { 215 return DataUsageUtils.hasMobileData(context) 216 && DataUsageUtils.getDefaultSubscriptionId(context) 217 != SubscriptionManager.INVALID_SUBSCRIPTION_ID; 218 } 219 }; 220 } 221