1d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/*
2d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project
3d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *
4d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * you may not use this file except in compliance with the License.
6d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * You may obtain a copy of the License at
7d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *
8d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey *
10d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * See the License for the specific language governing permissions and
14d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey * limitations under the License.
15d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */
16d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
17d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeypackage com.android.server.net;
18d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
19f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkeyimport static android.Manifest.permission.ACCESS_NETWORK_STATE;
2021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.CONNECTIVITY_INTERNAL;
211b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.Manifest.permission.DUMP;
2221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.MANAGE_NETWORK_POLICY;
23497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
2422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport static android.Manifest.permission.READ_PHONE_STATE;
257c5befa4a7ccd6e7e91ffdd93264b717259ec863Amit Mahajanimport static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
2602e21d6a5b5117d494777a36783909854854f751Jeff Sharkeyimport static android.content.Intent.ACTION_PACKAGE_ADDED;
27b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.ACTION_UID_REMOVED;
28d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkeyimport static android.content.Intent.ACTION_USER_ADDED;
29d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkeyimport static android.content.Intent.ACTION_USER_REMOVED;
30b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.EXTRA_UID;
31f851d6dd2a15b74f63c85403afad0ed747f7311cErik Klineimport static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
321b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_MOBILE;
338e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkeyimport static android.net.ConnectivityManager.TYPE_WIMAX;
349f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport static android.net.ConnectivityManager.isNetworkTypeMobile;
359f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport static android.net.NetworkPolicy.CYCLE_NONE;
3622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport static android.net.NetworkPolicy.LIMIT_DISABLED;
3741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkeyimport static android.net.NetworkPolicy.SNOOZE_NEVER;
38497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static android.net.NetworkPolicy.WARNING_DISABLED;
3914711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkeyimport static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
40b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chenimport static android.net.NetworkPolicyManager.FIREWALL_CHAIN_DOZABLE;
41b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chenimport static android.net.NetworkPolicyManager.FIREWALL_CHAIN_STANDBY;
424a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackbornimport static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
43b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chenimport static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW;
4415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasaniimport static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
45be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackbornimport static android.net.NetworkPolicyManager.POLICY_ALLOW_BACKGROUND_BATTERY_SAVE;
46eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_NONE;
47fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
48c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
49fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkeyimport static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
50cd2ca4038a027315832c38c68be5076000bc4b53Jeff Sharkeyimport static android.net.NetworkPolicyManager.computeLastCycleBoundary;
511b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpPolicy;
521b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport static android.net.NetworkPolicyManager.dumpRules;
531b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
541b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_4G;
558e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
568e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkeyimport static android.net.NetworkTemplate.MATCH_WIFI;
574e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateMobileAll;
58241dde2306202e7655fdf41d5381f2874e47e108Jeff Sharkeyimport static android.net.TrafficStats.MB_IN_BYTES;
599f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport static android.net.wifi.WifiManager.CHANGE_REASON_ADDED;
609f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport static android.net.wifi.WifiManager.CHANGE_REASON_REMOVED;
619f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport static android.net.wifi.WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION;
629f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport static android.net.wifi.WifiManager.EXTRA_CHANGE_REASON;
639f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport static android.net.wifi.WifiManager.EXTRA_NETWORK_INFO;
649f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport static android.net.wifi.WifiManager.EXTRA_WIFI_CONFIGURATION;
659f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport static android.net.wifi.WifiManager.EXTRA_WIFI_INFO;
6621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.text.format.DateUtils.DAY_IN_MILLIS;
67854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkeyimport static com.android.internal.util.ArrayUtils.appendInt;
6821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull;
69ded7b75d1a353856ad8f126d171d598d15b97760Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readBooleanAttribute;
70ded7b75d1a353856ad8f126d171d598d15b97760Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readIntAttribute;
71ded7b75d1a353856ad8f126d171d598d15b97760Jeff Sharkeyimport static com.android.internal.util.XmlUtils.readLongAttribute;
72ded7b75d1a353856ad8f126d171d598d15b97760Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeBooleanAttribute;
73ded7b75d1a353856ad8f126d171d598d15b97760Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeIntAttribute;
74ded7b75d1a353856ad8f126d171d598d15b97760Jeff Sharkeyimport static com.android.internal.util.XmlUtils.writeLongAttribute;
75961e30458319cfd50e1892ba7dd14a1d0ebe4cc7Jeff Sharkeyimport static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
76497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
7721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
7821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static org.xmlpull.v1.XmlPullParser.START_TAG;
79d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
8088e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackbornimport android.Manifest;
81497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackbornimport android.app.ActivityManager;
8288e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackbornimport android.app.AppGlobals;
8316a16899505ec0a9ede5b76650bfb8817b3227c7Svet Ganovimport android.app.AppOpsManager;
84a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.app.IActivityManager;
85497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.INotificationManager;
86d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackbornimport android.app.IUidObserver;
87497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.Notification;
88497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.app.PendingIntent;
8915e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasaniimport android.app.usage.UsageStatsManagerInternal;
90a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.BroadcastReceiver;
9141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkeyimport android.content.ComponentName;
92d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.content.Context;
93a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.Intent;
94a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.content.IntentFilter;
95b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.content.pm.ApplicationInfo;
9688e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackbornimport android.content.pm.IPackageManager;
97b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport android.content.pm.PackageManager;
9815e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasaniimport android.content.pm.PackageManager.NameNotFoundException;
998a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkeyimport android.content.pm.UserInfo;
100497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.content.res.Resources;
101c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.ConnectivityManager;
10221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.IConnectivityManager;
10341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkeyimport android.net.INetworkManagementEventObserver;
104c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.net.INetworkPolicyListener;
105d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.net.INetworkPolicyManager;
10675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.INetworkStatsService;
107eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkeyimport android.net.LinkProperties;
1081b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkIdentity;
1099f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport android.net.NetworkInfo;
11021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkPolicy;
111f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkeyimport android.net.NetworkQuotaInfo;
11221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.net.NetworkState;
1131b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkTemplate;
1149f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport android.net.wifi.WifiConfiguration;
1159f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport android.net.wifi.WifiInfo;
1169f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkeyimport android.net.wifi.WifiManager;
117f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkeyimport android.os.Binder;
11821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Environment;
11921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.os.Handler;
120450a16b33f5d58370d181a7539aa113779efa247Amith Yamasaniimport android.os.HandlerThread;
1210b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackbornimport android.os.IDeviceIdleController;
12250fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharmaimport android.os.INetworkManagementService;
123a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.IPowerManager;
1244414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkeyimport android.os.Message;
125163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport android.os.MessageQueue.IdleHandler;
1260b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackbornimport android.os.PowerManager;
127be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackbornimport android.os.PowerManagerInternal;
128c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkeyimport android.os.RemoteCallbackList;
129a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.os.RemoteException;
1300b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackbornimport android.os.ServiceManager;
131f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackbornimport android.os.UserHandle;
132258848d2ae04f447ff1c18023fa76b139fcc0862Amith Yamasaniimport android.os.UserManager;
1333a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkeyimport android.provider.Settings;
1343256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkeyimport android.telephony.SubscriptionManager;
13522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport android.telephony.TelephonyManager;
136497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport android.text.format.Formatter;
13722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkeyimport android.text.format.Time;
138be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackbornimport android.util.ArrayMap;
139be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackbornimport android.util.ArraySet;
14039606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile;
141b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkeyimport android.util.Log;
14221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.NtpTrustedTime;
143eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkeyimport android.util.Pair;
144a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkeyimport android.util.Slog;
145d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseBooleanArray;
146d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkeyimport android.util.SparseIntArray;
14721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.TrustedTime;
14821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport android.util.Xml;
149d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
150fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackbornimport com.android.server.DeviceIdleController;
1513b16cf4f47142a845bf0ede54ef8ef956506c6c3Dianne Hackbornimport com.android.server.EventLogTags;
1523256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkeyimport libcore.io.IoUtils;
1533256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
154497e4437af386930dff3bd55296d128bd4520959Jeff Sharkeyimport com.android.internal.R;
1558b2c3a14603d163d7564e6f60286995079687690Jeff Sharkeyimport com.android.internal.annotations.VisibleForTesting;
1563256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkeyimport com.android.internal.util.ArrayUtils;
15721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.android.internal.util.FastXmlSerializer;
1588fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkeyimport com.android.internal.util.IndentingPrintWriter;
159be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackbornimport com.android.server.LocalServices;
16021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport com.google.android.collect.Lists;
16121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
16221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParser;
16321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlPullParserException;
16421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport org.xmlpull.v1.XmlSerializer;
16521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
16621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.File;
1671b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.FileDescriptor;
16821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileInputStream;
16921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileNotFoundException;
17021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.FileOutputStream;
17121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.io.IOException;
1721b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkeyimport java.io.PrintWriter;
1739e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewiczimport java.nio.charset.StandardCharsets;
17421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.ArrayList;
17521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport java.util.Arrays;
176b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkeyimport java.util.List;
17721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
178d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey/**
1798e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * Service that maintains low-level network policy rules, using
1808e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey * {@link NetworkStatsService} statistics to drive those rules.
181c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * <p>
182c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * Derives active rules by combining a given policy with other system status,
183c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * and delivers to listeners, such as {@link ConnectivityManager}, for
184c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey * enforcement.
185d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey */
1868dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chenpublic class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
187d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    private static final String TAG = "NetworkPolicy";
188ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey    private static final boolean LOGD = false;
18922c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private static final boolean LOGV = false;
190d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
19141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static final int VERSION_INIT = 1;
19241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static final int VERSION_ADDED_SNOOZE = 2;
1934664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3;
194f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey    private static final int VERSION_ADDED_METERED = 4;
1950e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    private static final int VERSION_SPLIT_SNOOZE = 5;
1969bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey    private static final int VERSION_ADDED_TIMEZONE = 6;
197837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey    private static final int VERSION_ADDED_INFERRED = 7;
1988a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey    private static final int VERSION_SWITCH_APP_ID = 8;
1998fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    private static final int VERSION_ADDED_NETWORK_ID = 9;
200d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey    private static final int VERSION_SWITCH_UID = 10;
201d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey    private static final int VERSION_LATEST = VERSION_SWITCH_UID;
20221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
2038b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    @VisibleForTesting
20441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public static final int TYPE_WARNING = 0x1;
2058b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    @VisibleForTesting
20641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public static final int TYPE_LIMIT = 0x2;
2078b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    @VisibleForTesting
20841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    public static final int TYPE_LIMIT_SNOOZED = 0x3;
209497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
21021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_POLICY_LIST = "policy-list";
21121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_NETWORK_POLICY = "network-policy";
21221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG_UID_POLICY = "uid-policy";
2138a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey    private static final String TAG_APP_POLICY = "app-policy";
21421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
21521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_VERSION = "version";
2164664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
21721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
21821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
2198fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    private static final String ATTR_NETWORK_ID = "networkId";
22021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_CYCLE_DAY = "cycleDay";
2219bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey    private static final String ATTR_CYCLE_TIMEZONE = "cycleTimezone";
22221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_WARNING_BYTES = "warningBytes";
22321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_LIMIT_BYTES = "limitBytes";
22441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static final String ATTR_LAST_SNOOZE = "lastSnooze";
2250e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    private static final String ATTR_LAST_WARNING_SNOOZE = "lastWarningSnooze";
2260e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    private static final String ATTR_LAST_LIMIT_SNOOZE = "lastLimitSnooze";
227f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey    private static final String ATTR_METERED = "metered";
228837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey    private static final String ATTR_INFERRED = "inferred";
22921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_UID = "uid";
2308a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey    private static final String ATTR_APP_ID = "appId";
23121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String ATTR_POLICY = "policy";
23221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
2333a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey    private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground";
2343a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
2358b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    private static final String ACTION_ALLOW_BACKGROUND =
2360e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            "com.android.server.net.action.ALLOW_BACKGROUND";
2378b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    private static final String ACTION_SNOOZE_WARNING =
2380e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            "com.android.server.net.action.SNOOZE_WARNING";
2393a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
24021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
24121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
2426f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey    private static final int MSG_RULES_CHANGED = 1;
2436f7af03cf13f76f48e63937e13e4a1c508d100d6Jeff Sharkey    private static final int MSG_METERED_IFACES_CHANGED = 2;
2447e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey    private static final int MSG_LIMIT_REACHED = 5;
2451f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey    private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6;
246e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey    private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7;
2470abe556d28f5f5d395559cc6567b05939d1b2640Jeff Sharkey    private static final int MSG_SCREEN_ON_CHANGED = 8;
2484414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey
24975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Context mContext;
25075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IActivityManager mActivityManager;
25175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IPowerManager mPowerManager;
25275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final INetworkStatsService mNetworkStats;
25341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private final INetworkManagementService mNetworkManager;
25415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani    private UsageStatsManagerInternal mUsageStats;
25521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final TrustedTime mTime;
256e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott    private final UserManager mUserManager;
25721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
25821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private IConnectivityManager mConnManager;
259497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private INotificationManager mNotifManager;
260be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn    private PowerManagerInternal mPowerManagerInternal;
2610b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn    private IDeviceIdleController mDeviceIdleController;
262a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
263497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    final Object mRulesLock = new Object();
264a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
2658ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn    volatile boolean mSystemReady;
266497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    volatile boolean mScreenOn;
267497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    volatile boolean mRestrictBackground;
268497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    volatile boolean mRestrictPower;
2698ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn    volatile boolean mDeviceIdleMode;
270d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
2718e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    private final boolean mSuppressDefaultPolicy;
2728e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
27341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Defined network policies. */
2743256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    final ArrayMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = new ArrayMap<>();
27541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Currently active network rules for ifaces. */
2763256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    final ArrayMap<NetworkPolicy, String[]> mNetworkRules = new ArrayMap<>();
27722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
278d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey    /** Defined UID policies. */
279497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    final SparseIntArray mUidPolicy = new SparseIntArray();
28041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Currently derived rules for each UID. */
2813256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    final SparseIntArray mUidRules = new SparseIntArray();
2828dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen    /** Set of states for the child firewall chains. True if the chain is active. */
283b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen    final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
284be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
2853256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    /**
2863256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * UIDs that have been white-listed to always be able to have network access
2874a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn     * in power save mode, except device idle (doze) still applies.
2884a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn     * TODO: An int array might be sufficient
2894a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn     */
2904a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn    private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
2914a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn
2924a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn    /**
2934a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn     * UIDs that have been white-listed to always be able to have network access
2943256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * in power save mode.
295af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani     * TODO: An int array might be sufficient
2963256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     */
297be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn    private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();
298d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
299af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani    private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray();
300af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani
301fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey    /** Set of ifaces that are metered. */
3023256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    private ArraySet<String> mMeteredIfaces = new ArraySet<>();
30341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /** Set of over-limit templates that have been notified. */
3043256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    private final ArraySet<NetworkTemplate> mOverLimitNotified = new ArraySet<>();
305fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
3068e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    /** Set of currently active {@link Notification} tags. */
307497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    private final ArraySet<String> mActiveNotifs = new ArraySet<String>();
3088e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
309d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn    /** Foreground at UID granularity. */
3103256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    final SparseIntArray mUidState = new SparseIntArray();
311497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn
3123256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    private final RemoteCallbackList<INetworkPolicyListener>
3133256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            mListeners = new RemoteCallbackList<>();
314c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
315497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    final Handler mHandler;
31621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
31721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private final AtomicFile mPolicyFile;
318d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
31916a16899505ec0a9ede5b76650bfb8817b3227c7Svet Ganov    private final AppOpsManager mAppOps;
32016a16899505ec0a9ede5b76650bfb8817b3227c7Svet Ganov
321c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    // TODO: keep whitelist of system-critical services that should never have
322c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    // rules enforced, such as system, phone, and radio UIDs.
323c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
32441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    // TODO: migrate notifications to SystemUI
32541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
32675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
32750fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            IPowerManager powerManager, INetworkStatsService networkStats,
32850fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            INetworkManagementService networkManagement) {
329b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        this(context, activityManager, powerManager, networkStats, networkManagement,
3308e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                NtpTrustedTime.getInstance(context), getSystemDir(), false);
33121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
33221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
33321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static File getSystemDir() {
33421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        return new File(Environment.getDataDirectory(), "system");
33521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
33621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
33721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
33850fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            IPowerManager powerManager, INetworkStatsService networkStats,
3398e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            INetworkManagementService networkManagement, TrustedTime time, File systemDir,
3408e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            boolean suppressDefaultPolicy) {
341a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mContext = checkNotNull(context, "missing context");
342a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mActivityManager = checkNotNull(activityManager, "missing activityManager");
343a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        mPowerManager = checkNotNull(powerManager, "missing powerManager");
34475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mNetworkStats = checkNotNull(networkStats, "missing networkStats");
34541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
3460b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn        mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService(
3471958e5e7870579337f1d1d3e6c6fae096ba3abb9Dianne Hackborn                Context.DEVICE_IDLE_CONTROLLER));
34821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mTime = checkNotNull(time, "missing TrustedTime");
349e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott        mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
35021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
351450a16b33f5d58370d181a7539aa113779efa247Amith Yamasani        HandlerThread thread = new HandlerThread(TAG);
352450a16b33f5d58370d181a7539aa113779efa247Amith Yamasani        thread.start();
353450a16b33f5d58370d181a7539aa113779efa247Amith Yamasani        mHandler = new Handler(thread.getLooper(), mHandlerCallback);
35421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
3558e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        mSuppressDefaultPolicy = suppressDefaultPolicy;
3568e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
35721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
35816a16899505ec0a9ede5b76650bfb8817b3227c7Svet Ganov
35916a16899505ec0a9ede5b76650bfb8817b3227c7Svet Ganov        mAppOps = context.getSystemService(AppOpsManager.class);
36021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
36121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
36221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public void bindConnectivityManager(IConnectivityManager connManager) {
36321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
364a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
365d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
366497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    public void bindNotificationManager(INotificationManager notifManager) {
367497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
368497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
369497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
3700b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn    void updatePowerSaveWhitelistLocked() {
3710b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn        try {
3724a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            int[] whitelist = mDeviceIdleController.getAppIdWhitelistExceptIdle();
3734a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            mPowerSaveWhitelistExceptIdleAppIds.clear();
3744a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            if (whitelist != null) {
3754a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                for (int uid : whitelist) {
3764a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                    mPowerSaveWhitelistExceptIdleAppIds.put(uid, true);
3774a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                }
3784a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            }
3794a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            whitelist = mDeviceIdleController.getAppIdWhitelist();
3800b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn            mPowerSaveWhitelistAppIds.clear();
3810b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn            if (whitelist != null) {
3820b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn                for (int uid : whitelist) {
3830b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn                    mPowerSaveWhitelistAppIds.put(uid, true);
3840b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn                }
3850b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn            }
3860b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn        } catch (RemoteException e) {
3870b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn        }
3880b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn    }
3890b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn
390af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani    void updatePowerSaveTempWhitelistLocked() {
391af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani        try {
39206f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani            // Clear the states of the current whitelist
39306f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani            final int N = mPowerSaveTempWhitelistAppIds.size();
39406f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani            for (int i = 0; i < N; i++) {
39506f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani                mPowerSaveTempWhitelistAppIds.setValueAt(i, false);
39606f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani            }
39706f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani            // Update the states with the new whitelist
398af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani            final int[] whitelist = mDeviceIdleController.getAppIdTempWhitelist();
399af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani            if (whitelist != null) {
400af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani                for (int uid : whitelist) {
401af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani                    mPowerSaveTempWhitelistAppIds.put(uid, true);
402af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani                }
403af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani            }
404af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani        } catch (RemoteException e) {
405af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani        }
406af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani    }
407af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani
40806f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani    /**
40906f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani     * Remove unnecessary entries in the temp whitelist
41006f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani     */
41106f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani    void purgePowerSaveTempWhitelistLocked() {
41206f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani        final int N = mPowerSaveTempWhitelistAppIds.size();
41306f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani        for (int i = N - 1; i >= 0; i--) {
41406f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani            if (mPowerSaveTempWhitelistAppIds.valueAt(i) == false) {
41506f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani                mPowerSaveTempWhitelistAppIds.removeAt(i);
41606f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani            }
41706f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani        }
41806f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani    }
41906f0806bd54e907f3d6d2069d263c700bd91260cAmith Yamasani
420a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    public void systemReady() {
4218c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey        if (!isBandwidthControlEnabled()) {
4228c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey            Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy");
4238c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey            return;
4248c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey        }
4258c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey
42615e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
42715e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani
42821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
4290b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn            updatePowerSaveWhitelistLocked();
430be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
431be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            mPowerManagerInternal.registerLowPowerModeObserver(
432be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    new PowerManagerInternal.LowPowerModeListener() {
433be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                @Override
434be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                public void onLowPowerModeChanged(boolean enabled) {
435be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    synchronized (mRulesLock) {
436be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                        if (mRestrictPower != enabled) {
437be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                            mRestrictPower = enabled;
438be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                            updateRulesForGlobalChangeLocked(true);
439be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                        }
440be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    }
441be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                }
442be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            });
443be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled();
4448ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn            mSystemReady = true;
445be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
44621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // read policy from disk
44721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            readPolicyLocked();
4484664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey
4498ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn            if (mRestrictBackground || mRestrictPower || mDeviceIdleMode) {
4504a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                updateRulesForGlobalChangeLocked(false);
4513a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey                updateNotificationsLocked();
4524a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            } else {
4534a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                // If we are not in any special mode, we just need to make sure the current
4544a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                // app idle state is updated.
4554a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                updateRulesForAppIdleLocked();
4564664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            }
45721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
458d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
459a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        updateScreenOn();
460d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
461a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        try {
462d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn            mActivityManager.registerUidObserver(mUidObserver);
46341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.registerObserver(mAlertObserver);
46441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        } catch (RemoteException e) {
465b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; both services live in system_server
46641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
46741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
468a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // TODO: traverse existing processes to know foreground state, or have
469a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // activitymanager dispatch current state when new observer attached.
470d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
471a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        final IntentFilter screenFilter = new IntentFilter();
472a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        screenFilter.addAction(Intent.ACTION_SCREEN_ON);
473a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
4740abe556d28f5f5d395559cc6567b05939d1b2640Jeff Sharkey        mContext.registerReceiver(mScreenReceiver, screenFilter);
475d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
4760b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn        // listen for changes to power save whitelist
4770b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn        final IntentFilter whitelistFilter = new IntentFilter(
4780b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn                PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
4790b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn        mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler);
4800b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn
481fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn        DeviceIdleController.LocalService deviceIdleService
482fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                = LocalServices.getService(DeviceIdleController.LocalService.class);
483fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn        deviceIdleService.setNetworkPolicyTempWhitelistCallback(mTempPowerSaveChangedCallback);
484fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn
48521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // watch for network interfaces to be claimed
486f851d6dd2a15b74f63c85403afad0ed747f7311cErik Kline        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION);
487b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
488b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
489d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        // listen for package changes to update policy
49002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        final IntentFilter packageFilter = new IntentFilter();
49102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        packageFilter.addAction(ACTION_PACKAGE_ADDED);
492d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        packageFilter.addDataScheme("package");
49302e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
49421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
495d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        // listen for UID changes to update policy
496d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        mContext.registerReceiver(
497d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                mUidRemovedReceiver, new IntentFilter(ACTION_UID_REMOVED), null, mHandler);
498d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey
499d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        // listen for user changes to update policy
500d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        final IntentFilter userFilter = new IntentFilter();
501d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        userFilter.addAction(ACTION_USER_ADDED);
502d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        userFilter.addAction(ACTION_USER_REMOVED);
503d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
504d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey
505b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // listen for stats update events
506497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
507497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        mContext.registerReceiver(
508497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
509497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
5103a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        // listen for restrict background changes from notifications
5113a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
5123a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler);
5133a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
5140e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        // listen for snooze warning from notifications
5150e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        final IntentFilter snoozeWarningFilter = new IntentFilter(ACTION_SNOOZE_WARNING);
5160e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        mContext.registerReceiver(mSnoozeWarningReceiver, snoozeWarningFilter,
5170e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                MANAGE_NETWORK_POLICY, mHandler);
5180e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey
5199f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey        // listen for configured wifi networks to be removed
5209f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey        final IntentFilter wifiConfigFilter = new IntentFilter(CONFIGURED_NETWORKS_CHANGED_ACTION);
52192d141fbc2f6bfc85dca1056e40512cba6d1dddbVinit Deshpande        mContext.registerReceiver(mWifiConfigReceiver, wifiConfigFilter, null, mHandler);
5229f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey
5239f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey        // listen for wifi state changes to catch metered hint
5249f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey        final IntentFilter wifiStateFilter = new IntentFilter(
5259f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                WifiManager.NETWORK_STATE_CHANGED_ACTION);
52692d141fbc2f6bfc85dca1056e40512cba6d1dddbVinit Deshpande        mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler);
5279f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey
5288dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen        mUsageStats.addAppIdleStateChangeListener(new AppIdleStateChangeListener());
52915e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani
530a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
531d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
532fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private IUidObserver mUidObserver = new IUidObserver.Stub() {
533d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn        @Override public void onUidStateChanged(int uid, int procState) throws RemoteException {
534497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn            synchronized (mRulesLock) {
535d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn                updateUidStateLocked(uid, procState);
536497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn            }
537a93c2c117d502ee57dd27705a0b5efca4bf65011Dianne Hackborn        }
538a93c2c117d502ee57dd27705a0b5efca4bf65011Dianne Hackborn
539d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn        @Override public void onUidGone(int uid) throws RemoteException {
540497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn            synchronized (mRulesLock) {
541d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn                removeUidStateLocked(uid);
542497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn            }
543a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
544a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    };
545a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
546fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() {
5470b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn        @Override
5480b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn        public void onReceive(Context context, Intent intent) {
5490b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn            // on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
5500b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn            synchronized (mRulesLock) {
551fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                updatePowerSaveWhitelistLocked();
552fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                updateRulesForGlobalChangeLocked(false);
5530b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn            }
5540b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn        }
5550b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn    };
5560b4daca9ba54b7252ea8c159218391380eb00c8aDianne Hackborn
557fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private Runnable mTempPowerSaveChangedCallback = new Runnable() {
558fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn        @Override
559fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn        public void run() {
560fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn            synchronized (mRulesLock) {
561fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                updatePowerSaveTempWhitelistLocked();
562fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                updateRulesForTempWhitelistChangeLocked();
563fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                purgePowerSaveTempWhitelistLocked();
564fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn            }
565fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn        }
566fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    };
567fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn
568fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
569a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        @Override
570a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        public void onReceive(Context context, Intent intent) {
57129afa142402b4b4f5e56f36b24367b84b5f64a6aJeff Sharkey            // screen-related broadcasts are protected by system, no need
57229afa142402b4b4f5e56f36b24367b84b5f64a6aJeff Sharkey            // for permissions check.
57329afa142402b4b4f5e56f36b24367b84b5f64a6aJeff Sharkey            mHandler.obtainMessage(MSG_SCREEN_ON_CHANGED).sendToTarget();
574a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
575a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    };
576d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
577fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
578b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        @Override
579b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        public void onReceive(Context context, Intent intent) {
580d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            // on background handler thread, and PACKAGE_ADDED is protected
58102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey
58202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            final String action = intent.getAction();
583d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            final int uid = intent.getIntExtra(EXTRA_UID, -1);
584d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            if (uid == -1) return;
585d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey
586d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            if (ACTION_PACKAGE_ADDED.equals(action)) {
587d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                // update rules for UID, since it might be subject to
588d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                // global background data policy
589d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
590d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                synchronized (mRulesLock) {
591d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                    updateRulesForUidLocked(uid);
592d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                }
593d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            }
594d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        }
595d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey    };
596d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey
597fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private BroadcastReceiver mUidRemovedReceiver = new BroadcastReceiver() {
598d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        @Override
599d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        public void onReceive(Context context, Intent intent) {
600d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            // on background handler thread, and UID_REMOVED is protected
601d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey
602d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            final int uid = intent.getIntExtra(EXTRA_UID, -1);
603d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            if (uid == -1) return;
604d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey
605d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            // remove any policy and update rules to clean up
606d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
607b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            synchronized (mRulesLock) {
608d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                mUidPolicy.delete(uid);
609d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                updateRulesForUidLocked(uid);
610d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                writePolicyLocked();
611d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            }
612d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        }
613d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey    };
6148a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey
615fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
616d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        @Override
617d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        public void onReceive(Context context, Intent intent) {
618d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            // on background handler thread, and USER_ADDED and USER_REMOVED
619d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            // broadcasts are protected
62002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey
621d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            final String action = intent.getAction();
622d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
623d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            if (userId == -1) return;
6248a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey
62515e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani            switch (action) {
62615e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani                case ACTION_USER_REMOVED:
62715e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani                case ACTION_USER_ADDED:
62815e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani                    synchronized (mRulesLock) {
62915e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani                        // Remove any policies for given user; both cleaning up after a
63015e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani                        // USER_REMOVED, and one last sanity check during USER_ADDED
63115e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani                        removePoliciesForUserLocked(userId);
63215e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani                        // Update global restrict for new user
63315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani                        updateRulesForGlobalChangeLocked(true);
63415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani                    }
63515e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani                    break;
636b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            }
637b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        }
638b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    };
639b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
64021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /**
641497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Receiver that watches for {@link INetworkStatsService} updates, which we
642497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * use to check against {@link NetworkPolicy#warningBytes}.
643497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
644fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
645497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        @Override
646497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        public void onReceive(Context context, Intent intent) {
647497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            // on background handler thread, and verified
648497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            // READ_NETWORK_USAGE_HISTORY permission above.
649497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
650684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey            maybeRefreshTrustedTime();
651497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            synchronized (mRulesLock) {
6528e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                updateNetworkEnabledLocked();
653497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                updateNotificationsLocked();
654497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
655497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
656497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    };
657497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
658497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
6593a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey     * Receiver that watches for {@link Notification} control of
6603a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey     * {@link #mRestrictBackground}.
6613a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey     */
662fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() {
6633a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        @Override
6643a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        public void onReceive(Context context, Intent intent) {
6653a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey            // on background handler thread, and verified MANAGE_NETWORK_POLICY
6663a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey            // permission above.
6673a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
6683a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey            setRestrictBackground(false);
6693a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        }
6703a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey    };
6713a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
6723a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey    /**
6730e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey     * Receiver that watches for {@link Notification} control of
6740e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey     * {@link NetworkPolicy#lastWarningSnooze}.
6750e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey     */
676fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() {
6770e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        @Override
6780e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        public void onReceive(Context context, Intent intent) {
6790e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            // on background handler thread, and verified MANAGE_NETWORK_POLICY
6800e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            // permission above.
6810e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey
6820e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            final NetworkTemplate template = intent.getParcelableExtra(EXTRA_NETWORK_TEMPLATE);
6830e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            performSnooze(template, TYPE_WARNING);
6840e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        }
6850e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    };
6860e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey
6870e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    /**
6889f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey     * Receiver that watches for {@link WifiConfiguration} to be changed.
6899f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey     */
690fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private BroadcastReceiver mWifiConfigReceiver = new BroadcastReceiver() {
6919f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey        @Override
6929f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey        public void onReceive(Context context, Intent intent) {
6939f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
6949f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            // permission above.
6959f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey
6969f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            final int reason = intent.getIntExtra(EXTRA_CHANGE_REASON, CHANGE_REASON_ADDED);
6979f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            if (reason == CHANGE_REASON_REMOVED) {
6989f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                final WifiConfiguration config = intent.getParcelableExtra(
6999f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                        EXTRA_WIFI_CONFIGURATION);
70000a10a1494954d124e1b11bc1ba3128e47b8ffbdIrfan Sheriff                if (config.SSID != null) {
7012e4dce0dd24aa89ca6adf6559f13d3e342ff8558Jeff Sharkey                    final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(config.SSID);
70200a10a1494954d124e1b11bc1ba3128e47b8ffbdIrfan Sheriff                    synchronized (mRulesLock) {
70300a10a1494954d124e1b11bc1ba3128e47b8ffbdIrfan Sheriff                        if (mNetworkPolicy.containsKey(template)) {
70400a10a1494954d124e1b11bc1ba3128e47b8ffbdIrfan Sheriff                            mNetworkPolicy.remove(template);
70500a10a1494954d124e1b11bc1ba3128e47b8ffbdIrfan Sheriff                            writePolicyLocked();
70600a10a1494954d124e1b11bc1ba3128e47b8ffbdIrfan Sheriff                        }
7079f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                    }
7089f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                }
7099f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            }
7109f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey        }
7119f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey    };
7129f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey
7139f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey    /**
7149f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey     * Receiver that watches {@link WifiInfo} state changes to infer metered
7159f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey     * state. Ignores hints when policy is user-defined.
7169f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey     */
717fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
7189f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey        @Override
7199f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey        public void onReceive(Context context, Intent intent) {
7209f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
7219f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            // permission above.
7229f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey
7239f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            // ignore when not connected
7249f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            final NetworkInfo netInfo = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
7259f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            if (!netInfo.isConnected()) return;
7269f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey
7279f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            final WifiInfo info = intent.getParcelableExtra(EXTRA_WIFI_INFO);
7289f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            final boolean meteredHint = info.getMeteredHint();
7299f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey
7302e4dce0dd24aa89ca6adf6559f13d3e342ff8558Jeff Sharkey            final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(info.getSSID());
7319f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            synchronized (mRulesLock) {
7329f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                NetworkPolicy policy = mNetworkPolicy.get(template);
7339f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                if (policy == null && meteredHint) {
7349f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                    // policy doesn't exist, and AP is hinting that it's
7359f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                    // metered: create an inferred policy.
7369f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                    policy = new NetworkPolicy(template, CYCLE_NONE, Time.TIMEZONE_UTC,
7379f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                            WARNING_DISABLED, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER,
7389f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                            meteredHint, true);
7399f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                    addNetworkPolicyLocked(policy);
7409f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey
7419f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                } else if (policy != null && policy.inferred) {
7429f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                    // policy exists, and was inferred: update its current
7439f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                    // metered state.
7449f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                    policy.metered = meteredHint;
7459f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey
7469f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                    // since this is inferred for each wifi session, just update
7479f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                    // rules without persisting.
7489f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                    updateNetworkRulesLocked();
7499f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                }
7509f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            }
7519f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey        }
7529f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey    };
7539f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey
7549f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey    /**
75541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     * Observer that watches for {@link INetworkManagementService} alerts.
75641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     */
757fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    final private INetworkManagementEventObserver mAlertObserver
758fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn            = new BaseNetworkObserver() {
75941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        @Override
76041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        public void limitReached(String limitName, String iface) {
76141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            // only someone like NMS should be calling us
76241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
76341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
7647e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey            if (!LIMIT_GLOBAL_ALERT.equals(limitName)) {
7657e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                mHandler.obtainMessage(MSG_LIMIT_REACHED, iface).sendToTarget();
76641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
76741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
76841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    };
76941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
77041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /**
771497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
772497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * to show visible notifications as needed.
773497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
774497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    void updateNotificationsLocked() {
775497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
776497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
7778e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        // keep track of previously active notifications
778497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        final ArraySet<String> beforeNotifs = new ArraySet<String>(mActiveNotifs);
7798e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        mActiveNotifs.clear();
780497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
781497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // TODO: when switching to kernel notifications, compute next future
782497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // cycle boundary to recompute notifications.
783497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
78402e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        // examine stats for each active policy
785684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey        final long currentTime = currentTimeMillis();
786be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
787be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
7888e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            // ignore policies that aren't relevant to user
7898e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            if (!isTemplateRelevant(policy.template)) continue;
7908fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            if (!policy.hasCycle()) continue;
7918e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
792497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final long start = computeLastCycleBoundary(currentTime, policy);
793497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final long end = currentTime;
7948e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            final long totalBytes = getTotalBytes(policy.template, start, end);
795497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
79650e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey            if (policy.isOverLimit(totalBytes)) {
7970e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                if (policy.lastLimitSnooze >= start) {
79841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
79941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                } else {
80041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    enqueueNotification(policy, TYPE_LIMIT, totalBytes);
80141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    notifyOverLimitLocked(policy.template);
80241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
80341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
804497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            } else {
80541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                notifyUnderLimitLocked(policy.template);
806497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
8070e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) {
80841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    enqueueNotification(policy, TYPE_WARNING, totalBytes);
809497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                }
810497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
81102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        }
81202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey
8133a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        // ongoing notification when restricting background data
8143a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        if (mRestrictBackground) {
8153a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey            enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND);
8163a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        }
8178e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
8188e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        // cancel stale notifications that we didn't renew above
819497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        for (int i = beforeNotifs.size()-1; i >= 0; i--) {
820497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn            final String tag = beforeNotifs.valueAt(i);
8218e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            if (!mActiveNotifs.contains(tag)) {
8228e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                cancelNotification(tag);
8238e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            }
8248e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        }
8258e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    }
8268e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
8278e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    /**
8288e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey     * Test if given {@link NetworkTemplate} is relevant to user based on
8298fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * current device state, such as when
8308fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * {@link TelephonyManager#getSubscriberId()} matches. This is regardless of
8318fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey     * data connection status.
8328e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey     */
8338e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    private boolean isTemplateRelevant(NetworkTemplate template) {
8343256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        if (template.isMatchRuleMobile()) {
8353256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            final TelephonyManager tele = TelephonyManager.from(mContext);
8363256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            final SubscriptionManager sub = SubscriptionManager.from(mContext);
8373256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
8383256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            // Mobile template is relevant when any active subscriber matches
8393256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            final int[] subIds = sub.getActiveSubscriptionIdList();
8403256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            for (int subId : subIds) {
8413256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                final String subscriberId = tele.getSubscriberId(subId);
8423256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
8433256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                        TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
8443256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                if (template.matches(probeIdent)) {
8453256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                    return true;
8463a66cf3e86f351f0957188a4b874a3e65edfa40fJeff Sharkey                }
8473256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            }
8483256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            return false;
8493256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        } else {
8503256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            return true;
8518e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        }
852497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
853497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
854497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
85541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     * Notify that given {@link NetworkTemplate} is over
85641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
85741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey     */
85841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void notifyOverLimitLocked(NetworkTemplate template) {
85941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        if (!mOverLimitNotified.contains(template)) {
86041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mContext.startActivity(buildNetworkOverLimitIntent(template));
86141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mOverLimitNotified.add(template);
86241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
86341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
86441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
86541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void notifyUnderLimitLocked(NetworkTemplate template) {
86641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mOverLimitNotified.remove(template);
86741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
86841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
86941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    /**
870497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Build unique tag that identifies an active {@link NetworkPolicy}
871497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * notification of a specific type, like {@link #TYPE_LIMIT}.
872497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
873497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    private String buildNotificationTag(NetworkPolicy policy, int type) {
8741b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return TAG + ":" + policy.template.hashCode() + ":" + type;
875497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
876497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
877497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
878497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * Show notification for combined {@link NetworkPolicy} and specific type,
879497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     * like {@link #TYPE_LIMIT}. Okay to call multiple times.
880497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey     */
88141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
882497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final String tag = buildNotificationTag(policy, type);
883497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final Notification.Builder builder = new Notification.Builder(mContext);
884497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        builder.setOnlyAlertOnce(true);
8850e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        builder.setWhen(0L);
8864a357cd2e55293402d7172766f7f9419815fc1e8Alan Viverette        builder.setColor(mContext.getColor(
887255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek                com.android.internal.R.color.system_notification_accent_color));
888497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
889497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final Resources res = mContext.getResources();
890497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        switch (type) {
891497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            case TYPE_WARNING: {
89241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence title = res.getText(R.string.data_usage_warning_title);
8938ca953da93eb8679574abba535f75f72d50016f2Jeff Sharkey                final CharSequence body = res.getString(R.string.data_usage_warning_body);
894497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
89550e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey                builder.setSmallIcon(R.drawable.stat_notify_error);
896497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setTicker(title);
897497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentTitle(title);
898497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentText(body);
89914711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey
9000e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template);
9010e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                builder.setDeleteIntent(PendingIntent.getBroadcast(
9020e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                        mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
9030e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey
9040e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                final Intent viewIntent = buildViewDataUsageIntent(policy.template);
90514711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey                builder.setContentIntent(PendingIntent.getActivity(
9060e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                        mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT));
9070e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey
908497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                break;
909497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
910497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            case TYPE_LIMIT: {
91141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence body = res.getText(R.string.data_usage_limit_body);
91241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
91341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence title;
914aedebda776ee3a68eda498a79bf14855e5f5d62eJohn Spurlock                int icon = R.drawable.stat_notify_disabled_data;
9151b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                switch (policy.template.getMatchRule()) {
9161b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    case MATCH_MOBILE_3G_LOWER:
91741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_3g_limit_title);
918497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        break;
9191b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    case MATCH_MOBILE_4G:
92041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_4g_limit_title);
921497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        break;
9228e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    case MATCH_MOBILE_ALL:
92341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_mobile_limit_title);
924497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        break;
9258e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    case MATCH_WIFI:
9268e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                        title = res.getText(R.string.data_usage_wifi_limit_title);
927aedebda776ee3a68eda498a79bf14855e5f5d62eJohn Spurlock                        icon = R.drawable.stat_notify_error;
9288e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                        break;
9298e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    default:
9308e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                        title = null;
9318e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                        break;
932497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                }
933497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
9340e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                builder.setOngoing(true);
935aedebda776ee3a68eda498a79bf14855e5f5d62eJohn Spurlock                builder.setSmallIcon(icon);
936497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setTicker(title);
937497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentTitle(title);
938497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                builder.setContentText(body);
93914711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey
94041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final Intent intent = buildNetworkOverLimitIntent(policy.template);
94141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setContentIntent(PendingIntent.getActivity(
94241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
94341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                break;
94441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
94541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            case TYPE_LIMIT_SNOOZED: {
94641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final long overBytes = totalBytes - policy.limitBytes;
94741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body,
94841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        Formatter.formatFileSize(mContext, overBytes));
94941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
95041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final CharSequence title;
95141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                switch (policy.template.getMatchRule()) {
95241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    case MATCH_MOBILE_3G_LOWER:
95341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_3g_limit_snoozed_title);
95441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        break;
95541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                    case MATCH_MOBILE_4G:
95641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
95741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        break;
9588e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    case MATCH_MOBILE_ALL:
95941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
96041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        break;
9618e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    case MATCH_WIFI:
9628e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                        title = res.getText(R.string.data_usage_wifi_limit_snoozed_title);
9638e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                        break;
9648e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    default:
9658e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                        title = null;
9668e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                        break;
96741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
96841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
9690e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                builder.setOngoing(true);
97050e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey                builder.setSmallIcon(R.drawable.stat_notify_error);
97141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setTicker(title);
97241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setContentTitle(title);
97341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                builder.setContentText(body);
97441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
97541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                final Intent intent = buildViewDataUsageIntent(policy.template);
97614711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey                builder.setContentIntent(PendingIntent.getActivity(
97714711eb5b6a45b587222ae71c57a381beb7b1a7eJeff Sharkey                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
978497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                break;
979497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
980497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
981497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
982497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // TODO: move to NotificationManager once we can mock it
9834120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        // XXX what to do about multi-user?
984497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        try {
985497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final String packageName = mContext.getPackageName();
986497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final int[] idReceived = new int[1];
987497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            mNotifManager.enqueueNotificationWithTag(
988f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                    packageName, packageName, tag, 0x0, builder.getNotification(), idReceived,
9894120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                    UserHandle.USER_OWNER);
9908e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            mActiveNotifs.add(tag);
991497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        } catch (RemoteException e) {
992b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
993497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
994497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
995497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
996497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
9973a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey     * Show ongoing notification to reflect that {@link #mRestrictBackground}
9983a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey     * has been enabled.
9993a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey     */
10003a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey    private void enqueueRestrictedNotification(String tag) {
10013a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        final Resources res = mContext.getResources();
10023a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        final Notification.Builder builder = new Notification.Builder(mContext);
10033a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
10043a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        final CharSequence title = res.getText(R.string.data_usage_restricted_title);
10053a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        final CharSequence body = res.getString(R.string.data_usage_restricted_body);
10063a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
10073a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        builder.setOnlyAlertOnce(true);
10083a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        builder.setOngoing(true);
100950e7e51d68e3b01c3362fe9ab7b3448132e48b43Jeff Sharkey        builder.setSmallIcon(R.drawable.stat_notify_error);
10103a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        builder.setTicker(title);
10113a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        builder.setContentTitle(title);
10123a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        builder.setContentText(body);
10134a357cd2e55293402d7172766f7f9419815fc1e8Alan Viverette        builder.setColor(mContext.getColor(
1014255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek                com.android.internal.R.color.system_notification_accent_color));
10153a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
10163a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        final Intent intent = buildAllowBackgroundDataIntent();
10173a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        builder.setContentIntent(
10183a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey                PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
10193a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
10203a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        // TODO: move to NotificationManager once we can mock it
10214120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        // XXX what to do about multi-user?
10223a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        try {
10233a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey            final String packageName = mContext.getPackageName();
10243a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey            final int[] idReceived = new int[1];
1025f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            mNotifManager.enqueueNotificationWithTag(packageName, packageName, tag,
10264120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                    0x0, builder.getNotification(), idReceived, UserHandle.USER_OWNER);
10278e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            mActiveNotifs.add(tag);
10283a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        } catch (RemoteException e) {
1029b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
10303a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        }
10313a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey    }
10323a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
10333a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey    private void cancelNotification(String tag) {
1034497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // TODO: move to NotificationManager once we can mock it
10354120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn        // XXX what to do about multi-user?
1036497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        try {
1037497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            final String packageName = mContext.getPackageName();
10383a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey            mNotifManager.cancelNotificationWithTag(
10394120375d46091df8527bb701882e056fbb0e6b06Dianne Hackborn                    packageName, tag, 0x0, UserHandle.USER_OWNER);
1040497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        } catch (RemoteException e) {
1041b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
1042497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
1043497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
1044497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
1045497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    /**
104621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * Receiver that watches for {@link IConnectivityManager} to claim network
104722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     * interfaces. Used to apply {@link NetworkPolicy} to matching networks.
104821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     */
1049b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
105021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        @Override
105121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        public void onReceive(Context context, Intent intent) {
105221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
105321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // permission above.
1054684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey
1055684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey            maybeRefreshTrustedTime();
105621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            synchronized (mRulesLock) {
105722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                ensureActiveMobilePolicyLocked();
10583256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                normalizePoliciesLocked();
10598e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                updateNetworkEnabledLocked();
106002e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                updateNetworkRulesLocked();
106102e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                updateNotificationsLocked();
106221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
106321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
106421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    };
106521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
106621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    /**
10678e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey     * Proactively control network data connections when they exceed
10688e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey     * {@link NetworkPolicy#limitBytes}.
10698e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey     */
1070497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    void updateNetworkEnabledLocked() {
10718e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()");
10728e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
10738e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        // TODO: reset any policy-disabled networks when any policy is removed
10748e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        // completely, which is currently rare case.
10758e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
1076684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey        final long currentTime = currentTimeMillis();
1077be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
1078be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
10798e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            // shortcut when policy has no limit
10808fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            if (policy.limitBytes == LIMIT_DISABLED || !policy.hasCycle()) {
10818e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                setNetworkTemplateEnabled(policy.template, true);
10828e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                continue;
10838e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            }
10848e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
10858e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            final long start = computeLastCycleBoundary(currentTime, policy);
10868e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            final long end = currentTime;
10878e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            final long totalBytes = getTotalBytes(policy.template, start, end);
10888e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
10898e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            // disable data connection when over limit and not snoozed
10900e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            final boolean overLimitWithoutSnooze = policy.isOverLimit(totalBytes)
10910e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                    && policy.lastLimitSnooze < start;
10920e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            final boolean networkEnabled = !overLimitWithoutSnooze;
10938e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
10940e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            setNetworkTemplateEnabled(policy.template, networkEnabled);
10958e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        }
10968e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    }
10978e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
10988e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    /**
10993256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * Proactively disable networks that match the given
11003256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey     * {@link NetworkTemplate}.
11018e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey     */
11028e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
11033256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        // TODO: reach into ConnectivityManager to proactively disable bringing
11043256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        // up this network, since we know that traffic will be blocked.
11058e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    }
11068e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
11078e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    /**
110821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * Examine all connected {@link NetworkState}, looking for
110921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * {@link NetworkPolicy} that need to be enforced. When matches found, set
111021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     * remaining quota based on usage cycle and historical stats.
111121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey     */
1112497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    void updateNetworkRulesLocked() {
11133256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        if (LOGV) Slog.v(TAG, "updateNetworkRulesLocked()");
111421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
111521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final NetworkState[] states;
111621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
111721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            states = mConnManager.getAllNetworkState();
111821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (RemoteException e) {
1119b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
112021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return;
112121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
112221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1123be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        // If we are in restrict power mode, we want to treat all interfaces
1124be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        // as metered, to restrict access to the network by uid.  However, we
1125be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        // will not have a bandwidth limit.  Also only do this if restrict
1126be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        // background data use is *not* enabled, since that takes precendence
1127be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        // use over those networks can have a cost associated with it).
1128b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        final boolean powerSave = mRestrictPower && !mRestrictBackground;
1129be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
1130eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey        // First, generate identities of all connected networks so we can
1131eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey        // quickly compare them against all defined policies below.
1132eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey        final ArrayList<Pair<String, NetworkIdentity>> connIdents = new ArrayList<>(states.length);
1133497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        final ArraySet<String> connIfaces = new ArraySet<String>(states.length);
113421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        for (NetworkState state : states) {
113521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (state.networkInfo.isConnected()) {
113621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
1137eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey
1138eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey                final String baseIface = state.linkProperties.getInterfaceName();
11399da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkey                if (baseIface != null) {
11409da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkey                    connIdents.add(Pair.create(baseIface, ident));
11419da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkey                    if (powerSave) {
11429da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkey                        connIfaces.add(baseIface);
11439da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkey                    }
1144eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey                }
1145eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey
1146eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey                // Stacked interfaces are considered to have same identity as
1147eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey                // their parent network.
1148eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey                final List<LinkProperties> stackedLinks = state.linkProperties.getStackedLinks();
1149eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey                for (LinkProperties stackedLink : stackedLinks) {
1150eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey                    final String stackedIface = stackedLink.getInterfaceName();
11519da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkey                    if (stackedIface != null) {
11529da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkey                        connIdents.add(Pair.create(stackedIface, ident));
11539da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkey                        if (powerSave) {
11549da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkey                            connIfaces.add(stackedIface);
11559da2f1e007268a42248a1778aa9b560e3ce3b704Jeff Sharkey                        }
1156eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey                    }
1157be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                }
115821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
115921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
116021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1161eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey        // Apply policies against all connected interfaces found above
116202e21d6a5b5117d494777a36783909854854f751Jeff Sharkey        mNetworkRules.clear();
116321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        final ArrayList<String> ifaceList = Lists.newArrayList();
1164eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey        for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
1165be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
116621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
116721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            ifaceList.clear();
1168eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey            for (int j = connIdents.size() - 1; j >= 0; j--) {
1169eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey                final Pair<String, NetworkIdentity> ident = connIdents.get(j);
1170eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey                if (policy.template.matches(ident.second)) {
1171eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey                    ifaceList.add(ident.first);
117221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
117321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
117421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
117521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (ifaceList.size() > 0) {
117621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
117702e21d6a5b5117d494777a36783909854854f751Jeff Sharkey                mNetworkRules.put(policy, ifaces);
117821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
117921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
118021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1181ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey        long lowestRule = Long.MAX_VALUE;
1182497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        final ArraySet<String> newMeteredIfaces = new ArraySet<String>(states.length);
1183fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
118421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // apply each policy that we found ifaces for; compute remaining data
118521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // based on current cycle and historical stats, and push to kernel.
1186684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey        final long currentTime = currentTimeMillis();
1187be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        for (int i = mNetworkRules.size()-1; i >= 0; i--) {
1188be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            final NetworkPolicy policy = mNetworkRules.keyAt(i);
1189be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            final String[] ifaces = mNetworkRules.valueAt(i);
119021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
11918fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            final long start;
11928fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            final long totalBytes;
11938fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            if (policy.hasCycle()) {
11948fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                start = computeLastCycleBoundary(currentTime, policy);
11958fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                totalBytes = getTotalBytes(policy.template, start, currentTime);
11968fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            } else {
11978fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                start = Long.MAX_VALUE;
11988fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                totalBytes = 0;
11998fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            }
120021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
120121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (LOGD) {
120221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
120322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey                        + Arrays.toString(ifaces));
120422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey            }
120522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
1206ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey            final boolean hasWarning = policy.warningBytes != LIMIT_DISABLED;
120741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
1208f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey            if (hasLimit || policy.metered) {
12098e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                final long quotaBytes;
1210f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                if (!hasLimit) {
1211f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                    // metered network, but no policy limit; we still need to
1212f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                    // restrict apps, so push really high quota.
1213f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                    quotaBytes = Long.MAX_VALUE;
12140e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                } else if (policy.lastLimitSnooze >= start) {
12158e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    // snoozing past quota, but we still need to restrict apps,
12168e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    // so push really high quota.
12178e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    quotaBytes = Long.MAX_VALUE;
12188e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                } else {
12198e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    // remaining "quota" bytes are based on total usage in
12208e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    // current cycle. kernel doesn't like 0-byte rules, so we
12218e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    // set 1-byte quota and disable the radio later.
12228e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    quotaBytes = Math.max(1, policy.limitBytes - totalBytes);
12238e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                }
122450fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma
1225b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                if (ifaces.length > 1) {
1226b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    // TODO: switch to shared quota once NMS supports
1227b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
1228b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                }
1229fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
1230fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey                for (String iface : ifaces) {
1231b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                    removeInterfaceQuota(iface);
12328e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    setInterfaceQuota(iface, quotaBytes);
12338e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey                    newMeteredIfaces.add(iface);
1234be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    if (powerSave) {
1235be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                        connIfaces.remove(iface);
1236be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    }
123741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
123841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
1239ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey
1240ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey            // keep track of lowest warning or limit of active policies
1241ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey            if (hasWarning && policy.warningBytes < lowestRule) {
1242ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey                lowestRule = policy.warningBytes;
1243ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey            }
1244ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey            if (hasLimit && policy.limitBytes < lowestRule) {
1245ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey                lowestRule = policy.limitBytes;
1246ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey            }
1247ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey        }
1248ac3fcb1590e1da21324c13ce237ec48f2bf488bfJeff Sharkey
1249be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        for (int i = connIfaces.size()-1; i >= 0; i--) {
1250be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            String iface = connIfaces.valueAt(i);
1251be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            removeInterfaceQuota(iface);
1252be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            setInterfaceQuota(iface, Long.MAX_VALUE);
1253be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            newMeteredIfaces.add(iface);
1254be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        }
1255be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
1256e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey        mHandler.obtainMessage(MSG_ADVISE_PERSIST_THRESHOLD, lowestRule).sendToTarget();
1257fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey
1258b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        // remove quota on any trailing interfaces
1259497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        for (int i = mMeteredIfaces.size() - 1; i >= 0; i--) {
1260497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn            final String iface = mMeteredIfaces.valueAt(i);
1261b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey            if (!newMeteredIfaces.contains(iface)) {
1262b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey                removeInterfaceQuota(iface);
126350fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma            }
126450fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma        }
1265b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        mMeteredIfaces = newMeteredIfaces;
1266b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
1267b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
1268b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
126950fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma    }
127050fd36d7c38c40b087c8f3e3172478abe0c051d9Ashish Sharma
127122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    /**
127222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
127322c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     * have at least a default mobile policy defined.
127422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey     */
127522c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    private void ensureActiveMobilePolicyLocked() {
127622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
12778e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        if (mSuppressDefaultPolicy) return;
12788e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
12798fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        final TelephonyManager tele = TelephonyManager.from(mContext);
12803256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        final SubscriptionManager sub = SubscriptionManager.from(mContext);
12818fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey
12823256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        final int[] subIds = sub.getActiveSubscriptionIdList();
12833256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        for (int subId : subIds) {
12843256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            final String subscriberId = tele.getSubscriberId(subId);
12853256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            ensureActiveMobilePolicyLocked(subscriberId);
12863256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        }
12873256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    }
128822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
12893256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    private void ensureActiveMobilePolicyLocked(String subscriberId) {
12903256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        // Poke around to see if we already have a policy
12913256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        final NetworkIdentity probeIdent = new NetworkIdentity(TYPE_MOBILE,
12923256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
12933256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        for (int i = mNetworkPolicy.size() - 1; i >= 0; i--) {
12943256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            final NetworkTemplate template = mNetworkPolicy.keyAt(i);
12953256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            if (template.matches(probeIdent)) {
12963256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                if (LOGD) {
12973256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                    Slog.d(TAG, "Found template " + template + " which matches subscriber "
12983256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                            + NetworkIdentity.scrubSubscriberId(subscriberId));
12993256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                }
13003256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                return;
130121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
130222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        }
130321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
13043256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        Slog.i(TAG, "No policy for subscriber " + NetworkIdentity.scrubSubscriberId(subscriberId)
13053256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                + "; generating default policy");
130621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
13073256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        // Build default mobile policy, and assume usage cycle starts today
13083256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        final long warningBytes = mContext.getResources().getInteger(
13093256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                com.android.internal.R.integer.config_networkPolicyDefaultWarning) * MB_IN_BYTES;
131022c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
13113256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        final Time time = new Time();
13123256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        time.setToNow();
13139bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey
13143256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        final int cycleDay = time.monthDay;
13153256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        final String cycleTimezone = time.timezone;
131622c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
13173256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
13183256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
13193256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
13203256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        addNetworkPolicyLocked(policy);
132121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
132221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
132321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void readPolicyLocked() {
132422c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (LOGV) Slog.v(TAG, "readPolicyLocked()");
132521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
132621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // clear any existing policy and read from disk
132722c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        mNetworkPolicy.clear();
1328d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        mUidPolicy.clear();
132921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
133021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        FileInputStream fis = null;
133121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
133221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fis = mPolicyFile.openRead();
133321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final XmlPullParser in = Xml.newPullParser();
13349e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewicz            in.setInput(fis, StandardCharsets.UTF_8.name());
133521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
133621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            int type;
133741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            int version = VERSION_INIT;
133821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            while ((type = in.next()) != END_DOCUMENT) {
133921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                final String tag = in.getName();
134021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                if (type == START_TAG) {
134121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    if (TAG_POLICY_LIST.equals(tag)) {
134221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        version = readIntAttribute(in, ATTR_VERSION);
13434664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                        if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) {
13444664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                            mRestrictBackground = readBooleanAttribute(
13454664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                                    in, ATTR_RESTRICT_BACKGROUND);
13464664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                        } else {
13473a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey                            mRestrictBackground = false;
13484664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey                        }
134921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
135021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    } else if (TAG_NETWORK_POLICY.equals(tag)) {
135121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
135221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
13538fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                        final String networkId;
13548fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                        if (version >= VERSION_ADDED_NETWORK_ID) {
13558fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                            networkId = in.getAttributeValue(null, ATTR_NETWORK_ID);
13568fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                        } else {
13578fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                            networkId = null;
13588fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                        }
135921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
13609bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey                        final String cycleTimezone;
13619bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey                        if (version >= VERSION_ADDED_TIMEZONE) {
13629bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey                            cycleTimezone = in.getAttributeValue(null, ATTR_CYCLE_TIMEZONE);
13639bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey                        } else {
13649bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey                            cycleTimezone = Time.TIMEZONE_UTC;
13659bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey                        }
136621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
136721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
13680e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                        final long lastLimitSnooze;
13690e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                        if (version >= VERSION_SPLIT_SNOOZE) {
13700e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                            lastLimitSnooze = readLongAttribute(in, ATTR_LAST_LIMIT_SNOOZE);
13710e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                        } else if (version >= VERSION_ADDED_SNOOZE) {
13720e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                            lastLimitSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
137341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        } else {
13740e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                            lastLimitSnooze = SNOOZE_NEVER;
137541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                        }
1376f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                        final boolean metered;
1377f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                        if (version >= VERSION_ADDED_METERED) {
1378f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                            metered = readBooleanAttribute(in, ATTR_METERED);
1379f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                        } else {
1380f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                            switch (networkTemplate) {
1381f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                                case MATCH_MOBILE_3G_LOWER:
1382f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                                case MATCH_MOBILE_4G:
1383f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                                case MATCH_MOBILE_ALL:
1384f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                                    metered = true;
1385f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                                    break;
1386f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                                default:
1387f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                                    metered = false;
1388f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                            }
1389f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                        }
13900e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                        final long lastWarningSnooze;
13910e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                        if (version >= VERSION_SPLIT_SNOOZE) {
13920e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                            lastWarningSnooze = readLongAttribute(in, ATTR_LAST_WARNING_SNOOZE);
13930e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                        } else {
13940e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                            lastWarningSnooze = SNOOZE_NEVER;
13950e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                        }
1396837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey                        final boolean inferred;
1397837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey                        if (version >= VERSION_ADDED_INFERRED) {
1398837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey                            inferred = readBooleanAttribute(in, ATTR_INFERRED);
1399837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey                        } else {
1400837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey                            inferred = false;
1401837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey                        }
140221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
14033256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                        final NetworkTemplate template = new NetworkTemplate(networkTemplate,
14043256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                                subscriberId, networkId);
14050e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                        mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
14069bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey                                cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
1407837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey                                lastLimitSnooze, metered, inferred));
140821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1409d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                    } else if (TAG_UID_POLICY.equals(tag)) {
141021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int uid = readIntAttribute(in, ATTR_UID);
141121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                        final int policy = readIntAttribute(in, ATTR_POLICY);
141221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1413d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                        if (UserHandle.isApp(uid)) {
1414be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                            setUidPolicyUncheckedLocked(uid, policy, false);
1415497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        } else {
1416497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                            Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
1417497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                        }
1418d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                    } else if (TAG_APP_POLICY.equals(tag)) {
14198a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey                        final int appId = readIntAttribute(in, ATTR_APP_ID);
14208a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey                        final int policy = readIntAttribute(in, ATTR_POLICY);
14218a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey
1422d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                        // TODO: set for other users during upgrade
1423d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                        final int uid = UserHandle.getUid(UserHandle.USER_OWNER, appId);
1424d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                        if (UserHandle.isApp(uid)) {
1425be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                            setUidPolicyUncheckedLocked(uid, policy, false);
14268a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey                        } else {
1427d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                            Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
14288a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey                        }
142921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    }
143021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
143121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
143221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
143321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (FileNotFoundException e) {
143421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // missing policy is okay, probably first boot
14353a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey            upgradeLegacyBackgroundData();
143621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (IOException e) {
1437b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem reading network policy", e);
143821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (XmlPullParserException e) {
1439b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem reading network policy", e);
144021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } finally {
144121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            IoUtils.closeQuietly(fis);
144221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
144321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
144421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
14453a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey    /**
14463a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey     * Upgrade legacy background data flags, notifying listeners of one last
14473a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey     * change to always-true.
14483a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey     */
14493a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey    private void upgradeLegacyBackgroundData() {
14503a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        mRestrictBackground = Settings.Secure.getInt(
14513a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey                mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1;
14523a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
14533a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        // kick off one last broadcast if restricted
14543a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        if (mRestrictBackground) {
14553a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey            final Intent broadcast = new Intent(
14563a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey                    ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
14575ac72a29593ab9a20337a2225df52bdf4754be02Dianne Hackborn            mContext.sendBroadcastAsUser(broadcast, UserHandle.ALL);
14583a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        }
14593a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey    }
14603a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
1461497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    void writePolicyLocked() {
146222c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey        if (LOGV) Slog.v(TAG, "writePolicyLocked()");
146321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
146421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        FileOutputStream fos = null;
146521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        try {
146621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fos = mPolicyFile.startWrite();
146721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
146821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            XmlSerializer out = new FastXmlSerializer();
14699e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewicz            out.setOutput(fos, StandardCharsets.UTF_8.name());
147021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.startDocument(null, true);
147121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
147221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.startTag(null, TAG_POLICY_LIST);
14738fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            writeIntAttribute(out, ATTR_VERSION, VERSION_LATEST);
14744664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
147521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
147621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // write all known network policies
1477be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            for (int i = 0; i < mNetworkPolicy.size(); i++) {
1478be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                final NetworkPolicy policy = mNetworkPolicy.valueAt(i);
14791b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                final NetworkTemplate template = policy.template;
14801b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
148121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.startTag(null, TAG_NETWORK_POLICY);
14821b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
14831b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                final String subscriberId = template.getSubscriberId();
14841b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (subscriberId != null) {
14851b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
148621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
14878fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                final String networkId = template.getNetworkId();
14888fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                if (networkId != null) {
14898fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                    out.attribute(null, ATTR_NETWORK_ID, networkId);
14908fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                }
149121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
14929bf3150cfae03421c9dd237b46657714859d871cJeff Sharkey                out.attribute(null, ATTR_CYCLE_TIMEZONE, policy.cycleTimezone);
149321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
149421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
14950e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                writeLongAttribute(out, ATTR_LAST_WARNING_SNOOZE, policy.lastWarningSnooze);
14960e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                writeLongAttribute(out, ATTR_LAST_LIMIT_SNOOZE, policy.lastLimitSnooze);
1497f60d0afd1ef08a24121d015bb016df05265b6d07Jeff Sharkey                writeBooleanAttribute(out, ATTR_METERED, policy.metered);
1498837f9242ae2e8f5f380d0b30b8fffbc68494914fJeff Sharkey                writeBooleanAttribute(out, ATTR_INFERRED, policy.inferred);
149921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                out.endTag(null, TAG_NETWORK_POLICY);
150021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
150121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
150221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // write all known uid policies
1503d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            for (int i = 0; i < mUidPolicy.size(); i++) {
1504d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                final int uid = mUidPolicy.keyAt(i);
1505d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                final int policy = mUidPolicy.valueAt(i);
150621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1507497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                // skip writing empty policies
1508497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey                if (policy == POLICY_NONE) continue;
1509497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
1510d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                out.startTag(null, TAG_UID_POLICY);
1511d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                writeIntAttribute(out, ATTR_UID, uid);
151221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                writeIntAttribute(out, ATTR_POLICY, policy);
1513d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                out.endTag(null, TAG_UID_POLICY);
151421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
151521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
151621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.endTag(null, TAG_POLICY_LIST);
151721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            out.endDocument();
151821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
151921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            mPolicyFile.finishWrite(fos);
152021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        } catch (IOException e) {
152121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            if (fos != null) {
152221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                mPolicyFile.failWrite(fos);
152321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
152421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
152521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
152621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1527d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    @Override
1528d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey    public void setUidPolicy(int uid, int policy) {
152921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1530a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
1531d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        if (!UserHandle.isApp(uid)) {
1532d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
1533497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        }
1534497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
1535be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        synchronized (mRulesLock) {
153672f83d6a05ddecd516787cedb3b49839bb287c6dJulia Reynolds            final long token = Binder.clearCallingIdentity();
153772f83d6a05ddecd516787cedb3b49839bb287c6dJulia Reynolds            try {
153872f83d6a05ddecd516787cedb3b49839bb287c6dJulia Reynolds                final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
153972f83d6a05ddecd516787cedb3b49839bb287c6dJulia Reynolds                if (oldPolicy != policy) {
154072f83d6a05ddecd516787cedb3b49839bb287c6dJulia Reynolds                    setUidPolicyUncheckedLocked(uid, policy, true);
154172f83d6a05ddecd516787cedb3b49839bb287c6dJulia Reynolds                }
154272f83d6a05ddecd516787cedb3b49839bb287c6dJulia Reynolds            } finally {
154372f83d6a05ddecd516787cedb3b49839bb287c6dJulia Reynolds                Binder.restoreCallingIdentity(token);
1544be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            }
1545be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        }
1546497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    }
1547497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
1548be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn    @Override
1549be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn    public void addUidPolicy(int uid, int policy) {
1550be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1551be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
1552be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        if (!UserHandle.isApp(uid)) {
1553be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
1554be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        }
1555be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
1556a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
1557be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
1558be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            policy |= oldPolicy;
1559be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            if (oldPolicy != policy) {
1560be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                setUidPolicyUncheckedLocked(uid, policy, true);
1561be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            }
1562be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        }
1563be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn    }
1564c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
1565be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn    @Override
1566be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn    public void removeUidPolicy(int uid, int policy) {
1567be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1568be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
1569be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        if (!UserHandle.isApp(uid)) {
1570be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            throw new IllegalArgumentException("cannot apply policy to UID " + uid);
1571be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        }
1572be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
1573be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        synchronized (mRulesLock) {
1574be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
1575be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            policy = oldPolicy & ~policy;
1576be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            if (oldPolicy != policy) {
1577be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                setUidPolicyUncheckedLocked(uid, policy, true);
1578497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            }
157921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
1580d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
1581d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1582be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn    private void setUidPolicyUncheckedLocked(int uid, int policy, boolean persist) {
1583be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        mUidPolicy.put(uid, policy);
1584be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
1585be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        // uid policy changed, recompute rules and persist policy.
1586be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        updateRulesForUidLocked(uid);
1587be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        if (persist) {
1588be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            writePolicyLocked();
1589be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        }
1590be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn    }
1591be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
1592d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    @Override
1593d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey    public int getUidPolicy(int uid) {
159421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
159521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1596a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
1597d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            return mUidPolicy.get(uid, POLICY_NONE);
1598a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
1599d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
1600d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
1601c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    @Override
1602d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey    public int[] getUidsWithPolicy(int policy) {
1603854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
1604854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey
1605d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        int[] uids = new int[0];
1606854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        synchronized (mRulesLock) {
1607d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            for (int i = 0; i < mUidPolicy.size(); i++) {
1608d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                final int uid = mUidPolicy.keyAt(i);
1609d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                final int uidPolicy = mUidPolicy.valueAt(i);
1610d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                if (uidPolicy == policy) {
1611d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                    uids = appendInt(uids, uid);
1612854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey                }
1613854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey            }
1614854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey        }
1615d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        return uids;
1616d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey    }
1617d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey
1618d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey    /**
1619d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey     * Remove any policies associated with given {@link UserHandle}, persisting
1620d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey     * if any changes are made.
1621d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey     */
1622497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    void removePoliciesForUserLocked(int userId) {
1623d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        if (LOGV) Slog.v(TAG, "removePoliciesForUserLocked()");
1624d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey
1625d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        int[] uids = new int[0];
1626d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        for (int i = 0; i < mUidPolicy.size(); i++) {
1627d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            final int uid = mUidPolicy.keyAt(i);
1628d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            if (UserHandle.getUserId(uid) == userId) {
1629d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                uids = appendInt(uids, uid);
1630d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            }
1631d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        }
1632d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey
1633d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        if (uids.length > 0) {
1634d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            for (int uid : uids) {
1635d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                mUidPolicy.delete(uid);
1636d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                updateRulesForUidLocked(uid);
1637d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            }
1638d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            writePolicyLocked();
1639d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        }
1640854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey    }
1641854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey
1642854b2b1670bda1eeb87a14b7ac3d222024f0aad6Jeff Sharkey    @Override
1643c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    public void registerListener(INetworkPolicyListener listener) {
16441a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        // TODO: create permission for observing network policy
16451a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
16461a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey
1647c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.register(listener);
1648c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
16494414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        // TODO: consider dispatching existing rules to new listeners
1650c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
1651c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
1652c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    @Override
1653c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    public void unregisterListener(INetworkPolicyListener listener) {
16541a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        // TODO: create permission for observing network policy
16551a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
16561a303953589fdddf21d88b8fa660136f5b060d0dJeff Sharkey
1657c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        mListeners.unregister(listener);
1658c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
1659c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
16601b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    @Override
166122c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey    public void setNetworkPolicies(NetworkPolicy[] policies) {
166221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
166321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1664684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey        maybeRefreshTrustedTime();
166521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
16663256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            normalizePoliciesLocked(policies);
16678e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            updateNetworkEnabledLocked();
166802e21d6a5b5117d494777a36783909854854f751Jeff Sharkey            updateNetworkRulesLocked();
1669497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            updateNotificationsLocked();
167021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            writePolicyLocked();
167121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
167221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
167321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1674497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    void addNetworkPolicyLocked(NetworkPolicy policy) {
167516a16899505ec0a9ede5b76650bfb8817b3227c7Svet Ganov        NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName());
16763256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        policies = ArrayUtils.appendElement(NetworkPolicy.class, policies, policy);
16773256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        setNetworkPolicies(policies);
16789f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey    }
16799f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey
168021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
168116a16899505ec0a9ede5b76650bfb8817b3227c7Svet Ganov    public NetworkPolicy[] getNetworkPolicies(String callingPackage) {
168221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
16837c5befa4a7ccd6e7e91ffdd93264b717259ec863Amit Mahajan        try {
1684a9e72a7653d25ae1974dac3f1156d126c807e40cAmit Mahajan            mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, TAG);
1685a9e72a7653d25ae1974dac3f1156d126c807e40cAmit Mahajan            // SKIP checking run-time OP_READ_PHONE_STATE since caller or self has PRIVILEGED
1686a9e72a7653d25ae1974dac3f1156d126c807e40cAmit Mahajan            // permission
16877c5befa4a7ccd6e7e91ffdd93264b717259ec863Amit Mahajan        } catch (SecurityException e) {
16887c5befa4a7ccd6e7e91ffdd93264b717259ec863Amit Mahajan            mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
16897c5befa4a7ccd6e7e91ffdd93264b717259ec863Amit Mahajan
16907c5befa4a7ccd6e7e91ffdd93264b717259ec863Amit Mahajan            if (mAppOps.noteOp(AppOpsManager.OP_READ_PHONE_STATE, Binder.getCallingUid(),
16917c5befa4a7ccd6e7e91ffdd93264b717259ec863Amit Mahajan                    callingPackage) != AppOpsManager.MODE_ALLOWED) {
16927c5befa4a7ccd6e7e91ffdd93264b717259ec863Amit Mahajan                return new NetworkPolicy[0];
16937c5befa4a7ccd6e7e91ffdd93264b717259ec863Amit Mahajan            }
169416a16899505ec0a9ede5b76650bfb8817b3227c7Svet Ganov        }
169516a16899505ec0a9ede5b76650bfb8817b3227c7Svet Ganov
169621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mRulesLock) {
16973256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            final int size = mNetworkPolicy.size();
16983256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            final NetworkPolicy[] policies = new NetworkPolicy[size];
16993256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            for (int i = 0; i < size; i++) {
17003256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                policies[i] = mNetworkPolicy.valueAt(i);
17013256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            }
17023256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            return policies;
17033256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        }
17043256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    }
17053256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
17063256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    private void normalizePoliciesLocked() {
170716a16899505ec0a9ede5b76650bfb8817b3227c7Svet Ganov        normalizePoliciesLocked(getNetworkPolicies(mContext.getOpPackageName()));
17083256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    }
17093256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
17103256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey    private void normalizePoliciesLocked(NetworkPolicy[] policies) {
17113256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        final TelephonyManager tele = TelephonyManager.from(mContext);
17123256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        final String[] merged = tele.getMergedSubscriberIds();
17133256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey
17143256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        mNetworkPolicy.clear();
17153256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey        for (NetworkPolicy policy : policies) {
17163256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            // When two normalized templates conflict, prefer the most
17173256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            // restrictive policy
17183256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            policy.template = NetworkTemplate.normalize(policy.template, merged);
17193256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            final NetworkPolicy existing = mNetworkPolicy.get(policy.template);
17203256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            if (existing == null || existing.compareTo(policy) > 0) {
17213256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                if (existing != null) {
17223256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                    Slog.d(TAG, "Normalization replaced " + existing + " with " + policy);
17233256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                }
17243256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                mNetworkPolicy.put(policy.template, policy);
17253256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            }
172641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
172741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
172841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
172941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    @Override
17300e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    public void snoozeLimit(NetworkTemplate template) {
173141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
17326c0b4f393ae8e728c7a7943bfbdcdd27d6642192Jeff Sharkey
17336c0b4f393ae8e728c7a7943bfbdcdd27d6642192Jeff Sharkey        final long token = Binder.clearCallingIdentity();
17346c0b4f393ae8e728c7a7943bfbdcdd27d6642192Jeff Sharkey        try {
17356c0b4f393ae8e728c7a7943bfbdcdd27d6642192Jeff Sharkey            performSnooze(template, TYPE_LIMIT);
17366c0b4f393ae8e728c7a7943bfbdcdd27d6642192Jeff Sharkey        } finally {
17376c0b4f393ae8e728c7a7943bfbdcdd27d6642192Jeff Sharkey            Binder.restoreCallingIdentity(token);
17386c0b4f393ae8e728c7a7943bfbdcdd27d6642192Jeff Sharkey        }
17390e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    }
174041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
1741497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    void performSnooze(NetworkTemplate template, int type) {
1742684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey        maybeRefreshTrustedTime();
1743684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey        final long currentTime = currentTimeMillis();
174441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        synchronized (mRulesLock) {
174541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            // find and snooze local policy that matches
174641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            final NetworkPolicy policy = mNetworkPolicy.get(template);
174741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            if (policy == null) {
174841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                throw new IllegalArgumentException("unable to find policy for " + template);
174941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
175041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
17510e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            switch (type) {
17520e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                case TYPE_WARNING:
17530e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                    policy.lastWarningSnooze = currentTime;
17540e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                    break;
17550e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                case TYPE_LIMIT:
17560e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                    policy.lastLimitSnooze = currentTime;
17570e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                    break;
17580e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                default:
17590e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                    throw new IllegalArgumentException("unexpected type");
17600e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            }
176141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
17623256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            normalizePoliciesLocked();
17638e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            updateNetworkEnabledLocked();
176441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            updateNetworkRulesLocked();
176541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            updateNotificationsLocked();
176641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            writePolicyLocked();
176721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
176821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
176921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
177021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
17714664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    public void setRestrictBackground(boolean restrictBackground) {
17724664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
17734664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey
1774684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey        maybeRefreshTrustedTime();
17754664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        synchronized (mRulesLock) {
17764664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            mRestrictBackground = restrictBackground;
17779d14206594c0b50a539ee73e37804542694937d6Jeff Sharkey            updateRulesForGlobalChangeLocked(true);
17783a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey            updateNotificationsLocked();
1779f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            writePolicyLocked();
17804664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        }
17811f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey
17821f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey        mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED, restrictBackground ? 1 : 0, 0)
17831f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                .sendToTarget();
17844664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    }
17854664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey
17864664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    @Override
17874664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    public boolean getRestrictBackground() {
17884664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
17894664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey
17904664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        synchronized (mRulesLock) {
17914664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            return mRestrictBackground;
17924664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey        }
17934664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    }
17944664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey
17958ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn    @Override
17968ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn    public void setDeviceIdleMode(boolean enabled) {
17978ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
17988ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn
17998ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn        synchronized (mRulesLock) {
18008ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn            if (mDeviceIdleMode != enabled) {
18018ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn                mDeviceIdleMode = enabled;
18028ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn                if (mSystemReady) {
18033b16cf4f47142a845bf0ede54ef8ef956506c6c3Dianne Hackborn                    updateRulesForDeviceIdleLocked();
18043b16cf4f47142a845bf0ede54ef8ef956506c6c3Dianne Hackborn                }
18053b16cf4f47142a845bf0ede54ef8ef956506c6c3Dianne Hackborn                if (enabled) {
18063b16cf4f47142a845bf0ede54ef8ef956506c6c3Dianne Hackborn                    EventLogTags.writeDeviceIdleOnPhase("net");
18073b16cf4f47142a845bf0ede54ef8ef956506c6c3Dianne Hackborn                } else {
18083b16cf4f47142a845bf0ede54ef8ef956506c6c3Dianne Hackborn                    EventLogTags.writeDeviceIdleOffPhase("net");
18098ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn                }
18108ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn            }
18118ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn        }
18128ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn    }
18138ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn
1814f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) {
1815be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
1816be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            NetworkPolicy policy = mNetworkPolicy.valueAt(i);
1817f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            if (policy.template.matches(ident)) {
1818f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey                return policy;
1819f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            }
1820f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        }
1821f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        return null;
1822f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    }
1823f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1824f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    @Override
1825f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) {
1826f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
1827f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1828f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        // only returns usage summary, so we don't require caller to have
1829f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        // READ_NETWORK_USAGE_HISTORY.
1830f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final long token = Binder.clearCallingIdentity();
1831f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        try {
1832f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            return getNetworkQuotaInfoUnchecked(state);
1833f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        } finally {
1834f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            Binder.restoreCallingIdentity(token);
1835f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        }
1836f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    }
1837f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1838f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) {
1839f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
1840f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1841f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final NetworkPolicy policy;
1842f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        synchronized (mRulesLock) {
1843f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            policy = findPolicyForNetworkLocked(ident);
1844f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        }
1845f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
18468fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        if (policy == null || !policy.hasCycle()) {
1847f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            // missing policy means we can't derive useful quota info
1848f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey            return null;
1849f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        }
1850f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1851684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey        final long currentTime = currentTimeMillis();
1852f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1853b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        // find total bytes used under policy
1854f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final long start = computeLastCycleBoundary(currentTime, policy);
1855f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final long end = currentTime;
18568e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        final long totalBytes = getTotalBytes(policy.template, start, end);
1857f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1858f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        // report soft and hard limits under policy
1859f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes
1860f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey                : NetworkQuotaInfo.NO_LIMIT;
1861f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes
1862f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey                : NetworkQuotaInfo.NO_LIMIT;
1863f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
1864f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey        return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes);
1865f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey    }
1866f0ceede8fff5df24e5c98701d81c2b71eb138aa9Jeff Sharkey
18674664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey    @Override
18689f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey    public boolean isNetworkMetered(NetworkState state) {
18699f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey        final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
18709f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey
1871f166f480f0f29b310a27fe001ee26d7dfac84fddJeff Sharkey        // roaming networks are always considered metered
1872f166f480f0f29b310a27fe001ee26d7dfac84fddJeff Sharkey        if (ident.getRoaming()) {
1873f166f480f0f29b310a27fe001ee26d7dfac84fddJeff Sharkey            return true;
1874f166f480f0f29b310a27fe001ee26d7dfac84fddJeff Sharkey        }
1875f166f480f0f29b310a27fe001ee26d7dfac84fddJeff Sharkey
18769f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey        final NetworkPolicy policy;
18779f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey        synchronized (mRulesLock) {
18789f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey            policy = findPolicyForNetworkLocked(ident);
18799f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey        }
18809f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey
18819f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey        if (policy != null) {
18829f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey            return policy.metered;
18839f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey        } else {
18849f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            final int type = state.networkInfo.getType();
18859f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            if (isNetworkTypeMobile(type) || type == TYPE_WIMAX) {
18869f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey                return true;
18879f6e4ba50e7e73704c7fbd3ba65fe73bdf8ad73fJeff Sharkey            }
18889f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey            return false;
18899f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey        }
18909f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey    }
18919f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey
18929f7cbf0e50bcb7e9163b23524814003ba8784732Jeff Sharkey    @Override
18938fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
189475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
18951b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
18968fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey        final IndentingPrintWriter fout = new IndentingPrintWriter(writer, "  ");
18978fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey
1898497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        final ArraySet<String> argSet = new ArraySet<String>(args.length);
189941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        for (String arg : args) {
190041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            argSet.add(arg);
190141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
190241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
19031b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        synchronized (mRulesLock) {
19040e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey            if (argSet.contains("--unsnooze")) {
1905be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                for (int i = mNetworkPolicy.size()-1; i >= 0; i--) {
1906be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    mNetworkPolicy.valueAt(i).clearSnooze();
190741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                }
19080e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey
19093256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey                normalizePoliciesLocked();
19100e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                updateNetworkEnabledLocked();
19110e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                updateNetworkRulesLocked();
19120e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                updateNotificationsLocked();
191341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                writePolicyLocked();
19140e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey
19150e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey                fout.println("Cleared snooze timestamps");
191641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                return;
191741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            }
191841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
19198ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn            fout.print("System ready: "); fout.println(mSystemReady);
19204664500de0c1b270bce4991a400ab439ff2ef77bJeff Sharkey            fout.print("Restrict background: "); fout.println(mRestrictBackground);
1921be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            fout.print("Restrict power: "); fout.println(mRestrictPower);
19228ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn            fout.print("Device idle: "); fout.println(mDeviceIdleMode);
192321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            fout.println("Network policies:");
19248fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            fout.increaseIndent();
1925be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            for (int i = 0; i < mNetworkPolicy.size(); i++) {
1926be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                fout.println(mNetworkPolicy.valueAt(i).toString());
192721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
19288fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            fout.decreaseIndent();
192921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
1930eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey            fout.print("Metered ifaces: "); fout.println(String.valueOf(mMeteredIfaces));
1931eb2c2c790c4b86c9c09245e0b87a38972713434aJeff Sharkey
1932d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            fout.println("Policy for UIDs:");
19338fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            fout.increaseIndent();
1934d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            int size = mUidPolicy.size();
19358a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey            for (int i = 0; i < size; i++) {
1936d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                final int uid = mUidPolicy.keyAt(i);
1937d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                final int policy = mUidPolicy.valueAt(i);
1938d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                fout.print("UID=");
1939d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                fout.print(uid);
19408a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey                fout.print(" policy=");
19418a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey                dumpPolicy(fout, policy);
19428a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey                fout.println();
19438a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey            }
19448fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            fout.decreaseIndent();
19451b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
19464a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            size = mPowerSaveWhitelistExceptIdleAppIds.size();
19474a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            if (size > 0) {
19484a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                fout.println("Power save whitelist (except idle) app ids:");
19494a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                fout.increaseIndent();
19504a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                for (int i = 0; i < size; i++) {
19514a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                    fout.print("UID=");
19524a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                    fout.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
19534a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                    fout.print(": ");
19544a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                    fout.print(mPowerSaveWhitelistExceptIdleAppIds.valueAt(i));
19554a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                    fout.println();
19564a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                }
19574a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                fout.decreaseIndent();
19584a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            }
19594a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn
1960be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            size = mPowerSaveWhitelistAppIds.size();
1961be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            if (size > 0) {
1962be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                fout.println("Power save whitelist app ids:");
1963be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                fout.increaseIndent();
1964be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                for (int i = 0; i < size; i++) {
1965be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    fout.print("UID=");
1966be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    fout.print(mPowerSaveWhitelistAppIds.keyAt(i));
1967be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    fout.print(": ");
1968be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    fout.print(mPowerSaveWhitelistAppIds.valueAt(i));
1969be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    fout.println();
1970be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                }
1971be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                fout.decreaseIndent();
1972be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            }
1973be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
19741b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            final SparseBooleanArray knownUids = new SparseBooleanArray();
1975497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn            collectKeys(mUidState, knownUids);
19761b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            collectKeys(mUidRules, knownUids);
19771b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
19788a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey            fout.println("Status for known UIDs:");
19798fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            fout.increaseIndent();
19808a8b581e669f6187b397f856a567a76ed8aba2c2Jeff Sharkey            size = knownUids.size();
19811b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            for (int i = 0; i < size; i++) {
19821b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int uid = knownUids.keyAt(i);
19838fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                fout.print("UID=");
19841b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(uid);
19851b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
1986497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn                int state = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
1987497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn                fout.print(" state=");
1988497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn                fout.print(state);
19894a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                fout.print(state <= ActivityManager.PROCESS_STATE_TOP ? " (fg)" : " (bg)");
1990497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn
19911b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.print(" rules=");
19921b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                final int rulesIndex = mUidRules.indexOfKey(uid);
19931b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                if (rulesIndex < 0) {
19941b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    fout.print("UNKNOWN");
19951b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                } else {
19961b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                    dumpRules(fout, mUidRules.valueAt(rulesIndex));
19971b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                }
19981b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
19991b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey                fout.println();
20001b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            }
20018fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey            fout.decreaseIndent();
20021b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
20031b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
20049599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey
20059599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey    @Override
20069599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey    public boolean isUidForeground(int uid) {
2007497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
2008497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
20099599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        synchronized (mRulesLock) {
2010497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn            return isUidForegroundLocked(uid);
20119599cc5f21152860af9d18015b1398b50743da76Jeff Sharkey        }
2012c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey    }
2013c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
2014497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    boolean isUidForegroundLocked(int uid) {
2015497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        // only really in foreground when screen is also on
2016497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        return mScreenOn && mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY)
20174a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                <= ActivityManager.PROCESS_STATE_TOP;
2018497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    }
2019497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn
2020d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    /**
2021d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn     * Process state of UID changed; if needed, will trigger
2022d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn     * {@link #updateRulesForUidLocked(int)}.
2023d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey     */
2024d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn    void updateUidStateLocked(int uid, int uidState) {
2025497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        final int oldUidState = mUidState.get(uid, ActivityManager.PROCESS_STATE_CACHED_EMPTY);
2026497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        if (oldUidState != uidState) {
2027497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn            // state changed, push updated rules
2028497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn            mUidState.put(uid, uidState);
2029d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn            updateRulesForUidStateChangeLocked(uid, oldUidState, uidState);
2030fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn            if (mDeviceIdleMode && isProcStateAllowedWhileIdle(oldUidState)
2031fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                    != isProcStateAllowedWhileIdle(uidState)) {
2032fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                updateRulesForDeviceIdleLocked();
2033fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn            }
2034d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn        }
2035d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn    }
2036d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn
2037d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn    void removeUidStateLocked(int uid) {
2038d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn        final int index = mUidState.indexOfKey(uid);
2039d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn        if (index >= 0) {
2040d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn            final int oldUidState = mUidState.valueAt(index);
2041d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn            mUidState.removeAt(index);
2042d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn            if (oldUidState != ActivityManager.PROCESS_STATE_CACHED_EMPTY) {
2043d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn                updateRulesForUidStateChangeLocked(uid, oldUidState,
2044d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn                        ActivityManager.PROCESS_STATE_CACHED_EMPTY);
2045fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                if (mDeviceIdleMode) {
2046fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                    updateRulesForDeviceIdleLocked();
2047fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                }
2048497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn            }
2049a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
2050a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
2051a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
2052d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn    void updateRulesForUidStateChangeLocked(int uid, int oldUidState, int newUidState) {
20534a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        final boolean oldForeground = oldUidState <= ActivityManager.PROCESS_STATE_TOP;
20544a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        final boolean newForeground = newUidState <= ActivityManager.PROCESS_STATE_TOP;
2055d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn        if (oldForeground != newForeground) {
2056d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn            updateRulesForUidLocked(uid);
2057d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn        }
2058d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn    }
2059d23e0d6901935588f9472bd7073fea0009581e9bDianne Hackborn
2060a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    private void updateScreenOn() {
2061a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        synchronized (mRulesLock) {
2062a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            try {
2063037c33eae74bee2774897d969d48947f9abe254fJeff Brown                mScreenOn = mPowerManager.isInteractive();
2064a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            } catch (RemoteException e) {
2065b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                // ignored; service lives in system_server
2066a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
206721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            updateRulesForScreenLocked();
2068d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey        }
2069d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey    }
2070d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
2071a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    /**
2072a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey     * Update rules that might be changed by {@link #mScreenOn} value.
2073a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey     */
207421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private void updateRulesForScreenLocked() {
2075a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        // only update rules for anyone with foreground activities
2076497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        final int size = mUidState.size();
2077a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        for (int i = 0; i < size; i++) {
20784a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            if (mUidState.valueAt(i) <= ActivityManager.PROCESS_STATE_TOP) {
2079497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn                final int uid = mUidState.keyAt(i);
208021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                updateRulesForUidLocked(uid);
2081a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey            }
2082a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey        }
2083a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey    }
2084a4620793038b9a9163b26c6ece882cb454fcbf87Jeff Sharkey
2085fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    static boolean isProcStateAllowedWhileIdle(int procState) {
2086fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn        return procState <= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
2087fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn    }
2088fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn
2089b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen    void updateRulesForDeviceIdleLocked() {
2090b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        if (mDeviceIdleMode) {
2091b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            // sync the whitelists before enable dozable chain.  We don't care about the rules if
2092b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            // we are disabling the chain.
2093b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            SparseIntArray uidRules = new SparseIntArray();
2094b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            final List<UserInfo> users = mUserManager.getUsers();
2095fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn            for (int ui = users.size() - 1; ui >= 0; ui--) {
2096fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                UserInfo user = users.get(ui);
2097b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen                for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
20984a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                    if (mPowerSaveTempWhitelistAppIds.valueAt(i)) {
20994a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                        int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
21004a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                        int uid = UserHandle.getUid(user.id, appId);
21014a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                        uidRules.put(uid, FIREWALL_RULE_ALLOW);
21024a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                    }
2103b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen                }
2104b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen                for (int i = mPowerSaveWhitelistAppIds.size() - 1; i >= 0; i--) {
2105b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen                    int appId = mPowerSaveWhitelistAppIds.keyAt(i);
2106b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen                    int uid = UserHandle.getUid(user.id, appId);
2107b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen                    uidRules.put(uid, FIREWALL_RULE_ALLOW);
2108b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen                }
2109b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            }
2110fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn            for (int i = mUidState.size() - 1; i >= 0; i--) {
2111fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                if (isProcStateAllowedWhileIdle(mUidState.valueAt(i))) {
2112fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                    uidRules.put(mUidState.keyAt(i), FIREWALL_RULE_ALLOW);
2113fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn                }
2114fd854ee58c5d56f84047007ead9f88a767ae956fDianne Hackborn            }
2115b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            setUidFirewallRules(FIREWALL_CHAIN_DOZABLE, uidRules);
2116b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        }
21178dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen        enableFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, mDeviceIdleMode);
21188dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen    }
21198dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen
21204a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn    void updateRuleForDeviceIdleLocked(int uid) {
21214a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        if (mDeviceIdleMode) {
21224a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            int appId = UserHandle.getAppId(uid);
21234a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            if (mPowerSaveTempWhitelistAppIds.get(appId) || mPowerSaveWhitelistAppIds.get(appId)
21244a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                    || isProcStateAllowedWhileIdle(mUidState.get(uid))) {
21254a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_ALLOW);
21264a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            } else {
21274a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                setUidFirewallRule(FIREWALL_CHAIN_DOZABLE, uid, FIREWALL_RULE_DEFAULT);
21284a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            }
21294a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        }
21304a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn    }
21314a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn
21324a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn    void updateRulesForAppIdleLocked() {
21334a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        // Fully update the app idle firewall chain.
21344a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        SparseIntArray uidRules = new SparseIntArray();
21354a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        final List<UserInfo> users = mUserManager.getUsers();
21364a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        for (int ui = users.size() - 1; ui >= 0; ui--) {
21374a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            UserInfo user = users.get(ui);
21384a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            int[] idleUids = mUsageStats.getIdleUidsForUser(user.id);
21394a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            for (int uid : idleUids) {
21404a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                if (!mPowerSaveTempWhitelistAppIds.get(UserHandle.getAppId(uid), false)) {
21414a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                    uidRules.put(uid, FIREWALL_RULE_DENY);
21424a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                }
21434a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            }
21444a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        }
21454a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        setUidFirewallRules(FIREWALL_CHAIN_STANDBY, uidRules);
21464a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn    }
21474a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn
21484a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn    void updateRuleForAppIdleLocked(int uid) {
21494a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        if (!isUidValidForRules(uid)) return;
21504a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn
21514a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        int appId = UserHandle.getAppId(uid);
21524a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        if (!mPowerSaveTempWhitelistAppIds.get(appId) && isUidIdle(uid)) {
21534a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DENY);
21544a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        } else {
21554a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            setUidFirewallRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
21564a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        }
21574a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn    }
21584a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn
21598dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen    void updateRulesForAppIdleParoleLocked() {
21608dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen        boolean enableChain = !mUsageStats.isAppIdleParoleOn();
21618dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen        enableFirewallChainLocked(FIREWALL_CHAIN_STANDBY, enableChain);
2162b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen    }
2163b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen
2164b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    /**
21658ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn     * Update rules that might be changed by {@link #mRestrictBackground},
21668ad2af7e5b28f71e7bdfc1bb097937c6c1d22b18Dianne Hackborn     * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value.
2167b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey     */
2168497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    void updateRulesForGlobalChangeLocked(boolean restrictedNetworksChanged) {
2169b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        final PackageManager pm = mContext.getPackageManager();
2170d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey
2171b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        updateRulesForDeviceIdleLocked();
21724a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        updateRulesForAppIdleLocked();
2173b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen
2174d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        // update rules for all installed applications
2175e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott        final List<UserInfo> users = mUserManager.getUsers();
2176d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        final List<ApplicationInfo> apps = pm.getInstalledApplications(
2177d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
2178d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey
2179d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey        for (UserInfo user : users) {
2180d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            for (ApplicationInfo app : apps) {
2181d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                final int uid = UserHandle.getUid(user.id, app.uid);
2182d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey                updateRulesForUidLocked(uid);
2183d0c6ccbafdebc73d03cf3cd47f02f9f6c78a69ffJeff Sharkey            }
2184b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
2185b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
21865294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey        // limit data usage for some internal system services
21875294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey        updateRulesForUidLocked(android.os.Process.MEDIA_UID);
21885294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey        updateRulesForUidLocked(android.os.Process.DRM_UID);
2189be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn
2190be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        // If the set of restricted networks may have changed, re-evaluate those.
2191be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        if (restrictedNetworksChanged) {
21923256601f5e4d94713f59e97b9d4912875c1bdcafJeff Sharkey            normalizePoliciesLocked();
2193be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            updateNetworkRulesLocked();
2194be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        }
2195b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
2196b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
2197af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani    void updateRulesForTempWhitelistChangeLocked() {
2198af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani        final List<UserInfo> users = mUserManager.getUsers();
2199af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani        for (UserInfo user : users) {
2200af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani            for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
2201af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani                int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
2202af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani                int uid = UserHandle.getUid(user.id, appId);
22034a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                updateRuleForAppIdleLocked(uid);
22044a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                updateRuleForDeviceIdleLocked(uid);
2205af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani            }
2206af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani        }
2207af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani    }
2208af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani
22095294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey    private static boolean isUidValidForRules(int uid) {
22105294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey        // allow rules on specific system services, and any apps
22115294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey        if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
2212f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn                || UserHandle.isApp(uid)) {
22135294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey            return true;
22145294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey        }
22155294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey
22165294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey        return false;
22175294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey    }
22185294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey
221915e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani    private boolean isUidIdle(int uid) {
222015e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        final String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
222115e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        final int userId = UserHandle.getUserId(uid);
222215e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani
222315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        for (String packageName : packages) {
222415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani            if (!mUsageStats.isAppIdle(packageName, userId)) {
222515e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani                return false;
222615e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani            }
222715e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        }
222815e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        return true;
222915e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani    }
223015e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani
223115e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani    /**
223215e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani     * Applies network rules to bandwidth and firewall controllers based on uid policy.
223315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani     * @param uid The uid for which to apply the latest policy
223415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani     */
2235497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    void updateRulesForUidLocked(int uid) {
22365294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey        if (!isUidValidForRules(uid)) return;
22375294a2fc2f401cd248a4bc3f0f9ee1e2854f4e9aJeff Sharkey
223888e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackborn        // quick check: if this uid doesn't have INTERNET permission, it doesn't have
223988e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackborn        // network access anyway, so it is a waste to mess with it here.
224088e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackborn        final IPackageManager ipm = AppGlobals.getPackageManager();
224188e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackborn        try {
224288e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackborn            if (ipm.checkUidPermission(Manifest.permission.INTERNET, uid)
224388e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackborn                    != PackageManager.PERMISSION_GRANTED) {
224488e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackborn                return;
224588e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackborn            }
224688e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackborn        } catch (RemoteException e) {
224788e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackborn        }
224888e98dfa59e68a860d8c3b462ec03bc0b06d6b5cDianne Hackborn
2249497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
2250497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn        final boolean uidForeground = isUidForegroundLocked(uid);
2251d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
2252c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // derive active rules based on policy and active state
225315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani
2254af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani        int appId = UserHandle.getAppId(uid);
2255c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        int uidRules = RULE_ALLOW_ALL;
22564a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn        if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
2257fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey            // uid in background, and policy says to block metered data
2258fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey            uidRules = RULE_REJECT_METERED;
2259be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn        } else if (mRestrictBackground) {
2260be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            if (!uidForeground) {
2261be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                // uid in background, and global background disabled
2262be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                uidRules = RULE_REJECT_METERED;
2263be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            }
2264b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        } else if (mRestrictPower) {
22654a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            final boolean whitelisted = mPowerSaveWhitelistExceptIdleAppIds.get(appId)
2266af575b9f8e1b59be9c8862b6a65c0dcb88145a23Amith Yamasani                    || mPowerSaveTempWhitelistAppIds.get(appId);
2267be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            if (!whitelisted && !uidForeground
2268be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                    && (uidPolicy & POLICY_ALLOW_BACKGROUND_BATTERY_SAVE) == 0) {
2269be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                // uid is in background, restrict power use mode is on (so we want to
2270be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                // restrict all background network access), and this uid is not on the
2271be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                // white list of those allowed background access.
2272be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn                uidRules = RULE_REJECT_METERED;
2273be7c50e0a14e91330ce13161bc14a33d34ff6acaDianne Hackborn            }
2274b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
2275d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey
227615e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        final int oldRules = mUidRules.get(uid);
2277c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
2278350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        if (uidRules == RULE_ALLOW_ALL) {
2279350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            mUidRules.delete(uid);
2280350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        } else {
2281350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey            mUidRules.put(uid, uidRules);
2282350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        }
2283c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey
228415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        // Update bandwidth rules if necessary
228515e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        final boolean oldRejectMetered = (oldRules & RULE_REJECT_METERED) != 0;
2286fdfef57f498e3021a34342538aef9f1c7ccbae78Jeff Sharkey        final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
228715e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        if (oldRejectMetered != rejectMetered) {
228815e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani            setUidNetworkRules(uid, rejectMetered);
228915e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        }
229015e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani
2291c006f1aec15454782c35e028ad64d79a5c161cc1Jeff Sharkey        // dispatch changed rule to existing listeners
229215e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        if (oldRules != uidRules) {
229315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani            mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
229415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        }
2295b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
2296b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        try {
2297b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            // adjust stats accounting based on foreground status
2298b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            mNetworkStats.setUidForeground(uid, uidForeground);
2299b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        } catch (RemoteException e) {
2300b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
2301b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
23024414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    }
23034414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey
23048dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen    private class AppIdleStateChangeListener
23058dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen            extends UsageStatsManagerInternal.AppIdleStateChangeListener {
23068dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen
23078dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen        @Override
23088dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen        public void onAppIdleStateChanged(String packageName, int userId, boolean idle) {
23098dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen            try {
23108dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen                int uid = mContext.getPackageManager().getPackageUid(packageName, userId);
23118dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen                synchronized (mRulesLock) {
23124a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn                    updateRuleForAppIdleLocked(uid);
23138dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen                }
23148dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen            } catch (NameNotFoundException nnfe) {
23158dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen            }
23168dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen        }
23178dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen
23188dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen        @Override
23198dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen        public void onParoleStateChanged(boolean isParoleOn) {
232015e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani            synchronized (mRulesLock) {
23218dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen                updateRulesForAppIdleParoleLocked();
232215e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani            }
232315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        }
232415e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani    }
232515e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani
23264414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    private Handler.Callback mHandlerCallback = new Handler.Callback() {
2327bfdd680ab44da173a4a39fcd6feccdebb9d1f855Jeff Sharkey        @Override
23284414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey        public boolean handleMessage(Message msg) {
23294414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey            switch (msg.what) {
23304414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                case MSG_RULES_CHANGED: {
23314414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int uid = msg.arg1;
23324414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int uidRules = msg.arg2;
23334414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int length = mListeners.beginBroadcast();
23344414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    for (int i = 0; i < length; i++) {
23354414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
23364414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        if (listener != null) {
23374414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            try {
23384414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                                listener.onUidRulesChanged(uid, uidRules);
23394414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            } catch (RemoteException e) {
23404414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            }
23414414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        }
23424414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    }
23434414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    mListeners.finishBroadcast();
23444414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    return true;
23454414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                }
23464414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                case MSG_METERED_IFACES_CHANGED: {
23474414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final String[] meteredIfaces = (String[]) msg.obj;
23484414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    final int length = mListeners.beginBroadcast();
23494414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    for (int i = 0; i < length; i++) {
23504414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
23514414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        if (listener != null) {
23524414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            try {
23534414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                                listener.onMeteredIfacesChanged(meteredIfaces);
23544414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            } catch (RemoteException e) {
23554414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                            }
23564414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                        }
23574414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    }
23584414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    mListeners.finishBroadcast();
23594414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    return true;
23604414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                }
23617e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                case MSG_LIMIT_REACHED: {
23627e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                    final String iface = (String) msg.obj;
23637e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey
2364684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey                    maybeRefreshTrustedTime();
23657e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                    synchronized (mRulesLock) {
23667e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                        if (mMeteredIfaces.contains(iface)) {
23677e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                            try {
23687e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                                // force stats update to make sure we have
23697e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                                // numbers that caused alert to trigger.
23707e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                                mNetworkStats.forceUpdate();
23717e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                            } catch (RemoteException e) {
23727e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                                // ignored; service lives in system_server
23737e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                            }
23747e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey
23757e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                            updateNetworkEnabledLocked();
23767e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                            updateNotificationsLocked();
23777e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                        }
23787e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                    }
23797e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                    return true;
23807e25b0ea8891ffc0ac472d61f21610a9ac4e270aJeff Sharkey                }
23811f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                case MSG_RESTRICT_BACKGROUND_CHANGED: {
23821f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                    final boolean restrictBackground = msg.arg1 != 0;
23831f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                    final int length = mListeners.beginBroadcast();
23841f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                    for (int i = 0; i < length; i++) {
23851f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                        final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
23861f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                        if (listener != null) {
23871f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                            try {
23881f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                                listener.onRestrictBackgroundChanged(restrictBackground);
23891f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                            } catch (RemoteException e) {
23901f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                            }
23911f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                        }
23921f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                    }
23931f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                    mListeners.finishBroadcast();
2394e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                    return true;
2395e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                }
2396e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                case MSG_ADVISE_PERSIST_THRESHOLD: {
2397e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                    final long lowestRule = (Long) msg.obj;
2398e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                    try {
2399e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                        // make sure stats are recorded frequently enough; we aim
2400e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                        // for 2MB threshold for 2GB/month rules.
2401e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                        final long persistThreshold = lowestRule / 1000;
2402e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                        mNetworkStats.advisePersistThreshold(persistThreshold);
2403e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                    } catch (RemoteException e) {
2404e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                        // ignored; service lives in system_server
2405e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                    }
2406e19f39b79c831aea4d51a3309025acdf69d1e609Jeff Sharkey                    return true;
24071f8ea2dcd1ed3cde4b84fbb27b5a55b3fea7ff2aJeff Sharkey                }
24080abe556d28f5f5d395559cc6567b05939d1b2640Jeff Sharkey                case MSG_SCREEN_ON_CHANGED: {
24090abe556d28f5f5d395559cc6567b05939d1b2640Jeff Sharkey                    updateScreenOn();
24100abe556d28f5f5d395559cc6567b05939d1b2640Jeff Sharkey                    return true;
24110abe556d28f5f5d395559cc6567b05939d1b2640Jeff Sharkey                }
24124414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                default: {
24134414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey                    return false;
2414af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey                }
2415af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey            }
2416af11d4859582a9736aa204562f0beac5a7d60934Jeff Sharkey        }
24174414cea13908b8230640f84ef39603d68ff9c377Jeff Sharkey    };
241822c055e6424e0e9579711545d8f4800c0f796db8Jeff Sharkey
241941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private void setInterfaceQuota(String iface, long quotaBytes) {
2420b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        try {
242141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.setInterfaceQuota(iface, quotaBytes);
2422b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (IllegalStateException e) {
2423b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem setting interface quota", e);
2424b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (RemoteException e) {
2425b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
2426b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
2427b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
2428b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
2429b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private void removeInterfaceQuota(String iface) {
2430b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        try {
243141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.removeInterfaceQuota(iface);
2432b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (IllegalStateException e) {
2433b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem removing interface quota", e);
2434b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (RemoteException e) {
2435b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
243641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        }
243741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
243841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
2439b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
2440b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        try {
244141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey            mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
2442b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (IllegalStateException e) {
2443b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem setting uid rules", e);
2444b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        } catch (RemoteException e) {
244515e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani            // ignored; service lives in system_server
244615e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        }
244715e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani    }
244815e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani
244915e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani    /**
2450b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen     * Set uid rules on a particular firewall chain. This is going to synchronize the rules given
2451b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen     * here to netd.  It will clean up dead rules and make sure the target chain only contains rules
2452b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen     * specified here.
2453b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen     */
2454b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen    private void setUidFirewallRules(int chain, SparseIntArray uidRules) {
2455b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        try {
2456b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            int size = uidRules.size();
2457b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            int[] uids = new int[size];
2458b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            int[] rules = new int[size];
2459b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            for(int index = size - 1; index >= 0; --index) {
2460b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen                uids[index] = uidRules.keyAt(index);
2461b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen                rules[index] = uidRules.valueAt(index);
2462b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            }
2463b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            mNetworkManager.setFirewallUidRules(chain, uids, rules);
2464b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        } catch (IllegalStateException e) {
2465b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            Log.wtf(TAG, "problem setting firewall uid rules", e);
2466b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        } catch (RemoteException e) {
2467b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            // ignored; service lives in system_server
2468b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        }
2469b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen    }
2470b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen
2471b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen    /**
247215e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani     * Add or remove a uid to the firewall blacklist for all network ifaces.
247315e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani     */
24744a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn    private void setUidFirewallRule(int chain, int uid, int rule) {
247515e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        try {
24764a503b1ece485d44c15eb02ec2bcd464b46e6f7fDianne Hackborn            mNetworkManager.setFirewallUidRule(chain, uid, rule);
247715e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        } catch (IllegalStateException e) {
247815e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani            Log.wtf(TAG, "problem setting firewall uid rules", e);
247915e47235c055495ec0ccc24768a6746a960d3a61Amith Yamasani        } catch (RemoteException e) {
2480b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
2481b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey        }
2482b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey    }
2483b3f19ca36c8c1301893c621d8f2150e06210722cJeff Sharkey
2484b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen    /**
2485b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen     * Add or remove a uid to the firewall blacklist for all network ifaces.
2486b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen     */
24878dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen    private void enableFirewallChainLocked(int chain, boolean enable) {
2488b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        if (mFirewallChainStates.indexOfKey(chain) >= 0 &&
2489b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen                mFirewallChainStates.get(chain) == enable) {
2490b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            // All is the same, nothing to do.
2491b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            return;
2492b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        }
24938dca36dc8a5d17315775ce216689addc5bd9be00Xiaohui Chen        mFirewallChainStates.put(chain, enable);
2494b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        try {
2495b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            mNetworkManager.setFirewallChainEnabled(chain, enable);
2496b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        } catch (IllegalStateException e) {
2497b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            Log.wtf(TAG, "problem enable firewall chain", e);
2498b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        } catch (RemoteException e) {
2499b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen            // ignored; service lives in system_server
2500b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen        }
2501b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen    }
2502b41c9f7f39939cee8d226eb5e506c3f0573f44f5Xiaohui Chen
25038e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    private long getTotalBytes(NetworkTemplate template, long start, long end) {
25048e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        try {
2505b52e3e55098c4a6e3dbfe19885895411cfb38911Jeff Sharkey            return mNetworkStats.getNetworkTotalBytes(template, start, end);
250663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        } catch (RuntimeException e) {
250763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            Slog.w(TAG, "problem reading network stats: " + e);
250863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            return 0;
25098e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        } catch (RemoteException e) {
2510b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
2511b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            return 0;
25128e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        }
25138e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    }
25148e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
25158c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey    private boolean isBandwidthControlEnabled() {
25168c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey        final long token = Binder.clearCallingIdentity();
25178c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey        try {
25188c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey            return mNetworkManager.isBandwidthControlEnabled();
25198c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey        } catch (RemoteException e) {
25208c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey            // ignored; service lives in system_server
25218c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey            return false;
25228c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey        } finally {
25238c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey            Binder.restoreCallingIdentity(token);
25248c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey        }
25258c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey    }
25268c1dc72b1402d55dae388a294476565b2473a87aJeff Sharkey
2527684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey    /**
2528684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey     * Try refreshing {@link #mTime} when stale.
2529684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey     */
2530497175beffe26336c092ee11a67b90f79dcdaca7Dianne Hackborn    void maybeRefreshTrustedTime() {
2531684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey        if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
25328e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey            mTime.forceRefresh();
25338e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        }
2534684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey    }
25358e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
2536684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey    private long currentTimeMillis() {
25378e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey        return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
25388e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey    }
25398e28b7d78232f6cf08739ca0d129cc7f9e650801Jeff Sharkey
25403a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey    private static Intent buildAllowBackgroundDataIntent() {
25413a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey        return new Intent(ACTION_ALLOW_BACKGROUND);
25423a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey    }
25433a844fcf5a0e70a19c38dc500306b9ebe4e1413bJeff Sharkey
25440e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    private static Intent buildSnoozeWarningIntent(NetworkTemplate template) {
25450e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        final Intent intent = new Intent(ACTION_SNOOZE_WARNING);
25460e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
25470e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey        return intent;
25480e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey    }
25490e2e5f8b564bebd5798c9fa387fbff96429ab5d2Jeff Sharkey
255041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
255141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        final Intent intent = new Intent();
255241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.setComponent(new ComponentName(
255341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity"));
255441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
255541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
255641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        return intent;
255741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
255841ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
255941ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    private static Intent buildViewDataUsageIntent(NetworkTemplate template) {
256041ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        final Intent intent = new Intent();
256141ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.setComponent(new ComponentName(
256241ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey                "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
256341ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
256441ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
256541ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey        return intent;
256641ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey    }
256741ff7ec82422a5b6d00892afdb3232bc0e53d851Jeff Sharkey
25688b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    @VisibleForTesting
2569163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    public void addIdleHandler(IdleHandler handler) {
2570163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        mHandler.getLooper().getQueue().addIdleHandler(handler);
2571163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    }
2572163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
25731b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
25741b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        final int size = source.size();
25751b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        for (int i = 0; i < size; i++) {
25761b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey            target.put(source.keyAt(i), true);
25771b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey        }
25781b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey    }
25791b861278a2051f53ce7955fb7992fa536dc975d9Jeff Sharkey
2580f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott    @Override
2581f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott    public void factoryReset(String subscriber) {
2582f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott        mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
2583f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott
2584e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott        if (mUserManager.hasUserRestriction(UserManager.DISALLOW_NETWORK_RESET)) {
2585e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott            return;
2586e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott        }
2587e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott
2588f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott        // Turn mobile data limit off
25899a9a1d923d476ab21624fa9c5da69e0a4daf51fcStuart Scott        NetworkPolicy[] policies = getNetworkPolicies(mContext.getOpPackageName());
2590f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott        NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriber);
2591f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott        for (NetworkPolicy policy : policies) {
2592f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott            if (policy.template.equals(template)) {
2593f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott                policy.limitBytes = NetworkPolicy.LIMIT_DISABLED;
2594f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott                policy.inferred = false;
2595f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott                policy.clearSnooze();
2596f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott            }
2597f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott        }
2598f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott        setNetworkPolicies(policies);
2599f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott
2600f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott        // Turn restrict background data off
2601f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott        setRestrictBackground(false);
2602f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott
2603e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott        if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_APPS_CONTROL)) {
2604e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott            // Remove app's "restrict background data" flag
2605e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott            for (int uid : getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) {
2606e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott                setUidPolicy(uid, POLICY_NONE);
2607e3e314df4d52881225326d426a76e3e7f1bc40d3Stuart Scott            }
2608f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott        }
2609f1fb39763d87dabe254b6ed64ac8f20145035bc0Stuart Scott    }
2610d5cdd597b895a48ffa9a8e39f8a2504cd9b905c4Jeff Sharkey}
2611