Home | History | Annotate | Download | only in datausage
      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 static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
     18 import static android.net.NetworkPolicyManager.POLICY_NONE;
     19 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
     20 
     21 import android.content.Context;
     22 import android.net.INetworkPolicyListener;
     23 import android.net.NetworkPolicyManager;
     24 import android.os.RemoteException;
     25 import android.util.SparseIntArray;
     26 
     27 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
     28 import com.android.settings.overlay.FeatureFactory;
     29 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
     30 import com.android.settingslib.utils.ThreadUtils;
     31 
     32 import java.util.ArrayList;
     33 
     34 public class DataSaverBackend {
     35 
     36     private static final String TAG = "DataSaverBackend";
     37 
     38     private final Context mContext;
     39     private final MetricsFeatureProvider mMetricsFeatureProvider;
     40 
     41     private final NetworkPolicyManager mPolicyManager;
     42     private final ArrayList<Listener> mListeners = new ArrayList<>();
     43     private SparseIntArray mUidPolicies = new SparseIntArray();
     44     private boolean mWhitelistInitialized;
     45     private boolean mBlacklistInitialized;
     46 
     47     // TODO: Staticize into only one.
     48     public DataSaverBackend(Context context) {
     49         mContext = context;
     50         mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
     51         mPolicyManager = NetworkPolicyManager.from(context);
     52     }
     53 
     54     public void addListener(Listener listener) {
     55         mListeners.add(listener);
     56         if (mListeners.size() == 1) {
     57             mPolicyManager.registerListener(mPolicyListener);
     58         }
     59         listener.onDataSaverChanged(isDataSaverEnabled());
     60     }
     61 
     62     public void remListener(Listener listener) {
     63         mListeners.remove(listener);
     64         if (mListeners.size() == 0) {
     65             mPolicyManager.unregisterListener(mPolicyListener);
     66         }
     67     }
     68 
     69     public boolean isDataSaverEnabled() {
     70         return mPolicyManager.getRestrictBackground();
     71     }
     72 
     73     public void setDataSaverEnabled(boolean enabled) {
     74         mPolicyManager.setRestrictBackground(enabled);
     75         mMetricsFeatureProvider.action(
     76                 mContext, MetricsEvent.ACTION_DATA_SAVER_MODE, enabled ? 1 : 0);
     77     }
     78 
     79     public void refreshWhitelist() {
     80         loadWhitelist();
     81     }
     82 
     83     public void setIsWhitelisted(int uid, String packageName, boolean whitelisted) {
     84         final int policy = whitelisted ? POLICY_ALLOW_METERED_BACKGROUND : POLICY_NONE;
     85         mPolicyManager.setUidPolicy(uid, policy);
     86         mUidPolicies.put(uid, policy);
     87         if (whitelisted) {
     88             mMetricsFeatureProvider.action(
     89                     mContext, MetricsEvent.ACTION_DATA_SAVER_WHITELIST, packageName);
     90         }
     91     }
     92 
     93     public boolean isWhitelisted(int uid) {
     94         loadWhitelist();
     95         return mUidPolicies.get(uid, POLICY_NONE) == POLICY_ALLOW_METERED_BACKGROUND;
     96     }
     97 
     98     public int getWhitelistedCount() {
     99         int count = 0;
    100         loadWhitelist();
    101         for (int i = 0; i < mUidPolicies.size(); i++) {
    102             if (mUidPolicies.valueAt(i) == POLICY_ALLOW_METERED_BACKGROUND) {
    103                 count++;
    104             }
    105         }
    106         return count;
    107     }
    108 
    109     private void loadWhitelist() {
    110         if (mWhitelistInitialized) return;
    111 
    112         for (int uid : mPolicyManager.getUidsWithPolicy(POLICY_ALLOW_METERED_BACKGROUND)) {
    113             mUidPolicies.put(uid, POLICY_ALLOW_METERED_BACKGROUND);
    114         }
    115         mWhitelistInitialized = true;
    116     }
    117 
    118     public void refreshBlacklist() {
    119         loadBlacklist();
    120     }
    121 
    122     public void setIsBlacklisted(int uid, String packageName, boolean blacklisted) {
    123         final int policy = blacklisted ? POLICY_REJECT_METERED_BACKGROUND : POLICY_NONE;
    124         mPolicyManager.setUidPolicy(uid, policy);
    125         mUidPolicies.put(uid, policy);
    126         if (blacklisted) {
    127             mMetricsFeatureProvider.action(
    128                     mContext, MetricsEvent.ACTION_DATA_SAVER_BLACKLIST, packageName);
    129         }
    130     }
    131 
    132     public boolean isBlacklisted(int uid) {
    133         loadBlacklist();
    134         return mUidPolicies.get(uid, POLICY_NONE) == POLICY_REJECT_METERED_BACKGROUND;
    135     }
    136 
    137     private void loadBlacklist() {
    138         if (mBlacklistInitialized) return;
    139         for (int uid : mPolicyManager.getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) {
    140             mUidPolicies.put(uid, POLICY_REJECT_METERED_BACKGROUND);
    141         }
    142         mBlacklistInitialized = true;
    143     }
    144 
    145     private void handleRestrictBackgroundChanged(boolean isDataSaving) {
    146         for (int i = 0; i < mListeners.size(); i++) {
    147             mListeners.get(i).onDataSaverChanged(isDataSaving);
    148         }
    149     }
    150 
    151     private void handleWhitelistChanged(int uid, boolean isWhitelisted) {
    152         for (int i = 0; i < mListeners.size(); i++) {
    153             mListeners.get(i).onWhitelistStatusChanged(uid, isWhitelisted);
    154         }
    155     }
    156 
    157     private void handleBlacklistChanged(int uid, boolean isBlacklisted) {
    158         for (int i = 0; i < mListeners.size(); i++) {
    159             mListeners.get(i).onBlacklistStatusChanged(uid, isBlacklisted);
    160         }
    161     }
    162 
    163     private void handleUidPoliciesChanged(int uid, int newPolicy) {
    164         loadWhitelist();
    165         loadBlacklist();
    166 
    167         final int oldPolicy = mUidPolicies.get(uid, POLICY_NONE);
    168         if (newPolicy == POLICY_NONE) {
    169             mUidPolicies.delete(uid);
    170         } else {
    171             mUidPolicies.put(uid, newPolicy);
    172         }
    173 
    174         final boolean wasWhitelisted = oldPolicy == POLICY_ALLOW_METERED_BACKGROUND;
    175         final boolean wasBlacklisted = oldPolicy == POLICY_REJECT_METERED_BACKGROUND;
    176         final boolean isWhitelisted = newPolicy == POLICY_ALLOW_METERED_BACKGROUND;
    177         final boolean isBlacklisted = newPolicy == POLICY_REJECT_METERED_BACKGROUND;
    178 
    179         if (wasWhitelisted != isWhitelisted) {
    180             handleWhitelistChanged(uid, isWhitelisted);
    181         }
    182 
    183         if (wasBlacklisted != isBlacklisted) {
    184             handleBlacklistChanged(uid, isBlacklisted);
    185         }
    186 
    187     }
    188 
    189     private final INetworkPolicyListener mPolicyListener = new INetworkPolicyListener.Stub() {
    190         @Override
    191         public void onUidRulesChanged(int uid, int uidRules) throws RemoteException {
    192         }
    193 
    194         @Override
    195         public void onUidPoliciesChanged(final int uid, final int uidPolicies) {
    196             ThreadUtils.postOnMainThread(() -> handleUidPoliciesChanged(uid, uidPolicies));
    197         }
    198 
    199         @Override
    200         public void onMeteredIfacesChanged(String[] strings) throws RemoteException {
    201         }
    202 
    203         @Override
    204         public void onRestrictBackgroundChanged(final boolean isDataSaving) throws RemoteException {
    205             ThreadUtils.postOnMainThread(() -> handleRestrictBackgroundChanged(isDataSaving));
    206         }
    207 
    208         @Override
    209         public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) {
    210         }
    211     };
    212 
    213     public interface Listener {
    214         void onDataSaverChanged(boolean isDataSaving);
    215         void onWhitelistStatusChanged(int uid, boolean isWhitelisted);
    216         void onBlacklistStatusChanged(int uid, boolean isBlacklisted);
    217     }
    218 }
    219