1 /* 2 * Copyright (C) 2016 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.settings.datausage; 16 17 import android.content.Context; 18 import android.net.INetworkPolicyListener; 19 import android.net.INetworkPolicyManager; 20 import android.net.NetworkPolicyManager; 21 import android.os.Handler; 22 import android.os.RemoteException; 23 import android.os.ServiceManager; 24 import android.util.Log; 25 import android.util.SparseBooleanArray; 26 27 import com.android.internal.logging.MetricsLogger; 28 import com.android.internal.logging.MetricsProto.MetricsEvent; 29 30 import java.util.ArrayList; 31 32 import static android.net.NetworkPolicyManager.POLICY_NONE; 33 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; 34 35 public class DataSaverBackend { 36 37 private static final String TAG = "DataSaverBackend"; 38 39 private final Context mContext; 40 41 private final Handler mHandler = new Handler(); 42 private final NetworkPolicyManager mPolicyManager; 43 private final INetworkPolicyManager mIPolicyManager; 44 private final ArrayList<Listener> mListeners = new ArrayList<>(); 45 private SparseBooleanArray mWhitelist; 46 private SparseBooleanArray mBlacklist; 47 48 // TODO: Staticize into only one. DataSaverBackend(Context context)49 public DataSaverBackend(Context context) { 50 mContext = context; 51 mIPolicyManager = INetworkPolicyManager.Stub.asInterface( 52 ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); 53 mPolicyManager = NetworkPolicyManager.from(context); 54 } 55 addListener(Listener listener)56 public void addListener(Listener listener) { 57 mListeners.add(listener); 58 if (mListeners.size() == 1) { 59 mPolicyManager.registerListener(mPolicyListener); 60 } 61 listener.onDataSaverChanged(isDataSaverEnabled()); 62 } 63 remListener(Listener listener)64 public void remListener(Listener listener) { 65 mListeners.remove(listener); 66 if (mListeners.size() == 0) { 67 mPolicyManager.unregisterListener(mPolicyListener); 68 } 69 } 70 isDataSaverEnabled()71 public boolean isDataSaverEnabled() { 72 return mPolicyManager.getRestrictBackground(); 73 } 74 setDataSaverEnabled(boolean enabled)75 public void setDataSaverEnabled(boolean enabled) { 76 mPolicyManager.setRestrictBackground(enabled); 77 MetricsLogger.action(mContext, MetricsEvent.ACTION_DATA_SAVER_MODE, enabled ? 1 : 0); 78 } 79 refreshWhitelist()80 public void refreshWhitelist() { 81 loadWhitelist(); 82 } 83 setIsWhitelisted(int uid, String packageName, boolean whitelisted)84 public void setIsWhitelisted(int uid, String packageName, boolean whitelisted) { 85 mWhitelist.put(uid, whitelisted); 86 try { 87 if (whitelisted) { 88 mIPolicyManager.addRestrictBackgroundWhitelistedUid(uid); 89 } else { 90 mIPolicyManager.removeRestrictBackgroundWhitelistedUid(uid); 91 } 92 } catch (RemoteException e) { 93 Log.w(TAG, "Can't reach policy manager", e); 94 } 95 if (whitelisted) { 96 MetricsLogger.action(mContext, MetricsEvent.ACTION_DATA_SAVER_WHITELIST, packageName); 97 } 98 } 99 isWhitelisted(int uid)100 public boolean isWhitelisted(int uid) { 101 if (mWhitelist == null) { 102 loadWhitelist(); 103 } 104 return mWhitelist.get(uid); 105 } 106 getWhitelistedCount()107 public int getWhitelistedCount() { 108 int count = 0; 109 if (mWhitelist == null) { 110 loadWhitelist(); 111 } 112 for (int i = 0; i < mWhitelist.size(); i++) { 113 if (mWhitelist.valueAt(i)) { 114 count++; 115 } 116 } 117 return count; 118 } 119 loadWhitelist()120 private void loadWhitelist() { 121 mWhitelist = new SparseBooleanArray(); 122 try { 123 for (int uid : mIPolicyManager.getRestrictBackgroundWhitelistedUids()) { 124 mWhitelist.put(uid, true); 125 } 126 } catch (RemoteException e) { 127 } 128 } 129 refreshBlacklist()130 public void refreshBlacklist() { 131 loadBlacklist(); 132 } 133 setIsBlacklisted(int uid, String packageName, boolean blacklisted)134 public void setIsBlacklisted(int uid, String packageName, boolean blacklisted) { 135 mPolicyManager.setUidPolicy( 136 uid, blacklisted ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE); 137 if (blacklisted) { 138 MetricsLogger.action(mContext, MetricsEvent.ACTION_DATA_SAVER_BLACKLIST, packageName); 139 } 140 } 141 isBlacklisted(int uid)142 public boolean isBlacklisted(int uid) { 143 if (mBlacklist == null) { 144 loadBlacklist(); 145 } 146 return mBlacklist.get(uid); 147 } 148 loadBlacklist()149 private void loadBlacklist() { 150 mBlacklist = new SparseBooleanArray(); 151 try { 152 for (int uid : mIPolicyManager.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) { 153 mBlacklist.put(uid, true); 154 } 155 } catch (RemoteException e) { 156 } 157 } 158 handleRestrictBackgroundChanged(boolean isDataSaving)159 private void handleRestrictBackgroundChanged(boolean isDataSaving) { 160 for (int i = 0; i < mListeners.size(); i++) { 161 mListeners.get(i).onDataSaverChanged(isDataSaving); 162 } 163 } 164 handleWhitelistChanged(int uid, boolean isWhitelisted)165 private void handleWhitelistChanged(int uid, boolean isWhitelisted) { 166 for (int i = 0; i < mListeners.size(); i++) { 167 mListeners.get(i).onWhitelistStatusChanged(uid, isWhitelisted); 168 } 169 } 170 handleBlacklistChanged(int uid, boolean isBlacklisted)171 private void handleBlacklistChanged(int uid, boolean isBlacklisted) { 172 for (int i = 0; i < mListeners.size(); i++) { 173 mListeners.get(i).onBlacklistStatusChanged(uid, isBlacklisted); 174 } 175 } 176 177 private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() { 178 @Override 179 public void onUidRulesChanged(final int uid, int uidRules) throws RemoteException { 180 } 181 182 @Override 183 public void onRestrictBackgroundBlacklistChanged(int uid, boolean blacklisted) { 184 if (mBlacklist == null) { 185 loadBlacklist(); 186 } 187 mBlacklist.put(uid, blacklisted); 188 mHandler.post(new Runnable() { 189 @Override 190 public void run() { 191 handleBlacklistChanged(uid, blacklisted); 192 } 193 }); 194 } 195 196 @Override 197 public void onRestrictBackgroundWhitelistChanged(final int uid, final boolean whitelisted) { 198 if (mWhitelist == null) { 199 loadWhitelist(); 200 } 201 mWhitelist.put(uid, whitelisted); 202 mHandler.post(new Runnable() { 203 @Override 204 public void run() { 205 handleWhitelistChanged(uid, whitelisted); 206 } 207 }); 208 } 209 210 @Override 211 public void onMeteredIfacesChanged(String[] strings) throws RemoteException { 212 } 213 214 @Override 215 public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException { 216 mHandler.post(new Runnable() { 217 @Override 218 public void run() { 219 handleRestrictBackgroundChanged(isDataSaving); 220 } 221 }); 222 } 223 }; 224 225 public interface Listener { onDataSaverChanged(boolean isDataSaving)226 void onDataSaverChanged(boolean isDataSaving); onWhitelistStatusChanged(int uid, boolean isWhitelisted)227 void onWhitelistStatusChanged(int uid, boolean isWhitelisted); onBlacklistStatusChanged(int uid, boolean isBlacklisted)228 void onBlacklistStatusChanged(int uid, boolean isBlacklisted); 229 } 230 } 231