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 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.
     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 
     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 
     64     public void remListener(Listener listener) {
     65         mListeners.remove(listener);
     66         if (mListeners.size() == 0) {
     67             mPolicyManager.unregisterListener(mPolicyListener);
     68         }
     69     }
     70 
     71     public boolean isDataSaverEnabled() {
     72         return mPolicyManager.getRestrictBackground();
     73     }
     74 
     75     public void setDataSaverEnabled(boolean enabled) {
     76         mPolicyManager.setRestrictBackground(enabled);
     77         MetricsLogger.action(mContext, MetricsEvent.ACTION_DATA_SAVER_MODE, enabled ? 1 : 0);
     78     }
     79 
     80     public void refreshWhitelist() {
     81         loadWhitelist();
     82     }
     83 
     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 
    100     public boolean isWhitelisted(int uid) {
    101         if (mWhitelist == null) {
    102             loadWhitelist();
    103         }
    104         return mWhitelist.get(uid);
    105     }
    106 
    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 
    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 
    130     public void refreshBlacklist() {
    131         loadBlacklist();
    132     }
    133 
    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 
    142     public boolean isBlacklisted(int uid) {
    143         if (mBlacklist == null) {
    144             loadBlacklist();
    145         }
    146         return mBlacklist.get(uid);
    147     }
    148 
    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 
    159     private void handleRestrictBackgroundChanged(boolean isDataSaving) {
    160         for (int i = 0; i < mListeners.size(); i++) {
    161             mListeners.get(i).onDataSaverChanged(isDataSaving);
    162         }
    163     }
    164 
    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 
    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 {
    226         void onDataSaverChanged(boolean isDataSaving);
    227         void onWhitelistStatusChanged(int uid, boolean isWhitelisted);
    228         void onBlacklistStatusChanged(int uid, boolean isBlacklisted);
    229     }
    230 }
    231