Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.net;
     18 
     19 import static android.Manifest.permission.ACCESS_NETWORK_STATE;
     20 import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
     21 import static android.Manifest.permission.DUMP;
     22 import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
     23 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
     24 import static android.Manifest.permission.READ_PHONE_STATE;
     25 import static android.content.Intent.ACTION_PACKAGE_ADDED;
     26 import static android.content.Intent.ACTION_UID_REMOVED;
     27 import static android.content.Intent.EXTRA_UID;
     28 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
     29 import static android.net.ConnectivityManager.TYPE_ETHERNET;
     30 import static android.net.ConnectivityManager.TYPE_MOBILE;
     31 import static android.net.ConnectivityManager.TYPE_WIFI;
     32 import static android.net.ConnectivityManager.TYPE_WIMAX;
     33 import static android.net.NetworkPolicy.LIMIT_DISABLED;
     34 import static android.net.NetworkPolicy.SNOOZE_NEVER;
     35 import static android.net.NetworkPolicy.WARNING_DISABLED;
     36 import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
     37 import static android.net.NetworkPolicyManager.POLICY_NONE;
     38 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
     39 import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
     40 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
     41 import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
     42 import static android.net.NetworkPolicyManager.dumpPolicy;
     43 import static android.net.NetworkPolicyManager.dumpRules;
     44 import static android.net.NetworkPolicyManager.isUidValidForPolicy;
     45 import static android.net.NetworkTemplate.MATCH_ETHERNET;
     46 import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
     47 import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
     48 import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
     49 import static android.net.NetworkTemplate.MATCH_WIFI;
     50 import static android.net.NetworkTemplate.buildTemplateMobileAll;
     51 import static android.text.format.DateUtils.DAY_IN_MILLIS;
     52 import static com.android.internal.util.Preconditions.checkNotNull;
     53 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
     54 import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readBooleanAttribute;
     55 import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readIntAttribute;
     56 import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.readLongAttribute;
     57 import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute;
     58 import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute;
     59 import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute;
     60 import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
     61 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
     62 import static org.xmlpull.v1.XmlPullParser.START_TAG;
     63 
     64 import android.app.IActivityManager;
     65 import android.app.INotificationManager;
     66 import android.app.IProcessObserver;
     67 import android.app.Notification;
     68 import android.app.PendingIntent;
     69 import android.content.BroadcastReceiver;
     70 import android.content.ComponentName;
     71 import android.content.Context;
     72 import android.content.Intent;
     73 import android.content.IntentFilter;
     74 import android.content.pm.ApplicationInfo;
     75 import android.content.pm.PackageManager;
     76 import android.content.res.Resources;
     77 import android.net.ConnectivityManager;
     78 import android.net.IConnectivityManager;
     79 import android.net.INetworkManagementEventObserver;
     80 import android.net.INetworkPolicyListener;
     81 import android.net.INetworkPolicyManager;
     82 import android.net.INetworkStatsService;
     83 import android.net.NetworkIdentity;
     84 import android.net.NetworkPolicy;
     85 import android.net.NetworkQuotaInfo;
     86 import android.net.NetworkState;
     87 import android.net.NetworkTemplate;
     88 import android.os.Binder;
     89 import android.os.Environment;
     90 import android.os.Handler;
     91 import android.os.HandlerThread;
     92 import android.os.INetworkManagementService;
     93 import android.os.IPowerManager;
     94 import android.os.Message;
     95 import android.os.MessageQueue.IdleHandler;
     96 import android.os.RemoteCallbackList;
     97 import android.os.RemoteException;
     98 import android.provider.Settings;
     99 import android.telephony.TelephonyManager;
    100 import android.text.format.Formatter;
    101 import android.text.format.Time;
    102 import android.util.Log;
    103 import android.util.NtpTrustedTime;
    104 import android.util.Slog;
    105 import android.util.SparseArray;
    106 import android.util.SparseBooleanArray;
    107 import android.util.SparseIntArray;
    108 import android.util.TrustedTime;
    109 import android.util.Xml;
    110 
    111 import com.android.internal.R;
    112 import com.android.internal.os.AtomicFile;
    113 import com.android.internal.util.FastXmlSerializer;
    114 import com.android.internal.util.Objects;
    115 import com.google.android.collect.Lists;
    116 import com.google.android.collect.Maps;
    117 import com.google.android.collect.Sets;
    118 
    119 import org.xmlpull.v1.XmlPullParser;
    120 import org.xmlpull.v1.XmlPullParserException;
    121 import org.xmlpull.v1.XmlSerializer;
    122 
    123 import java.io.File;
    124 import java.io.FileDescriptor;
    125 import java.io.FileInputStream;
    126 import java.io.FileNotFoundException;
    127 import java.io.FileOutputStream;
    128 import java.io.IOException;
    129 import java.io.PrintWriter;
    130 import java.net.ProtocolException;
    131 import java.util.ArrayList;
    132 import java.util.Arrays;
    133 import java.util.HashMap;
    134 import java.util.HashSet;
    135 import java.util.List;
    136 import java.util.Map;
    137 
    138 import libcore.io.IoUtils;
    139 
    140 /**
    141  * Service that maintains low-level network policy rules, using
    142  * {@link NetworkStatsService} statistics to drive those rules.
    143  * <p>
    144  * Derives active rules by combining a given policy with other system status,
    145  * and delivers to listeners, such as {@link ConnectivityManager}, for
    146  * enforcement.
    147  */
    148 public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
    149     private static final String TAG = "NetworkPolicy";
    150     private static final boolean LOGD = true;
    151     private static final boolean LOGV = false;
    152 
    153     private static final int VERSION_INIT = 1;
    154     private static final int VERSION_ADDED_SNOOZE = 2;
    155     private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3;
    156 
    157     private static final long KB_IN_BYTES = 1024;
    158     private static final long MB_IN_BYTES = KB_IN_BYTES * 1024;
    159     private static final long GB_IN_BYTES = MB_IN_BYTES * 1024;
    160 
    161     // @VisibleForTesting
    162     public static final int TYPE_WARNING = 0x1;
    163     public static final int TYPE_LIMIT = 0x2;
    164     public static final int TYPE_LIMIT_SNOOZED = 0x3;
    165 
    166     private static final String TAG_POLICY_LIST = "policy-list";
    167     private static final String TAG_NETWORK_POLICY = "network-policy";
    168     private static final String TAG_UID_POLICY = "uid-policy";
    169 
    170     private static final String ATTR_VERSION = "version";
    171     private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
    172     private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
    173     private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
    174     private static final String ATTR_CYCLE_DAY = "cycleDay";
    175     private static final String ATTR_WARNING_BYTES = "warningBytes";
    176     private static final String ATTR_LIMIT_BYTES = "limitBytes";
    177     private static final String ATTR_LAST_SNOOZE = "lastSnooze";
    178     private static final String ATTR_UID = "uid";
    179     private static final String ATTR_POLICY = "policy";
    180 
    181     private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground";
    182 
    183     // @VisibleForTesting
    184     public static final String ACTION_ALLOW_BACKGROUND =
    185             "com.android.server.action.ACTION_ALLOW_BACKGROUND";
    186 
    187     private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
    188 
    189     private static final int MSG_RULES_CHANGED = 1;
    190     private static final int MSG_METERED_IFACES_CHANGED = 2;
    191     private static final int MSG_FOREGROUND_ACTIVITIES_CHANGED = 3;
    192     private static final int MSG_PROCESS_DIED = 4;
    193     private static final int MSG_LIMIT_REACHED = 5;
    194 
    195     private final Context mContext;
    196     private final IActivityManager mActivityManager;
    197     private final IPowerManager mPowerManager;
    198     private final INetworkStatsService mNetworkStats;
    199     private final INetworkManagementService mNetworkManager;
    200     private final TrustedTime mTime;
    201 
    202     private IConnectivityManager mConnManager;
    203     private INotificationManager mNotifManager;
    204 
    205     private final Object mRulesLock = new Object();
    206 
    207     private volatile boolean mScreenOn;
    208     private volatile boolean mRestrictBackground;
    209 
    210     private final boolean mSuppressDefaultPolicy;
    211 
    212     /** Defined network policies. */
    213     private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap();
    214     /** Currently active network rules for ifaces. */
    215     private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap();
    216 
    217     /** Defined UID policies. */
    218     private SparseIntArray mUidPolicy = new SparseIntArray();
    219     /** Currently derived rules for each UID. */
    220     private SparseIntArray mUidRules = new SparseIntArray();
    221 
    222     /** Set of ifaces that are metered. */
    223     private HashSet<String> mMeteredIfaces = Sets.newHashSet();
    224     /** Set of over-limit templates that have been notified. */
    225     private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet();
    226 
    227     /** Set of currently active {@link Notification} tags. */
    228     private HashSet<String> mActiveNotifs = Sets.newHashSet();
    229 
    230     /** Foreground at both UID and PID granularity. */
    231     private SparseBooleanArray mUidForeground = new SparseBooleanArray();
    232     private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
    233             SparseBooleanArray>();
    234 
    235     private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
    236             INetworkPolicyListener>();
    237 
    238     private final HandlerThread mHandlerThread;
    239     private final Handler mHandler;
    240 
    241     private final AtomicFile mPolicyFile;
    242 
    243     // TODO: keep whitelist of system-critical services that should never have
    244     // rules enforced, such as system, phone, and radio UIDs.
    245 
    246     // TODO: migrate notifications to SystemUI
    247 
    248     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
    249             IPowerManager powerManager, INetworkStatsService networkStats,
    250             INetworkManagementService networkManagement) {
    251         this(context, activityManager, powerManager, networkStats, networkManagement,
    252                 NtpTrustedTime.getInstance(context), getSystemDir(), false);
    253     }
    254 
    255     private static File getSystemDir() {
    256         return new File(Environment.getDataDirectory(), "system");
    257     }
    258 
    259     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
    260             IPowerManager powerManager, INetworkStatsService networkStats,
    261             INetworkManagementService networkManagement, TrustedTime time, File systemDir,
    262             boolean suppressDefaultPolicy) {
    263         mContext = checkNotNull(context, "missing context");
    264         mActivityManager = checkNotNull(activityManager, "missing activityManager");
    265         mPowerManager = checkNotNull(powerManager, "missing powerManager");
    266         mNetworkStats = checkNotNull(networkStats, "missing networkStats");
    267         mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
    268         mTime = checkNotNull(time, "missing TrustedTime");
    269 
    270         mHandlerThread = new HandlerThread(TAG);
    271         mHandlerThread.start();
    272         mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
    273 
    274         mSuppressDefaultPolicy = suppressDefaultPolicy;
    275 
    276         mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
    277     }
    278 
    279     public void bindConnectivityManager(IConnectivityManager connManager) {
    280         mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
    281     }
    282 
    283     public void bindNotificationManager(INotificationManager notifManager) {
    284         mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
    285     }
    286 
    287     public void systemReady() {
    288         synchronized (mRulesLock) {
    289             // read policy from disk
    290             readPolicyLocked();
    291 
    292             if (mRestrictBackground) {
    293                 updateRulesForRestrictBackgroundLocked();
    294                 updateNotificationsLocked();
    295             }
    296         }
    297 
    298         updateScreenOn();
    299 
    300         try {
    301             mActivityManager.registerProcessObserver(mProcessObserver);
    302             mNetworkManager.registerObserver(mAlertObserver);
    303         } catch (RemoteException e) {
    304             // ignored; both services live in system_server
    305         }
    306 
    307         // TODO: traverse existing processes to know foreground state, or have
    308         // activitymanager dispatch current state when new observer attached.
    309 
    310         final IntentFilter screenFilter = new IntentFilter();
    311         screenFilter.addAction(Intent.ACTION_SCREEN_ON);
    312         screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
    313         mContext.registerReceiver(mScreenReceiver, screenFilter, null, mHandler);
    314 
    315         // watch for network interfaces to be claimed
    316         final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
    317         mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
    318 
    319         // listen for package/uid changes to update policy
    320         final IntentFilter packageFilter = new IntentFilter();
    321         packageFilter.addAction(ACTION_PACKAGE_ADDED);
    322         packageFilter.addAction(ACTION_UID_REMOVED);
    323         mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
    324 
    325         // listen for stats update events
    326         final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
    327         mContext.registerReceiver(
    328                 mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
    329 
    330         // listen for restrict background changes from notifications
    331         final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
    332         mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler);
    333 
    334     }
    335 
    336     private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
    337         @Override
    338         public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
    339             mHandler.obtainMessage(MSG_FOREGROUND_ACTIVITIES_CHANGED,
    340                     pid, uid, foregroundActivities).sendToTarget();
    341         }
    342 
    343         @Override
    344         public void onProcessDied(int pid, int uid) {
    345             mHandler.obtainMessage(MSG_PROCESS_DIED, pid, uid).sendToTarget();
    346         }
    347     };
    348 
    349     private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
    350         @Override
    351         public void onReceive(Context context, Intent intent) {
    352             synchronized (mRulesLock) {
    353                 // screen-related broadcasts are protected by system, no need
    354                 // for permissions check.
    355                 updateScreenOn();
    356             }
    357         }
    358     };
    359 
    360     private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
    361         @Override
    362         public void onReceive(Context context, Intent intent) {
    363             // on background handler thread, and PACKAGE_ADDED and UID_REMOVED
    364             // are protected broadcasts.
    365 
    366             final String action = intent.getAction();
    367             final int uid = intent.getIntExtra(EXTRA_UID, 0);
    368             synchronized (mRulesLock) {
    369                 if (ACTION_PACKAGE_ADDED.equals(action)) {
    370                     // update rules for UID, since it might be subject to
    371                     // global background data policy.
    372                     if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
    373                     updateRulesForUidLocked(uid);
    374 
    375                 } else if (ACTION_UID_REMOVED.equals(action)) {
    376                     // remove any policy and update rules to clean up.
    377                     if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
    378                     mUidPolicy.delete(uid);
    379                     updateRulesForUidLocked(uid);
    380                     writePolicyLocked();
    381                 }
    382             }
    383         }
    384     };
    385 
    386     /**
    387      * Receiver that watches for {@link INetworkStatsService} updates, which we
    388      * use to check against {@link NetworkPolicy#warningBytes}.
    389      */
    390     private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
    391         @Override
    392         public void onReceive(Context context, Intent intent) {
    393             // on background handler thread, and verified
    394             // READ_NETWORK_USAGE_HISTORY permission above.
    395 
    396             maybeRefreshTrustedTime();
    397             synchronized (mRulesLock) {
    398                 updateNetworkEnabledLocked();
    399                 updateNotificationsLocked();
    400             }
    401         }
    402     };
    403 
    404     /**
    405      * Receiver that watches for {@link Notification} control of
    406      * {@link #mRestrictBackground}.
    407      */
    408     private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() {
    409         @Override
    410         public void onReceive(Context context, Intent intent) {
    411             // on background handler thread, and verified MANAGE_NETWORK_POLICY
    412             // permission above.
    413 
    414             setRestrictBackground(false);
    415         }
    416     };
    417 
    418     /**
    419      * Observer that watches for {@link INetworkManagementService} alerts.
    420      */
    421     private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
    422         @Override
    423         public void limitReached(String limitName, String iface) {
    424             // only someone like NMS should be calling us
    425             mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
    426 
    427             if (!LIMIT_GLOBAL_ALERT.equals(limitName)) {
    428                 mHandler.obtainMessage(MSG_LIMIT_REACHED, iface).sendToTarget();
    429             }
    430         }
    431     };
    432 
    433     /**
    434      * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
    435      * to show visible notifications as needed.
    436      */
    437     private void updateNotificationsLocked() {
    438         if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
    439 
    440         // keep track of previously active notifications
    441         final HashSet<String> beforeNotifs = Sets.newHashSet();
    442         beforeNotifs.addAll(mActiveNotifs);
    443         mActiveNotifs.clear();
    444 
    445         // TODO: when switching to kernel notifications, compute next future
    446         // cycle boundary to recompute notifications.
    447 
    448         // examine stats for each active policy
    449         final long currentTime = currentTimeMillis();
    450         for (NetworkPolicy policy : mNetworkPolicy.values()) {
    451             // ignore policies that aren't relevant to user
    452             if (!isTemplateRelevant(policy.template)) continue;
    453 
    454             final long start = computeLastCycleBoundary(currentTime, policy);
    455             final long end = currentTime;
    456             final long totalBytes = getTotalBytes(policy.template, start, end);
    457 
    458             if (policy.isOverLimit(totalBytes)) {
    459                 if (policy.lastSnooze >= start) {
    460                     enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
    461                 } else {
    462                     enqueueNotification(policy, TYPE_LIMIT, totalBytes);
    463                     notifyOverLimitLocked(policy.template);
    464                 }
    465 
    466             } else {
    467                 notifyUnderLimitLocked(policy.template);
    468 
    469                 if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) {
    470                     enqueueNotification(policy, TYPE_WARNING, totalBytes);
    471                 }
    472             }
    473         }
    474 
    475         // ongoing notification when restricting background data
    476         if (mRestrictBackground) {
    477             enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND);
    478         }
    479 
    480         // cancel stale notifications that we didn't renew above
    481         for (String tag : beforeNotifs) {
    482             if (!mActiveNotifs.contains(tag)) {
    483                 cancelNotification(tag);
    484             }
    485         }
    486     }
    487 
    488     /**
    489      * Test if given {@link NetworkTemplate} is relevant to user based on
    490      * current device state, such as when {@link #getActiveSubscriberId()}
    491      * matches. This is regardless of data connection status.
    492      */
    493     private boolean isTemplateRelevant(NetworkTemplate template) {
    494         switch (template.getMatchRule()) {
    495             case MATCH_MOBILE_3G_LOWER:
    496             case MATCH_MOBILE_4G:
    497             case MATCH_MOBILE_ALL:
    498                 // mobile templates are relevant when subscriberid is active
    499                 return Objects.equal(getActiveSubscriberId(), template.getSubscriberId());
    500         }
    501         return true;
    502     }
    503 
    504     /**
    505      * Notify that given {@link NetworkTemplate} is over
    506      * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
    507      */
    508     private void notifyOverLimitLocked(NetworkTemplate template) {
    509         if (!mOverLimitNotified.contains(template)) {
    510             mContext.startActivity(buildNetworkOverLimitIntent(template));
    511             mOverLimitNotified.add(template);
    512         }
    513     }
    514 
    515     private void notifyUnderLimitLocked(NetworkTemplate template) {
    516         mOverLimitNotified.remove(template);
    517     }
    518 
    519     /**
    520      * Build unique tag that identifies an active {@link NetworkPolicy}
    521      * notification of a specific type, like {@link #TYPE_LIMIT}.
    522      */
    523     private String buildNotificationTag(NetworkPolicy policy, int type) {
    524         return TAG + ":" + policy.template.hashCode() + ":" + type;
    525     }
    526 
    527     /**
    528      * Show notification for combined {@link NetworkPolicy} and specific type,
    529      * like {@link #TYPE_LIMIT}. Okay to call multiple times.
    530      */
    531     private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
    532         final String tag = buildNotificationTag(policy, type);
    533         final Notification.Builder builder = new Notification.Builder(mContext);
    534         builder.setOnlyAlertOnce(true);
    535         builder.setOngoing(true);
    536 
    537         final Resources res = mContext.getResources();
    538         switch (type) {
    539             case TYPE_WARNING: {
    540                 final CharSequence title = res.getText(R.string.data_usage_warning_title);
    541                 final CharSequence body = res.getString(R.string.data_usage_warning_body);
    542 
    543                 builder.setSmallIcon(R.drawable.stat_notify_error);
    544                 builder.setTicker(title);
    545                 builder.setContentTitle(title);
    546                 builder.setContentText(body);
    547 
    548                 final Intent intent = buildViewDataUsageIntent(policy.template);
    549                 builder.setContentIntent(PendingIntent.getActivity(
    550                         mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
    551                 break;
    552             }
    553             case TYPE_LIMIT: {
    554                 final CharSequence body = res.getText(R.string.data_usage_limit_body);
    555 
    556                 final CharSequence title;
    557                 switch (policy.template.getMatchRule()) {
    558                     case MATCH_MOBILE_3G_LOWER:
    559                         title = res.getText(R.string.data_usage_3g_limit_title);
    560                         break;
    561                     case MATCH_MOBILE_4G:
    562                         title = res.getText(R.string.data_usage_4g_limit_title);
    563                         break;
    564                     case MATCH_MOBILE_ALL:
    565                         title = res.getText(R.string.data_usage_mobile_limit_title);
    566                         break;
    567                     case MATCH_WIFI:
    568                         title = res.getText(R.string.data_usage_wifi_limit_title);
    569                         break;
    570                     default:
    571                         title = null;
    572                         break;
    573                 }
    574 
    575                 builder.setSmallIcon(R.drawable.stat_notify_disabled);
    576                 builder.setTicker(title);
    577                 builder.setContentTitle(title);
    578                 builder.setContentText(body);
    579 
    580                 final Intent intent = buildNetworkOverLimitIntent(policy.template);
    581                 builder.setContentIntent(PendingIntent.getActivity(
    582                         mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
    583                 break;
    584             }
    585             case TYPE_LIMIT_SNOOZED: {
    586                 final long overBytes = totalBytes - policy.limitBytes;
    587                 final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body,
    588                         Formatter.formatFileSize(mContext, overBytes));
    589 
    590                 final CharSequence title;
    591                 switch (policy.template.getMatchRule()) {
    592                     case MATCH_MOBILE_3G_LOWER:
    593                         title = res.getText(R.string.data_usage_3g_limit_snoozed_title);
    594                         break;
    595                     case MATCH_MOBILE_4G:
    596                         title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
    597                         break;
    598                     case MATCH_MOBILE_ALL:
    599                         title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
    600                         break;
    601                     case MATCH_WIFI:
    602                         title = res.getText(R.string.data_usage_wifi_limit_snoozed_title);
    603                         break;
    604                     default:
    605                         title = null;
    606                         break;
    607                 }
    608 
    609                 builder.setSmallIcon(R.drawable.stat_notify_error);
    610                 builder.setTicker(title);
    611                 builder.setContentTitle(title);
    612                 builder.setContentText(body);
    613 
    614                 final Intent intent = buildViewDataUsageIntent(policy.template);
    615                 builder.setContentIntent(PendingIntent.getActivity(
    616                         mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
    617                 break;
    618             }
    619         }
    620 
    621         // TODO: move to NotificationManager once we can mock it
    622         try {
    623             final String packageName = mContext.getPackageName();
    624             final int[] idReceived = new int[1];
    625             mNotifManager.enqueueNotificationWithTag(
    626                     packageName, tag, 0x0, builder.getNotification(), idReceived);
    627             mActiveNotifs.add(tag);
    628         } catch (RemoteException e) {
    629             // ignored; service lives in system_server
    630         }
    631     }
    632 
    633     /**
    634      * Show ongoing notification to reflect that {@link #mRestrictBackground}
    635      * has been enabled.
    636      */
    637     private void enqueueRestrictedNotification(String tag) {
    638         final Resources res = mContext.getResources();
    639         final Notification.Builder builder = new Notification.Builder(mContext);
    640 
    641         final CharSequence title = res.getText(R.string.data_usage_restricted_title);
    642         final CharSequence body = res.getString(R.string.data_usage_restricted_body);
    643 
    644         builder.setOnlyAlertOnce(true);
    645         builder.setOngoing(true);
    646         builder.setSmallIcon(R.drawable.stat_notify_error);
    647         builder.setTicker(title);
    648         builder.setContentTitle(title);
    649         builder.setContentText(body);
    650 
    651         final Intent intent = buildAllowBackgroundDataIntent();
    652         builder.setContentIntent(
    653                 PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
    654 
    655         // TODO: move to NotificationManager once we can mock it
    656         try {
    657             final String packageName = mContext.getPackageName();
    658             final int[] idReceived = new int[1];
    659             mNotifManager.enqueueNotificationWithTag(packageName, tag,
    660                     0x0, builder.getNotification(), idReceived);
    661             mActiveNotifs.add(tag);
    662         } catch (RemoteException e) {
    663             // ignored; service lives in system_server
    664         }
    665     }
    666 
    667     private void cancelNotification(String tag) {
    668         // TODO: move to NotificationManager once we can mock it
    669         try {
    670             final String packageName = mContext.getPackageName();
    671             mNotifManager.cancelNotificationWithTag(
    672                     packageName, tag, 0x0);
    673         } catch (RemoteException e) {
    674             // ignored; service lives in system_server
    675         }
    676     }
    677 
    678     /**
    679      * Receiver that watches for {@link IConnectivityManager} to claim network
    680      * interfaces. Used to apply {@link NetworkPolicy} to matching networks.
    681      */
    682     private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
    683         @Override
    684         public void onReceive(Context context, Intent intent) {
    685             // on background handler thread, and verified CONNECTIVITY_INTERNAL
    686             // permission above.
    687 
    688             maybeRefreshTrustedTime();
    689             synchronized (mRulesLock) {
    690                 ensureActiveMobilePolicyLocked();
    691                 updateNetworkEnabledLocked();
    692                 updateNetworkRulesLocked();
    693                 updateNotificationsLocked();
    694             }
    695         }
    696     };
    697 
    698     /**
    699      * Proactively control network data connections when they exceed
    700      * {@link NetworkPolicy#limitBytes}.
    701      */
    702     private void updateNetworkEnabledLocked() {
    703         if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()");
    704 
    705         // TODO: reset any policy-disabled networks when any policy is removed
    706         // completely, which is currently rare case.
    707 
    708         final long currentTime = currentTimeMillis();
    709         for (NetworkPolicy policy : mNetworkPolicy.values()) {
    710             // shortcut when policy has no limit
    711             if (policy.limitBytes == LIMIT_DISABLED) {
    712                 setNetworkTemplateEnabled(policy.template, true);
    713                 continue;
    714             }
    715 
    716             final long start = computeLastCycleBoundary(currentTime, policy);
    717             final long end = currentTime;
    718             final long totalBytes = getTotalBytes(policy.template, start, end);
    719 
    720             // disable data connection when over limit and not snoozed
    721             final boolean overLimit = policy.isOverLimit(totalBytes) && policy.lastSnooze < start;
    722             final boolean enabled = !overLimit;
    723 
    724             setNetworkTemplateEnabled(policy.template, enabled);
    725         }
    726     }
    727 
    728     /**
    729      * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}
    730      * for the given {@link NetworkTemplate}.
    731      */
    732     private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
    733         switch (template.getMatchRule()) {
    734             case MATCH_MOBILE_3G_LOWER:
    735             case MATCH_MOBILE_4G:
    736             case MATCH_MOBILE_ALL:
    737                 // TODO: offer more granular control over radio states once
    738                 // 4965893 is available.
    739                 if (Objects.equal(getActiveSubscriberId(), template.getSubscriberId())) {
    740                     setPolicyDataEnable(TYPE_MOBILE, enabled);
    741                     setPolicyDataEnable(TYPE_WIMAX, enabled);
    742                 }
    743                 break;
    744             case MATCH_WIFI:
    745                 setPolicyDataEnable(TYPE_WIFI, enabled);
    746                 break;
    747             case MATCH_ETHERNET:
    748                 setPolicyDataEnable(TYPE_ETHERNET, enabled);
    749                 break;
    750             default:
    751                 throw new IllegalArgumentException("unexpected template");
    752         }
    753     }
    754 
    755     /**
    756      * Examine all connected {@link NetworkState}, looking for
    757      * {@link NetworkPolicy} that need to be enforced. When matches found, set
    758      * remaining quota based on usage cycle and historical stats.
    759      */
    760     private void updateNetworkRulesLocked() {
    761         if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
    762 
    763         final NetworkState[] states;
    764         try {
    765             states = mConnManager.getAllNetworkState();
    766         } catch (RemoteException e) {
    767             // ignored; service lives in system_server
    768             return;
    769         }
    770 
    771         // first, derive identity for all connected networks, which can be used
    772         // to match against templates.
    773         final HashMap<NetworkIdentity, String> networks = Maps.newHashMap();
    774         for (NetworkState state : states) {
    775             // stash identity and iface away for later use
    776             if (state.networkInfo.isConnected()) {
    777                 final String iface = state.linkProperties.getInterfaceName();
    778                 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
    779                 networks.put(ident, iface);
    780             }
    781         }
    782 
    783         // build list of rules and ifaces to enforce them against
    784         mNetworkRules.clear();
    785         final ArrayList<String> ifaceList = Lists.newArrayList();
    786         for (NetworkPolicy policy : mNetworkPolicy.values()) {
    787 
    788             // collect all active ifaces that match this template
    789             ifaceList.clear();
    790             for (Map.Entry<NetworkIdentity, String> entry : networks.entrySet()) {
    791                 final NetworkIdentity ident = entry.getKey();
    792                 if (policy.template.matches(ident)) {
    793                     final String iface = entry.getValue();
    794                     ifaceList.add(iface);
    795                 }
    796             }
    797 
    798             if (ifaceList.size() > 0) {
    799                 final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
    800                 mNetworkRules.put(policy, ifaces);
    801             }
    802         }
    803 
    804         final HashSet<String> newMeteredIfaces = Sets.newHashSet();
    805 
    806         // apply each policy that we found ifaces for; compute remaining data
    807         // based on current cycle and historical stats, and push to kernel.
    808         final long currentTime = currentTimeMillis();
    809         for (NetworkPolicy policy : mNetworkRules.keySet()) {
    810             final String[] ifaces = mNetworkRules.get(policy);
    811 
    812             final long start = computeLastCycleBoundary(currentTime, policy);
    813             final long end = currentTime;
    814             final long totalBytes = getTotalBytes(policy.template, start, end);
    815 
    816             if (LOGD) {
    817                 Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
    818                         + Arrays.toString(ifaces));
    819             }
    820 
    821             final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
    822             if (hasLimit) {
    823                 final long quotaBytes;
    824                 if (policy.lastSnooze >= start) {
    825                     // snoozing past quota, but we still need to restrict apps,
    826                     // so push really high quota.
    827                     quotaBytes = Long.MAX_VALUE;
    828                 } else {
    829                     // remaining "quota" bytes are based on total usage in
    830                     // current cycle. kernel doesn't like 0-byte rules, so we
    831                     // set 1-byte quota and disable the radio later.
    832                     quotaBytes = Math.max(1, policy.limitBytes - totalBytes);
    833                 }
    834 
    835                 if (ifaces.length > 1) {
    836                     // TODO: switch to shared quota once NMS supports
    837                     Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
    838                 }
    839 
    840                 for (String iface : ifaces) {
    841                     removeInterfaceQuota(iface);
    842                     setInterfaceQuota(iface, quotaBytes);
    843                     newMeteredIfaces.add(iface);
    844                 }
    845             }
    846         }
    847 
    848         // remove quota on any trailing interfaces
    849         for (String iface : mMeteredIfaces) {
    850             if (!newMeteredIfaces.contains(iface)) {
    851                 removeInterfaceQuota(iface);
    852             }
    853         }
    854         mMeteredIfaces = newMeteredIfaces;
    855 
    856         final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
    857         mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
    858     }
    859 
    860     /**
    861      * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
    862      * have at least a default mobile policy defined.
    863      */
    864     private void ensureActiveMobilePolicyLocked() {
    865         if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
    866         if (mSuppressDefaultPolicy) return;
    867 
    868         final String subscriberId = getActiveSubscriberId();
    869         final NetworkIdentity probeIdent = new NetworkIdentity(
    870                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false);
    871 
    872         // examine to see if any policy is defined for active mobile
    873         boolean mobileDefined = false;
    874         for (NetworkPolicy policy : mNetworkPolicy.values()) {
    875             if (policy.template.matches(probeIdent)) {
    876                 mobileDefined = true;
    877             }
    878         }
    879 
    880         if (!mobileDefined) {
    881             Slog.i(TAG, "no policy for active mobile network; generating default policy");
    882 
    883             // build default mobile policy, and assume usage cycle starts today
    884             final long warningBytes = mContext.getResources().getInteger(
    885                     com.android.internal.R.integer.config_networkPolicyDefaultWarning)
    886                     * MB_IN_BYTES;
    887 
    888             final Time time = new Time(Time.TIMEZONE_UTC);
    889             time.setToNow();
    890             final int cycleDay = time.monthDay;
    891 
    892             final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
    893             mNetworkPolicy.put(template, new NetworkPolicy(
    894                     template, cycleDay, warningBytes, LIMIT_DISABLED, SNOOZE_NEVER));
    895             writePolicyLocked();
    896         }
    897     }
    898 
    899     private void readPolicyLocked() {
    900         if (LOGV) Slog.v(TAG, "readPolicyLocked()");
    901 
    902         // clear any existing policy and read from disk
    903         mNetworkPolicy.clear();
    904         mUidPolicy.clear();
    905 
    906         FileInputStream fis = null;
    907         try {
    908             fis = mPolicyFile.openRead();
    909             final XmlPullParser in = Xml.newPullParser();
    910             in.setInput(fis, null);
    911 
    912             int type;
    913             int version = VERSION_INIT;
    914             while ((type = in.next()) != END_DOCUMENT) {
    915                 final String tag = in.getName();
    916                 if (type == START_TAG) {
    917                     if (TAG_POLICY_LIST.equals(tag)) {
    918                         version = readIntAttribute(in, ATTR_VERSION);
    919                         if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) {
    920                             mRestrictBackground = readBooleanAttribute(
    921                                     in, ATTR_RESTRICT_BACKGROUND);
    922                         } else {
    923                             mRestrictBackground = false;
    924                         }
    925 
    926                     } else if (TAG_NETWORK_POLICY.equals(tag)) {
    927                         final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
    928                         final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
    929                         final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
    930                         final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
    931                         final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
    932                         final long lastSnooze;
    933                         if (version >= VERSION_ADDED_SNOOZE) {
    934                             lastSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
    935                         } else {
    936                             lastSnooze = SNOOZE_NEVER;
    937                         }
    938 
    939                         final NetworkTemplate template = new NetworkTemplate(
    940                                 networkTemplate, subscriberId);
    941                         mNetworkPolicy.put(template, new NetworkPolicy(
    942                                 template, cycleDay, warningBytes, limitBytes, lastSnooze));
    943 
    944                     } else if (TAG_UID_POLICY.equals(tag)) {
    945                         final int uid = readIntAttribute(in, ATTR_UID);
    946                         final int policy = readIntAttribute(in, ATTR_POLICY);
    947 
    948                         if (isUidValidForPolicy(mContext, uid)) {
    949                             setUidPolicyUnchecked(uid, policy, false);
    950                         } else {
    951                             Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
    952                         }
    953                     }
    954                 }
    955             }
    956 
    957         } catch (FileNotFoundException e) {
    958             // missing policy is okay, probably first boot
    959             upgradeLegacyBackgroundData();
    960         } catch (IOException e) {
    961             Log.wtf(TAG, "problem reading network policy", e);
    962         } catch (XmlPullParserException e) {
    963             Log.wtf(TAG, "problem reading network policy", e);
    964         } finally {
    965             IoUtils.closeQuietly(fis);
    966         }
    967     }
    968 
    969     /**
    970      * Upgrade legacy background data flags, notifying listeners of one last
    971      * change to always-true.
    972      */
    973     private void upgradeLegacyBackgroundData() {
    974         mRestrictBackground = Settings.Secure.getInt(
    975                 mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1;
    976 
    977         // kick off one last broadcast if restricted
    978         if (mRestrictBackground) {
    979             final Intent broadcast = new Intent(
    980                     ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
    981             mContext.sendBroadcast(broadcast);
    982         }
    983     }
    984 
    985     private void writePolicyLocked() {
    986         if (LOGV) Slog.v(TAG, "writePolicyLocked()");
    987 
    988         FileOutputStream fos = null;
    989         try {
    990             fos = mPolicyFile.startWrite();
    991 
    992             XmlSerializer out = new FastXmlSerializer();
    993             out.setOutput(fos, "utf-8");
    994             out.startDocument(null, true);
    995 
    996             out.startTag(null, TAG_POLICY_LIST);
    997             writeIntAttribute(out, ATTR_VERSION, VERSION_ADDED_RESTRICT_BACKGROUND);
    998             writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
    999 
   1000             // write all known network policies
   1001             for (NetworkPolicy policy : mNetworkPolicy.values()) {
   1002                 final NetworkTemplate template = policy.template;
   1003 
   1004                 out.startTag(null, TAG_NETWORK_POLICY);
   1005                 writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
   1006                 final String subscriberId = template.getSubscriberId();
   1007                 if (subscriberId != null) {
   1008                     out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
   1009                 }
   1010                 writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
   1011                 writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
   1012                 writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
   1013                 writeLongAttribute(out, ATTR_LAST_SNOOZE, policy.lastSnooze);
   1014                 out.endTag(null, TAG_NETWORK_POLICY);
   1015             }
   1016 
   1017             // write all known uid policies
   1018             for (int i = 0; i < mUidPolicy.size(); i++) {
   1019                 final int uid = mUidPolicy.keyAt(i);
   1020                 final int policy = mUidPolicy.valueAt(i);
   1021 
   1022                 // skip writing empty policies
   1023                 if (policy == POLICY_NONE) continue;
   1024 
   1025                 out.startTag(null, TAG_UID_POLICY);
   1026                 writeIntAttribute(out, ATTR_UID, uid);
   1027                 writeIntAttribute(out, ATTR_POLICY, policy);
   1028                 out.endTag(null, TAG_UID_POLICY);
   1029             }
   1030 
   1031             out.endTag(null, TAG_POLICY_LIST);
   1032             out.endDocument();
   1033 
   1034             mPolicyFile.finishWrite(fos);
   1035         } catch (IOException e) {
   1036             if (fos != null) {
   1037                 mPolicyFile.failWrite(fos);
   1038             }
   1039         }
   1040     }
   1041 
   1042     @Override
   1043     public void setUidPolicy(int uid, int policy) {
   1044         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1045 
   1046         if (!isUidValidForPolicy(mContext, uid)) {
   1047             throw new IllegalArgumentException("cannot apply policy to UID " + uid);
   1048         }
   1049 
   1050         setUidPolicyUnchecked(uid, policy, true);
   1051     }
   1052 
   1053     private void setUidPolicyUnchecked(int uid, int policy, boolean persist) {
   1054         final int oldPolicy;
   1055         synchronized (mRulesLock) {
   1056             oldPolicy = getUidPolicy(uid);
   1057             mUidPolicy.put(uid, policy);
   1058 
   1059             // uid policy changed, recompute rules and persist policy.
   1060             updateRulesForUidLocked(uid);
   1061             if (persist) {
   1062                 writePolicyLocked();
   1063             }
   1064         }
   1065     }
   1066 
   1067     @Override
   1068     public int getUidPolicy(int uid) {
   1069         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1070 
   1071         synchronized (mRulesLock) {
   1072             return mUidPolicy.get(uid, POLICY_NONE);
   1073         }
   1074     }
   1075 
   1076     @Override
   1077     public void registerListener(INetworkPolicyListener listener) {
   1078         // TODO: create permission for observing network policy
   1079         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1080 
   1081         mListeners.register(listener);
   1082 
   1083         // TODO: consider dispatching existing rules to new listeners
   1084     }
   1085 
   1086     @Override
   1087     public void unregisterListener(INetworkPolicyListener listener) {
   1088         // TODO: create permission for observing network policy
   1089         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1090 
   1091         mListeners.unregister(listener);
   1092     }
   1093 
   1094     @Override
   1095     public void setNetworkPolicies(NetworkPolicy[] policies) {
   1096         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1097 
   1098         maybeRefreshTrustedTime();
   1099         synchronized (mRulesLock) {
   1100             mNetworkPolicy.clear();
   1101             for (NetworkPolicy policy : policies) {
   1102                 mNetworkPolicy.put(policy.template, policy);
   1103             }
   1104 
   1105             updateNetworkEnabledLocked();
   1106             updateNetworkRulesLocked();
   1107             updateNotificationsLocked();
   1108             writePolicyLocked();
   1109         }
   1110     }
   1111 
   1112     @Override
   1113     public NetworkPolicy[] getNetworkPolicies() {
   1114         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1115         mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
   1116 
   1117         synchronized (mRulesLock) {
   1118             return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]);
   1119         }
   1120     }
   1121 
   1122     @Override
   1123     public void snoozePolicy(NetworkTemplate template) {
   1124         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1125 
   1126         maybeRefreshTrustedTime();
   1127         final long currentTime = currentTimeMillis();
   1128         synchronized (mRulesLock) {
   1129             // find and snooze local policy that matches
   1130             final NetworkPolicy policy = mNetworkPolicy.get(template);
   1131             if (policy == null) {
   1132                 throw new IllegalArgumentException("unable to find policy for " + template);
   1133             }
   1134 
   1135             policy.lastSnooze = currentTime;
   1136 
   1137             updateNetworkEnabledLocked();
   1138             updateNetworkRulesLocked();
   1139             updateNotificationsLocked();
   1140             writePolicyLocked();
   1141         }
   1142     }
   1143 
   1144     @Override
   1145     public void setRestrictBackground(boolean restrictBackground) {
   1146         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1147 
   1148         maybeRefreshTrustedTime();
   1149         synchronized (mRulesLock) {
   1150             mRestrictBackground = restrictBackground;
   1151             updateRulesForRestrictBackgroundLocked();
   1152             updateNotificationsLocked();
   1153             writePolicyLocked();
   1154         }
   1155     }
   1156 
   1157     @Override
   1158     public boolean getRestrictBackground() {
   1159         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1160 
   1161         synchronized (mRulesLock) {
   1162             return mRestrictBackground;
   1163         }
   1164     }
   1165 
   1166     private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) {
   1167         for (NetworkPolicy policy : mNetworkPolicy.values()) {
   1168             if (policy.template.matches(ident)) {
   1169                 return policy;
   1170             }
   1171         }
   1172         return null;
   1173     }
   1174 
   1175     @Override
   1176     public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) {
   1177         mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
   1178 
   1179         // only returns usage summary, so we don't require caller to have
   1180         // READ_NETWORK_USAGE_HISTORY.
   1181         final long token = Binder.clearCallingIdentity();
   1182         try {
   1183             return getNetworkQuotaInfoUnchecked(state);
   1184         } finally {
   1185             Binder.restoreCallingIdentity(token);
   1186         }
   1187     }
   1188 
   1189     private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) {
   1190         final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
   1191 
   1192         final NetworkPolicy policy;
   1193         synchronized (mRulesLock) {
   1194             policy = findPolicyForNetworkLocked(ident);
   1195         }
   1196 
   1197         if (policy == null) {
   1198             // missing policy means we can't derive useful quota info
   1199             return null;
   1200         }
   1201 
   1202         final long currentTime = currentTimeMillis();
   1203 
   1204         // find total bytes used under policy
   1205         final long start = computeLastCycleBoundary(currentTime, policy);
   1206         final long end = currentTime;
   1207         final long totalBytes = getTotalBytes(policy.template, start, end);
   1208 
   1209         // report soft and hard limits under policy
   1210         final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes
   1211                 : NetworkQuotaInfo.NO_LIMIT;
   1212         final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes
   1213                 : NetworkQuotaInfo.NO_LIMIT;
   1214 
   1215         return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes);
   1216     }
   1217 
   1218     @Override
   1219     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
   1220         mContext.enforceCallingOrSelfPermission(DUMP, TAG);
   1221 
   1222         final HashSet<String> argSet = new HashSet<String>();
   1223         for (String arg : args) {
   1224             argSet.add(arg);
   1225         }
   1226 
   1227         synchronized (mRulesLock) {
   1228             if (argSet.contains("unsnooze")) {
   1229                 for (NetworkPolicy policy : mNetworkPolicy.values()) {
   1230                     policy.lastSnooze = SNOOZE_NEVER;
   1231                 }
   1232                 writePolicyLocked();
   1233                 fout.println("Wiped snooze timestamps");
   1234                 return;
   1235             }
   1236 
   1237             fout.print("Restrict background: "); fout.println(mRestrictBackground);
   1238             fout.println("Network policies:");
   1239             for (NetworkPolicy policy : mNetworkPolicy.values()) {
   1240                 fout.print("  "); fout.println(policy.toString());
   1241             }
   1242 
   1243             fout.println("Policy status for known UIDs:");
   1244 
   1245             final SparseBooleanArray knownUids = new SparseBooleanArray();
   1246             collectKeys(mUidPolicy, knownUids);
   1247             collectKeys(mUidForeground, knownUids);
   1248             collectKeys(mUidRules, knownUids);
   1249 
   1250             final int size = knownUids.size();
   1251             for (int i = 0; i < size; i++) {
   1252                 final int uid = knownUids.keyAt(i);
   1253                 fout.print("  UID=");
   1254                 fout.print(uid);
   1255 
   1256                 fout.print(" policy=");
   1257                 final int policyIndex = mUidPolicy.indexOfKey(uid);
   1258                 if (policyIndex < 0) {
   1259                     fout.print("UNKNOWN");
   1260                 } else {
   1261                     dumpPolicy(fout, mUidPolicy.valueAt(policyIndex));
   1262                 }
   1263 
   1264                 fout.print(" foreground=");
   1265                 final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
   1266                 if (foregroundIndex < 0) {
   1267                     fout.print("UNKNOWN");
   1268                 } else {
   1269                     dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex));
   1270                 }
   1271 
   1272                 fout.print(" rules=");
   1273                 final int rulesIndex = mUidRules.indexOfKey(uid);
   1274                 if (rulesIndex < 0) {
   1275                     fout.print("UNKNOWN");
   1276                 } else {
   1277                     dumpRules(fout, mUidRules.valueAt(rulesIndex));
   1278                 }
   1279 
   1280                 fout.println();
   1281             }
   1282         }
   1283     }
   1284 
   1285     @Override
   1286     public boolean isUidForeground(int uid) {
   1287         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1288 
   1289         synchronized (mRulesLock) {
   1290             // only really in foreground when screen is also on
   1291             return mUidForeground.get(uid, false) && mScreenOn;
   1292         }
   1293     }
   1294 
   1295     /**
   1296      * Foreground for PID changed; recompute foreground at UID level. If
   1297      * changed, will trigger {@link #updateRulesForUidLocked(int)}.
   1298      */
   1299     private void computeUidForegroundLocked(int uid) {
   1300         final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
   1301 
   1302         // current pid is dropping foreground; examine other pids
   1303         boolean uidForeground = false;
   1304         final int size = pidForeground.size();
   1305         for (int i = 0; i < size; i++) {
   1306             if (pidForeground.valueAt(i)) {
   1307                 uidForeground = true;
   1308                 break;
   1309             }
   1310         }
   1311 
   1312         final boolean oldUidForeground = mUidForeground.get(uid, false);
   1313         if (oldUidForeground != uidForeground) {
   1314             // foreground changed, push updated rules
   1315             mUidForeground.put(uid, uidForeground);
   1316             updateRulesForUidLocked(uid);
   1317         }
   1318     }
   1319 
   1320     private void updateScreenOn() {
   1321         synchronized (mRulesLock) {
   1322             try {
   1323                 mScreenOn = mPowerManager.isScreenOn();
   1324             } catch (RemoteException e) {
   1325                 // ignored; service lives in system_server
   1326             }
   1327             updateRulesForScreenLocked();
   1328         }
   1329     }
   1330 
   1331     /**
   1332      * Update rules that might be changed by {@link #mScreenOn} value.
   1333      */
   1334     private void updateRulesForScreenLocked() {
   1335         // only update rules for anyone with foreground activities
   1336         final int size = mUidForeground.size();
   1337         for (int i = 0; i < size; i++) {
   1338             if (mUidForeground.valueAt(i)) {
   1339                 final int uid = mUidForeground.keyAt(i);
   1340                 updateRulesForUidLocked(uid);
   1341             }
   1342         }
   1343     }
   1344 
   1345     /**
   1346      * Update rules that might be changed by {@link #mRestrictBackground} value.
   1347      */
   1348     private void updateRulesForRestrictBackgroundLocked() {
   1349         // update rules for all installed applications
   1350         final PackageManager pm = mContext.getPackageManager();
   1351         final List<ApplicationInfo> apps = pm.getInstalledApplications(0);
   1352         for (ApplicationInfo app : apps) {
   1353             updateRulesForUidLocked(app.uid);
   1354         }
   1355 
   1356         // and catch system UIDs
   1357         // TODO: keep in sync with android_filesystem_config.h
   1358         for (int uid = 1000; uid <= 1025; uid++) {
   1359             updateRulesForUidLocked(uid);
   1360         }
   1361         for (int uid = 2000; uid <= 2002; uid++) {
   1362             updateRulesForUidLocked(uid);
   1363         }
   1364         for (int uid = 3000; uid <= 3007; uid++) {
   1365             updateRulesForUidLocked(uid);
   1366         }
   1367         for (int uid = 9998; uid <= 9999; uid++) {
   1368             updateRulesForUidLocked(uid);
   1369         }
   1370     }
   1371 
   1372     private void updateRulesForUidLocked(int uid) {
   1373         final int uidPolicy = getUidPolicy(uid);
   1374         final boolean uidForeground = isUidForeground(uid);
   1375 
   1376         // derive active rules based on policy and active state
   1377         int uidRules = RULE_ALLOW_ALL;
   1378         if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
   1379             // uid in background, and policy says to block metered data
   1380             uidRules = RULE_REJECT_METERED;
   1381         }
   1382         if (!uidForeground && mRestrictBackground) {
   1383             // uid in background, and global background disabled
   1384             uidRules = RULE_REJECT_METERED;
   1385         }
   1386 
   1387         // TODO: only dispatch when rules actually change
   1388 
   1389         if (uidRules == RULE_ALLOW_ALL) {
   1390             mUidRules.delete(uid);
   1391         } else {
   1392             mUidRules.put(uid, uidRules);
   1393         }
   1394 
   1395         final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
   1396         setUidNetworkRules(uid, rejectMetered);
   1397 
   1398         // dispatch changed rule to existing listeners
   1399         mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
   1400 
   1401         try {
   1402             // adjust stats accounting based on foreground status
   1403             mNetworkStats.setUidForeground(uid, uidForeground);
   1404         } catch (RemoteException e) {
   1405             // ignored; service lives in system_server
   1406         }
   1407     }
   1408 
   1409     private Handler.Callback mHandlerCallback = new Handler.Callback() {
   1410         /** {@inheritDoc} */
   1411         public boolean handleMessage(Message msg) {
   1412             switch (msg.what) {
   1413                 case MSG_RULES_CHANGED: {
   1414                     final int uid = msg.arg1;
   1415                     final int uidRules = msg.arg2;
   1416                     final int length = mListeners.beginBroadcast();
   1417                     for (int i = 0; i < length; i++) {
   1418                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
   1419                         if (listener != null) {
   1420                             try {
   1421                                 listener.onUidRulesChanged(uid, uidRules);
   1422                             } catch (RemoteException e) {
   1423                             }
   1424                         }
   1425                     }
   1426                     mListeners.finishBroadcast();
   1427                     return true;
   1428                 }
   1429                 case MSG_METERED_IFACES_CHANGED: {
   1430                     final String[] meteredIfaces = (String[]) msg.obj;
   1431                     final int length = mListeners.beginBroadcast();
   1432                     for (int i = 0; i < length; i++) {
   1433                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
   1434                         if (listener != null) {
   1435                             try {
   1436                                 listener.onMeteredIfacesChanged(meteredIfaces);
   1437                             } catch (RemoteException e) {
   1438                             }
   1439                         }
   1440                     }
   1441                     mListeners.finishBroadcast();
   1442                     return true;
   1443                 }
   1444                 case MSG_FOREGROUND_ACTIVITIES_CHANGED: {
   1445                     final int pid = msg.arg1;
   1446                     final int uid = msg.arg2;
   1447                     final boolean foregroundActivities = (Boolean) msg.obj;
   1448 
   1449                     synchronized (mRulesLock) {
   1450                         // because a uid can have multiple pids running inside, we need to
   1451                         // remember all pid states and summarize foreground at uid level.
   1452 
   1453                         // record foreground for this specific pid
   1454                         SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
   1455                         if (pidForeground == null) {
   1456                             pidForeground = new SparseBooleanArray(2);
   1457                             mUidPidForeground.put(uid, pidForeground);
   1458                         }
   1459                         pidForeground.put(pid, foregroundActivities);
   1460                         computeUidForegroundLocked(uid);
   1461                     }
   1462                     return true;
   1463                 }
   1464                 case MSG_PROCESS_DIED: {
   1465                     final int pid = msg.arg1;
   1466                     final int uid = msg.arg2;
   1467 
   1468                     synchronized (mRulesLock) {
   1469                         // clear records and recompute, when they exist
   1470                         final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
   1471                         if (pidForeground != null) {
   1472                             pidForeground.delete(pid);
   1473                             computeUidForegroundLocked(uid);
   1474                         }
   1475                     }
   1476                     return true;
   1477                 }
   1478                 case MSG_LIMIT_REACHED: {
   1479                     final String iface = (String) msg.obj;
   1480 
   1481                     maybeRefreshTrustedTime();
   1482                     synchronized (mRulesLock) {
   1483                         if (mMeteredIfaces.contains(iface)) {
   1484                             try {
   1485                                 // force stats update to make sure we have
   1486                                 // numbers that caused alert to trigger.
   1487                                 mNetworkStats.forceUpdate();
   1488                             } catch (RemoteException e) {
   1489                                 // ignored; service lives in system_server
   1490                             }
   1491 
   1492                             updateNetworkEnabledLocked();
   1493                             updateNotificationsLocked();
   1494                         }
   1495                     }
   1496                     return true;
   1497                 }
   1498                 default: {
   1499                     return false;
   1500                 }
   1501             }
   1502         }
   1503     };
   1504 
   1505     private void setInterfaceQuota(String iface, long quotaBytes) {
   1506         try {
   1507             mNetworkManager.setInterfaceQuota(iface, quotaBytes);
   1508         } catch (IllegalStateException e) {
   1509             Log.wtf(TAG, "problem setting interface quota", e);
   1510         } catch (RemoteException e) {
   1511             // ignored; service lives in system_server
   1512         }
   1513     }
   1514 
   1515     private void removeInterfaceQuota(String iface) {
   1516         try {
   1517             mNetworkManager.removeInterfaceQuota(iface);
   1518         } catch (IllegalStateException e) {
   1519             Log.wtf(TAG, "problem removing interface quota", e);
   1520         } catch (RemoteException e) {
   1521             // ignored; service lives in system_server
   1522         }
   1523     }
   1524 
   1525     private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
   1526         try {
   1527             mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
   1528         } catch (IllegalStateException e) {
   1529             Log.wtf(TAG, "problem setting uid rules", e);
   1530         } catch (RemoteException e) {
   1531             // ignored; service lives in system_server
   1532         }
   1533     }
   1534 
   1535     /**
   1536      * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}.
   1537      */
   1538     private void setPolicyDataEnable(int networkType, boolean enabled) {
   1539         try {
   1540             mConnManager.setPolicyDataEnable(networkType, enabled);
   1541         } catch (RemoteException e) {
   1542             // ignored; service lives in system_server
   1543         }
   1544     }
   1545 
   1546     private String getActiveSubscriberId() {
   1547         final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
   1548                 Context.TELEPHONY_SERVICE);
   1549         return telephony.getSubscriberId();
   1550     }
   1551 
   1552     private long getTotalBytes(NetworkTemplate template, long start, long end) {
   1553         try {
   1554             return mNetworkStats.getSummaryForNetwork(template, start, end).getTotalBytes();
   1555         } catch (RemoteException e) {
   1556             // ignored; service lives in system_server
   1557             return 0;
   1558         }
   1559     }
   1560 
   1561     /**
   1562      * Try refreshing {@link #mTime} when stale.
   1563      */
   1564     private void maybeRefreshTrustedTime() {
   1565         if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
   1566             mTime.forceRefresh();
   1567         }
   1568     }
   1569 
   1570     private long currentTimeMillis() {
   1571         return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
   1572     }
   1573 
   1574     private static Intent buildAllowBackgroundDataIntent() {
   1575         return new Intent(ACTION_ALLOW_BACKGROUND);
   1576     }
   1577 
   1578     private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
   1579         final Intent intent = new Intent();
   1580         intent.setComponent(new ComponentName(
   1581                 "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity"));
   1582         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   1583         intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
   1584         return intent;
   1585     }
   1586 
   1587     private static Intent buildViewDataUsageIntent(NetworkTemplate template) {
   1588         final Intent intent = new Intent();
   1589         intent.setComponent(new ComponentName(
   1590                 "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
   1591         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   1592         intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
   1593         return intent;
   1594     }
   1595 
   1596     // @VisibleForTesting
   1597     public void addIdleHandler(IdleHandler handler) {
   1598         mHandler.getLooper().getQueue().addIdleHandler(handler);
   1599     }
   1600 
   1601     private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
   1602         final int size = source.size();
   1603         for (int i = 0; i < size; i++) {
   1604             target.put(source.keyAt(i), true);
   1605         }
   1606     }
   1607 
   1608     private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) {
   1609         final int size = source.size();
   1610         for (int i = 0; i < size; i++) {
   1611             target.put(source.keyAt(i), true);
   1612         }
   1613     }
   1614 
   1615     private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) {
   1616         fout.print("[");
   1617         final int size = value.size();
   1618         for (int i = 0; i < size; i++) {
   1619             fout.print(value.keyAt(i) + "=" + value.valueAt(i));
   1620             if (i < size - 1) fout.print(",");
   1621         }
   1622         fout.print("]");
   1623     }
   1624 
   1625     public static class XmlUtils {
   1626         public static int readIntAttribute(XmlPullParser in, String name) throws IOException {
   1627             final String value = in.getAttributeValue(null, name);
   1628             try {
   1629                 return Integer.parseInt(value);
   1630             } catch (NumberFormatException e) {
   1631                 throw new ProtocolException("problem parsing " + name + "=" + value + " as int");
   1632             }
   1633         }
   1634 
   1635         public static void writeIntAttribute(XmlSerializer out, String name, int value)
   1636                 throws IOException {
   1637             out.attribute(null, name, Integer.toString(value));
   1638         }
   1639 
   1640         public static long readLongAttribute(XmlPullParser in, String name) throws IOException {
   1641             final String value = in.getAttributeValue(null, name);
   1642             try {
   1643                 return Long.parseLong(value);
   1644             } catch (NumberFormatException e) {
   1645                 throw new ProtocolException("problem parsing " + name + "=" + value + " as long");
   1646             }
   1647         }
   1648 
   1649         public static void writeLongAttribute(XmlSerializer out, String name, long value)
   1650                 throws IOException {
   1651             out.attribute(null, name, Long.toString(value));
   1652         }
   1653 
   1654         public static boolean readBooleanAttribute(XmlPullParser in, String name) {
   1655             final String value = in.getAttributeValue(null, name);
   1656             return Boolean.parseBoolean(value);
   1657         }
   1658 
   1659         public static void writeBooleanAttribute(XmlSerializer out, String name, boolean value)
   1660                 throws IOException {
   1661             out.attribute(null, name, Boolean.toString(value));
   1662         }
   1663     }
   1664 }
   1665