19e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt/*
29e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * Copyright (C) 2007 The Android Open Source Project
39e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt *
49e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
59e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * you may not use this file except in compliance with the License.
69e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * You may obtain a copy of the License at
79e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt *
89e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt *      http://www.apache.org/licenses/LICENSE-2.0
99e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt *
109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * Unless required by applicable law or agreed to in writing, software
119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * See the License for the specific language governing permissions and
149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt * limitations under the License.
159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt */
169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltpackage com.android.server;
189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.app.AlarmManager;
209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.app.Notification;
219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.app.NotificationManager;
229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.app.PendingIntent;
239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.BroadcastReceiver;
2481aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwaltimport android.content.ContentResolver;
259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.Context;
269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.Intent;
279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.IntentFilter;
289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.pm.PackageManager;
299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.content.res.Resources;
3081aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwaltimport android.database.ContentObserver;
31fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwaltimport android.net.INetworkManagementEventObserver;
329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.net.IThrottleManager;
339a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkeyimport android.net.NetworkStats;
349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.net.ThrottleManager;
359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.Binder;
36b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwaltimport android.os.Environment;
379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.Handler;
389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.HandlerThread;
399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.IBinder;
409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.INetworkManagementService;
419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.Looper;
429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.Message;
439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.RemoteException;
449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.ServiceManager;
459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.SystemClock;
469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.os.SystemProperties;
479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.provider.Settings;
48e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwaltimport android.telephony.TelephonyManager;
49fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwaltimport android.text.TextUtils;
50b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkeyimport android.util.NtpTrustedTime;
519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.util.Slog;
52b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkeyimport android.util.TrustedTime;
535f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt
54104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkeyimport com.android.internal.R;
55104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkeyimport com.android.internal.telephony.TelephonyProperties;
56104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey
57b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwaltimport java.io.BufferedWriter;
58b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwaltimport java.io.File;
599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.io.FileDescriptor;
60b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwaltimport java.io.FileInputStream;
61b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwaltimport java.io.FileWriter;
62b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwaltimport java.io.IOException;
639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.io.PrintWriter;
649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.util.Calendar;
659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.util.GregorianCalendar;
669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.util.Random;
67b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkeyimport java.util.concurrent.atomic.AtomicInteger;
68b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkeyimport java.util.concurrent.atomic.AtomicLong;
699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt// TODO - add comments - reference the ThrottleManager for public API
719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltpublic class ThrottleService extends IThrottleManager.Stub {
729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String TESTING_ENABLED_PROPERTY = "persist.throttle.testing";
749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String TAG = "ThrottleService";
76bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt    private static final boolean DBG = true;
77bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt    private static final boolean VDBG = false;
789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private Handler mHandler;
799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private HandlerThread mThread;
809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private Context mContext;
829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
83fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt    private static final int INITIAL_POLL_DELAY_SEC = 90;
849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int TESTING_POLLING_PERIOD_SEC = 60 * 1;
857171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    private static final int TESTING_RESET_PERIOD_SEC = 60 * 10;
86d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt    private static final long TESTING_THRESHOLD = 1 * 1024 * 1024;
879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
88b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    private static final long MAX_NTP_CACHE_AGE = 24 * 60 * 60 * 1000;
89b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
90b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    private long mMaxNtpCacheAge = MAX_NTP_CACHE_AGE;
91b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
92d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt    private int mPolicyPollPeriodSec;
9339e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt    private AtomicLong mPolicyThreshold;
9439e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt    private AtomicInteger mPolicyThrottleValue;
959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private int mPolicyResetDay; // 1-28
96d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt    private int mPolicyNotificationsAllowedMask;
979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private long mLastRead; // read byte count from last poll
999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private long mLastWrite; // write byte count from last poll
1009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String ACTION_POLL = "com.android.server.ThrottleManager.action.POLL";
1029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static int POLL_REQUEST = 0;
1039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private PendingIntent mPendingPollIntent;
1049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String ACTION_RESET = "com.android.server.ThorottleManager.action.RESET";
1059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static int RESET_REQUEST = 1;
1069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private PendingIntent mPendingResetIntent;
1079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private INetworkManagementService mNMService;
1099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private AlarmManager mAlarmManager;
1109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private NotificationManager mNotificationManager;
1119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private DataRecorder mRecorder;
1139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
114d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt    private String mIface;
1159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int NOTIFICATION_WARNING   = 2;
1179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private Notification mThrottlingNotification;
1199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private boolean mWarningNotificationSent = false;
1209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
121fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt    private InterfaceObserver mInterfaceObserver;
12281aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt    private SettingsObserver mSettingsObserver;
12381aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt
12439e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt    private AtomicInteger mThrottleIndex; // 0 for none, 1 for first throttle val, 2 for next, etc
12581aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt    private static final int THROTTLE_INDEX_UNINITIALIZED = -1;
12681aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt    private static final int THROTTLE_INDEX_UNTHROTTLED   =  0;
12781aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt
128b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    private Intent mPollStickyBroadcast;
129b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
130b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    private TrustedTime mTime;
131b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
132b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    private static INetworkManagementService getNetworkManagementService() {
133b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        final IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
134b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        return INetworkManagementService.Stub.asInterface(b);
135b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
1367171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
1379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public ThrottleService(Context context) {
138104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        this(context, getNetworkManagementService(), NtpTrustedTime.getInstance(context),
139b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                context.getResources().getString(R.string.config_datause_iface));
140b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
141b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
142b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    public ThrottleService(Context context, INetworkManagementService nmService, TrustedTime time,
143b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            String iface) {
1445a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt        if (VDBG) Slog.v(TAG, "Starting ThrottleService");
1459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext = context;
1469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
14724488bd0946f2342fcc725ce55c1347c0698b1e9Robert Greenwalt        mPolicyThreshold = new AtomicLong();
14824488bd0946f2342fcc725ce55c1347c0698b1e9Robert Greenwalt        mPolicyThrottleValue = new AtomicInteger();
14924488bd0946f2342fcc725ce55c1347c0698b1e9Robert Greenwalt        mThrottleIndex = new AtomicInteger();
15024488bd0946f2342fcc725ce55c1347c0698b1e9Robert Greenwalt
151b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        mIface = iface;
1529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
1539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Intent pollIntent = new Intent(ACTION_POLL, null);
1549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
1559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Intent resetIntent = new Intent(ACTION_RESET, null);
1569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mPendingResetIntent = PendingIntent.getBroadcast(mContext, RESET_REQUEST, resetIntent, 0);
1579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
158b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        mNMService = nmService;
159b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        mTime = time;
1609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mNotificationManager = (NotificationManager)mContext.getSystemService(
1629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Context.NOTIFICATION_SERVICE);
1639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
1649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
165fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt    private static class InterfaceObserver extends INetworkManagementEventObserver.Stub {
166fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        private int mMsg;
167fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        private Handler mHandler;
168fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        private String mIface;
169fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
170fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        InterfaceObserver(Handler handler, int msg, String iface) {
171fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            super();
172fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            mHandler = handler;
173fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            mMsg = msg;
174fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            mIface = iface;
175fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        }
176fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
177f59c7d0f2ac8d489b6d8118543a57ea4a603eacfMike J. Chen        public void interfaceStatusChanged(String iface, boolean up) {
178f59c7d0f2ac8d489b6d8118543a57ea4a603eacfMike J. Chen            if (up) {
179fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                if (TextUtils.equals(iface, mIface)) {
180fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                    mHandler.obtainMessage(mMsg).sendToTarget();
181fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                }
182fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            }
183fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        }
184fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
185f59c7d0f2ac8d489b6d8118543a57ea4a603eacfMike J. Chen        public void interfaceLinkStateChanged(String iface, boolean up) {
186f59c7d0f2ac8d489b6d8118543a57ea4a603eacfMike J. Chen        }
187f59c7d0f2ac8d489b6d8118543a57ea4a603eacfMike J. Chen
188fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        public void interfaceAdded(String iface) {
189fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            // TODO - an interface added in the UP state should also trigger a StatusChanged
190fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            // notification..
191fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            if (TextUtils.equals(iface, mIface)) {
192fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                mHandler.obtainMessage(mMsg).sendToTarget();
193fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            }
194fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        }
195fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
196fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        public void interfaceRemoved(String iface) {}
19712b933d0d9252decaae9fee2456bb1e1cd94c085JP Abgrall        public void limitReached(String limitName, String iface) {}
198fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt    }
199fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
200fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
20181aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt    private static class SettingsObserver extends ContentObserver {
20281aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        private int mMsg;
20381aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        private Handler mHandler;
20481aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        SettingsObserver(Handler handler, int msg) {
20581aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            super(handler);
20681aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            mHandler = handler;
20781aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            mMsg = msg;
20881aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        }
20981aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt
210b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        void register(Context context) {
21181aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            ContentResolver resolver = context.getContentResolver();
21281aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
21381aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt                    Settings.Secure.THROTTLE_POLLING_SEC), false, this);
21481aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
215d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    Settings.Secure.THROTTLE_THRESHOLD_BYTES), false, this);
21681aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
217d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    Settings.Secure.THROTTLE_VALUE_KBITSPS), false, this);
21881aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
21981aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt                    Settings.Secure.THROTTLE_RESET_DAY), false, this);
22081aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
22181aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt                    Settings.Secure.THROTTLE_NOTIFICATION_TYPE), false, this);
22281aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
223d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    Settings.Secure.THROTTLE_HELP_URI), false, this);
224d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
225d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt                    Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC), false, this);
22681aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        }
22781aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt
228b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        void unregister(Context context) {
229b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            final ContentResolver resolver = context.getContentResolver();
230b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            resolver.unregisterContentObserver(this);
231b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        }
232b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
23381aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        @Override
23481aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        public void onChange(boolean selfChange) {
23581aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            mHandler.obtainMessage(mMsg).sendToTarget();
23681aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        }
23781aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt    }
23881aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt
2399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private void enforceAccessPermission() {
2409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
2419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                android.Manifest.permission.ACCESS_NETWORK_STATE,
2429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                "ThrottleService");
2439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
2449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
24505d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt    private long ntpToWallTime(long ntpTime) {
246b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        // get time quickly without worrying about trusted state
247b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        long bestNow = mTime.hasCache() ? mTime.currentTimeMillis()
248b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                : System.currentTimeMillis();
24905d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt        long localNow = System.currentTimeMillis();
25005d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt        return localNow + (ntpTime - bestNow);
25105d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt    }
25205d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt
253cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
2547171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    // return time in the local, system wall time, correcting for the use of ntp
25505d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt
25639e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt    public long getResetTime(String iface) {
2579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
2587171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        long resetTime = 0;
259cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff        if (mRecorder != null) {
26039e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            resetTime = mRecorder.getPeriodEnd();
261d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt        }
26239e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt        resetTime = ntpToWallTime(resetTime);
2637171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        return resetTime;
2649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
265cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff
266cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
26705d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt    // return time in the local, system wall time, correcting for the use of ntp
26839e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt    public long getPeriodStartTime(String iface) {
2697171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        long startTime = 0;
27039e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt        enforceAccessPermission();
271cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff        if (mRecorder != null) {
27239e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            startTime = mRecorder.getPeriodStart();
273d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt        }
27439e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt        startTime = ntpToWallTime(startTime);
2757171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        return startTime;
2769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
2779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    //TODO - a better name?  getCliffByteCountThreshold?
278cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
27939e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt    public long getCliffThreshold(String iface, int cliff) {
2809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
281cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff        if (cliff == 1) {
28239e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt           return mPolicyThreshold.get();
2839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
2849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
2859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
2869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // TODO - a better name? getThrottleRate?
287cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
28839e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt    public int getCliffLevel(String iface, int cliff) {
2899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
290cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff        if (cliff == 1) {
29139e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            return mPolicyThrottleValue.get();
2929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
2939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
2949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
2959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
296c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff    public String getHelpUri() {
297c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff        enforceAccessPermission();
298c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff        return Settings.Secure.getString(mContext.getContentResolver(),
299c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff                    Settings.Secure.THROTTLE_HELP_URI);
300c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff    }
301c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff
302cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
30339e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt    public long getByteCount(String iface, int dir, int period, int ago) {
3049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
30539e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt        if ((period == ThrottleManager.PERIOD_CYCLE) && (mRecorder != null)) {
3069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (dir == ThrottleManager.DIRECTION_TX) return mRecorder.getPeriodTx(ago);
3079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (dir == ThrottleManager.DIRECTION_RX) return mRecorder.getPeriodRx(ago);
3089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
3099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
3109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
3119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // TODO - a better name - getCurrentThrottleRate?
313cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
31439e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt    public int getThrottle(String iface) {
3159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
31639e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt        if (mThrottleIndex.get() == 1) {
31739e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            return mPolicyThrottleValue.get();
3189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
3199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
3209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
3219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    void systemReady() {
3235a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt        if (VDBG) Slog.v(TAG, "systemReady");
3249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext.registerReceiver(
3259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            new BroadcastReceiver() {
3269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                @Override
3279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                public void onReceive(Context context, Intent intent) {
328b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                    dispatchPoll();
3299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
3309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }, new IntentFilter(ACTION_POLL));
3319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext.registerReceiver(
3339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            new BroadcastReceiver() {
3349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                @Override
3359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                public void onReceive(Context context, Intent intent) {
336b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                    dispatchReset();
3379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
3389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }, new IntentFilter(ACTION_RESET));
3399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
340c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt        // use a new thread as we don't want to stall the system for file writes
341c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt        mThread = new HandlerThread(TAG);
342c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt        mThread.start();
343c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt        mHandler = new MyHandler(mThread.getLooper());
344c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt        mHandler.obtainMessage(EVENT_REBOOT_RECOVERY).sendToTarget();
345c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt
346c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt        mInterfaceObserver = new InterfaceObserver(mHandler, EVENT_IFACE_UP, mIface);
347c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt        try {
348c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt            mNMService.registerObserver(mInterfaceObserver);
349c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt        } catch (RemoteException e) {
350c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt            Slog.e(TAG, "Could not register InterfaceObserver " + e);
351c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt        }
352c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt
353c76c15e255b01412e5cda33b606d7672713b6665Robert Greenwalt        mSettingsObserver = new SettingsObserver(mHandler, EVENT_POLICY_CHANGED);
354b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        mSettingsObserver.register(mContext);
355b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
356b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
357b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    void shutdown() {
358b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        // TODO: eventually connect with ShutdownThread to persist stats during
359b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        // graceful shutdown.
360b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
361b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        if (mThread != null) {
362b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            mThread.quit();
363b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        }
364b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
365b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        if (mSettingsObserver != null) {
366b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            mSettingsObserver.unregister(mContext);
367b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        }
368b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
369b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        if (mPollStickyBroadcast != null) {
370b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            mContext.removeStickyBroadcast(mPollStickyBroadcast);
371b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        }
3729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
3739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
374b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    void dispatchPoll() {
375b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        mHandler.obtainMessage(EVENT_POLL_ALARM).sendToTarget();
376b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
377b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey
378b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    void dispatchReset() {
379b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget();
380b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey    }
3819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_REBOOT_RECOVERY = 0;
3839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_POLICY_CHANGED  = 1;
3849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_POLL_ALARM      = 2;
3859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_RESET_ALARM     = 3;
386fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt    private static final int EVENT_IFACE_UP        = 4;
3879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private class MyHandler extends Handler {
3889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public MyHandler(Looper l) {
3899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            super(l);
3909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
3919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        @Override
3939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public void handleMessage(Message msg) {
3949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            switch (msg.what) {
3959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_REBOOT_RECOVERY:
3969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onRebootRecovery();
3979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                break;
3989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_POLICY_CHANGED:
3999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onPolicyChanged();
4009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                break;
4019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_POLL_ALARM:
4029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onPollAlarm();
4039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                break;
4049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_RESET_ALARM:
4059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onResetAlarm();
406fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                break;
407fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            case EVENT_IFACE_UP:
408fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                onIfaceUp();
4099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
4119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onRebootRecovery() {
4135a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt            if (VDBG) Slog.v(TAG, "onRebootRecovery");
4149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // check for sim change TODO
4159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // reregister for notification of policy change
4169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
41739e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            mThrottleIndex.set(THROTTLE_INDEX_UNINITIALIZED);
4189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mRecorder = new DataRecorder(mContext, ThrottleService.this);
4209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // get policy
4229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mHandler.obtainMessage(EVENT_POLICY_CHANGED).sendToTarget();
423fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt
424fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt            // if we poll now we won't have network connectivity or even imsi access
425fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt            // queue up a poll to happen in a little while - after ntp and imsi are avail
426fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt            // TODO - make this callback based (ie, listen for notificaitons)
427fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_POLL_ALARM),
428fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt                    INITIAL_POLL_DELAY_SEC * 1000);
4299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
4309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        // check for new policy info (threshold limit/value/etc)
4329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onPolicyChanged() {
4339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            boolean testing = SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true");
4349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
435d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            int pollingPeriod = mContext.getResources().getInteger(
4367171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    R.integer.config_datause_polling_period_sec);
4379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mPolicyPollPeriodSec = Settings.Secure.getInt(mContext.getContentResolver(),
4389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Settings.Secure.THROTTLE_POLLING_SEC, pollingPeriod);
4399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - remove testing stuff?
441d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            long defaultThreshold = mContext.getResources().getInteger(
4427171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    R.integer.config_datause_threshold_bytes);
443d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            int defaultValue = mContext.getResources().getInteger(
4447171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    R.integer.config_datause_throttle_kbitsps);
44539e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            long threshold = Settings.Secure.getLong(mContext.getContentResolver(),
44639e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                    Settings.Secure.THROTTLE_THRESHOLD_BYTES, defaultThreshold);
44739e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            int value = Settings.Secure.getInt(mContext.getContentResolver(),
44839e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                    Settings.Secure.THROTTLE_VALUE_KBITSPS, defaultValue);
44939e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt
45039e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            mPolicyThreshold.set(threshold);
45139e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            mPolicyThrottleValue.set(value);
45239e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            if (testing) {
45339e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                mPolicyPollPeriodSec = TESTING_POLLING_PERIOD_SEC;
45439e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                mPolicyThreshold.set(TESTING_THRESHOLD);
4559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
456d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt
4579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mPolicyResetDay = Settings.Secure.getInt(mContext.getContentResolver(),
4589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Settings.Secure.THROTTLE_RESET_DAY, -1);
4599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (mPolicyResetDay == -1 ||
4609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    ((mPolicyResetDay < 1) || (mPolicyResetDay > 28))) {
4619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Random g = new Random();
4629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPolicyResetDay = 1 + g.nextInt(28); // 1-28
4639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Settings.Secure.putInt(mContext.getContentResolver(),
4649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Settings.Secure.THROTTLE_RESET_DAY, mPolicyResetDay);
4659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
46639e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            if (mIface == null) {
46739e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                mPolicyThreshold.set(0);
4689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
470d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            int defaultNotificationType = mContext.getResources().getInteger(
4717171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    R.integer.config_datause_notification_type);
4729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mPolicyNotificationsAllowedMask = Settings.Secure.getInt(mContext.getContentResolver(),
473d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    Settings.Secure.THROTTLE_NOTIFICATION_TYPE, defaultNotificationType);
4749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
475b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            final int maxNtpCacheAgeSec = Settings.Secure.getInt(mContext.getContentResolver(),
476b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                    Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC,
477b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                    (int) (MAX_NTP_CACHE_AGE / 1000));
478b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            mMaxNtpCacheAge = maxNtpCacheAgeSec * 1000;
479d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt
480687f2a07bf76863fba4a7dc1c92ae69cca049039Robert Greenwalt            if (VDBG || (mPolicyThreshold.get() != 0)) {
4815a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                Slog.d(TAG, "onPolicyChanged testing=" + testing +", period=" +
482687f2a07bf76863fba4a7dc1c92ae69cca049039Robert Greenwalt                        mPolicyPollPeriodSec + ", threshold=" + mPolicyThreshold.get() +
483687f2a07bf76863fba4a7dc1c92ae69cca049039Robert Greenwalt                        ", value=" + mPolicyThrottleValue.get() + ", resetDay=" + mPolicyResetDay +
484b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                        ", noteType=" + mPolicyNotificationsAllowedMask + ", mMaxNtpCacheAge=" +
485b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                        mMaxNtpCacheAge);
4865a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt            }
4879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4885bf16d6e8c0afae4e60590ffbdbed1bd6e73ff8bRobert Greenwalt            // force updates
48939e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            mThrottleIndex.set(THROTTLE_INDEX_UNINITIALIZED);
4905bf16d6e8c0afae4e60590ffbdbed1bd6e73ff8bRobert Greenwalt
49181aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            onResetAlarm();
4929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
493b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            onPollAlarm();
494b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt
49581aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            Intent broadcast = new Intent(ThrottleManager.POLICY_CHANGED_ACTION);
49681aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            mContext.sendBroadcast(broadcast);
4979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
4989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onPollAlarm() {
5009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long now = SystemClock.elapsedRealtime();
501b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            long next = now + mPolicyPollPeriodSec * 1000;
5027171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
503b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            // when trusted cache outdated, try refreshing
504b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            if (mTime.getCacheAge() > mMaxNtpCacheAge) {
505b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                if (mTime.forceRefresh()) {
506b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                    if (VDBG) Slog.d(TAG, "updated trusted time, reseting alarm");
507b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                    dispatchReset();
508b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                }
509b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            }
5107171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
5119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long incRead = 0;
5129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long incWrite = 0;
5139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            try {
514e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey                final NetworkStats stats = mNMService.getNetworkStatsSummaryDev();
515b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                final int index = stats.findIndex(mIface, NetworkStats.UID_ALL,
516b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        NetworkStats.SET_DEFAULT, NetworkStats.TAG_NONE);
5179a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
5189a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey                if (index != -1) {
519d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                    final NetworkStats.Entry entry = stats.getValues(index, null);
520d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                    incRead = entry.rxBytes - mLastRead;
521d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                    incWrite = entry.txBytes - mLastWrite;
5229a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey                } else {
5239a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey                    // missing iface, assume stats are 0
5249a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey                    Slog.w(TAG, "unable to find stats for iface " + mIface);
5259a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey                }
5269a13f36cddaad01350bdb5f000167811a1d753c9Jeff Sharkey
5278c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                // handle iface resets - on some device the 3g iface comes and goes and gets
5288c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                // totals reset to 0.  Deal with it
5298c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                if ((incRead < 0) || (incWrite < 0)) {
5308c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                    incRead += mLastRead;
5318c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                    incWrite += mLastWrite;
5328c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                    mLastRead = 0;
5338c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                    mLastWrite = 0;
5348c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                }
535558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey            } catch (IllegalStateException e) {
536558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey                Slog.e(TAG, "problem during onPollAlarm: " + e);
5379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            } catch (RemoteException e) {
538558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey                Slog.e(TAG, "problem during onPollAlarm: " + e);
5399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
540558a23200697d306b75750cf4612cf0717e73537Jeff Sharkey
5415f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt            // don't count this data if we're roaming.
5425f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt            boolean roaming = "true".equals(
5435f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt                    SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING));
5445f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt            if (!roaming) {
5455f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt                mRecorder.addData(incRead, incWrite);
5465f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt            }
5479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long periodRx = mRecorder.getPeriodRx(0);
5499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long periodTx = mRecorder.getPeriodTx(0);
5509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long total = periodRx + periodTx;
551687f2a07bf76863fba4a7dc1c92ae69cca049039Robert Greenwalt            if (VDBG || (mPolicyThreshold.get() != 0)) {
552bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt                Slog.d(TAG, "onPollAlarm - roaming =" + roaming +
5535f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt                        ", read =" + incRead + ", written =" + incWrite + ", new total =" + total);
5549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
5559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mLastRead += incRead;
5569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mLastWrite += incWrite;
5579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            checkThrottleAndPostNotification(total);
5599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Intent broadcast = new Intent(ThrottleManager.THROTTLE_POLL_ACTION);
5619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_READ, periodRx);
5629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_WRITE, periodTx);
56305d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_START, getPeriodStartTime(mIface));
56405d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_END, getResetTime(mIface));
5659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mContext.sendStickyBroadcast(broadcast);
566b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            mPollStickyBroadcast = broadcast;
5679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
568d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            mAlarmManager.cancel(mPendingPollIntent);
5695a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
5709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
5719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
572fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        private void onIfaceUp() {
573fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            // if we were throttled before, be sure and set it again - the iface went down
574fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            // (and may have disappeared all together) and these settings were lost
57539e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            if (mThrottleIndex.get() == 1) {
576fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                try {
577fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                    mNMService.setInterfaceThrottle(mIface, -1, -1);
578fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                    mNMService.setInterfaceThrottle(mIface,
57939e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                            mPolicyThrottleValue.get(), mPolicyThrottleValue.get());
580fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                } catch (Exception e) {
581fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                    Slog.e(TAG, "error setting Throttle: " + e);
582fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                }
583fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            }
584fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        }
585fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
5869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void checkThrottleAndPostNotification(long currentTotal) {
587d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            // is throttling enabled?
58839e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            long threshold = mPolicyThreshold.get();
58939e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            if (threshold == 0) {
590cce83379ef5ddd122ffe6fcce431cb86d059a74bRobert Greenwalt                clearThrottleAndNotification();
5919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return;
5927171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            }
5937171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
5947171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            // have we spoken with an ntp server yet?
5957171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            // this is controversial, but we'd rather err towards not throttling
596b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            if (!mTime.hasCache()) {
597b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                Slog.w(TAG, "missing trusted time, skipping throttle check");
5987171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                return;
5997171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            }
6009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // check if we need to throttle
60239e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            if (currentTotal > threshold) {
60339e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                if (mThrottleIndex.get() != 1) {
60439e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                    mThrottleIndex.set(1);
60539e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                    if (DBG) Slog.d(TAG, "Threshold " + threshold + " exceeded!");
6069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    try {
607d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                        mNMService.setInterfaceThrottle(mIface,
60839e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                                mPolicyThrottleValue.get(), mPolicyThrottleValue.get());
6099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    } catch (Exception e) {
6109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        Slog.e(TAG, "error setting Throttle: " + e);
6119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    }
6129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6137171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    mNotificationManager.cancel(R.drawable.stat_sys_throttled);
6149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6157171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    postNotification(R.string.throttled_notification_title,
6167171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                            R.string.throttled_notification_message,
6177171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                            R.drawable.stat_sys_throttled,
618c87dc6dc90d0953c10051dceb470ff05e2fb9300Robert Greenwalt                            Notification.FLAG_ONGOING_EVENT);
6199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
62139e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                    broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL,
62239e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                            mPolicyThrottleValue.get());
6239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mContext.sendStickyBroadcast(broadcast);
6249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                } // else already up!
6269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            } else {
6275bf16d6e8c0afae4e60590ffbdbed1bd6e73ff8bRobert Greenwalt                clearThrottleAndNotification();
6289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if ((mPolicyNotificationsAllowedMask & NOTIFICATION_WARNING) != 0) {
6299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    // check if we should warn about throttle
630e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // pretend we only have 1/2 the time remaining that we actually do
631e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // if our burn rate in the period so far would have us exceed the limit
632e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // in that 1/2 window, warn the user.
633e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // this gets more generous in the early to middle period and converges back
634e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // to the limit as we move toward the period end.
635e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt
636e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // adding another factor - it must be greater than the total cap/4
637e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // else we may get false alarms very early in the period..  in the first
638e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // tenth of a percent of the period if we used more than a tenth of a percent
639e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // of the cap we'd get a warning and that's not desired.
640e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    long start = mRecorder.getPeriodStart();
641e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    long end = mRecorder.getPeriodEnd();
642e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    long periodLength = end - start;
643e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    long now = System.currentTimeMillis();
644e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    long timeUsed = now - start;
64539e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                    long warningThreshold = 2*threshold*timeUsed/(timeUsed+periodLength);
64639e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                    if ((currentTotal > warningThreshold) && (currentTotal > threshold/4)) {
647e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                        if (mWarningNotificationSent == false) {
648e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                            mWarningNotificationSent = true;
6497171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                            mNotificationManager.cancel(R.drawable.stat_sys_throttled);
6507171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                            postNotification(R.string.throttle_warning_notification_title,
6517171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                                    R.string.throttle_warning_notification_message,
6527171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                                    R.drawable.stat_sys_throttled,
653e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                                    0);
654e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                        }
6559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    } else {
656e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                        if (mWarningNotificationSent == true) {
6577171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                            mNotificationManager.cancel(R.drawable.stat_sys_throttled);
658e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                            mWarningNotificationSent =false;
659e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                        }
6609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    }
6619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
6629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
665c87dc6dc90d0953c10051dceb470ff05e2fb9300Robert Greenwalt        private void postNotification(int titleInt, int messageInt, int icon, int flags) {
6669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Intent intent = new Intent();
6679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - fix up intent
6682a7b730378a0c9d7c3dfbc47e9862169a149d347Robert Greenwalt            intent.setClassName("com.android.phone", "com.android.phone.DataUsage");
6699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
6709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
6729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Resources r = Resources.getSystem();
6749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            CharSequence title = r.getText(titleInt);
6759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            CharSequence message = r.getText(messageInt);
6769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (mThrottlingNotification == null) {
6779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification = new Notification();
6789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification.when = 0;
6799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                // TODO -  fixup icon
6809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification.icon = icon;
6819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification.defaults &= ~Notification.DEFAULT_SOUND;
6829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
683c87dc6dc90d0953c10051dceb470ff05e2fb9300Robert Greenwalt            mThrottlingNotification.flags = flags;
6849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mThrottlingNotification.tickerText = title;
6859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mThrottlingNotification.setLatestEventInfo(mContext, title, message, pi);
6869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mNotificationManager.notify(mThrottlingNotification.icon, mThrottlingNotification);
6889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
69139e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt        private void clearThrottleAndNotification() {
69239e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            if (mThrottleIndex.get() != THROTTLE_INDEX_UNTHROTTLED) {
69339e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                mThrottleIndex.set(THROTTLE_INDEX_UNTHROTTLED);
6949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                try {
695d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    mNMService.setInterfaceThrottle(mIface, -1, -1);
6969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                } catch (Exception e) {
6979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Slog.e(TAG, "error clearing Throttle: " + e);
6989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
6999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
7009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, -1);
7019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mContext.sendStickyBroadcast(broadcast);
7025bf16d6e8c0afae4e60590ffbdbed1bd6e73ff8bRobert Greenwalt                mNotificationManager.cancel(R.drawable.stat_sys_throttled);
7035bf16d6e8c0afae4e60590ffbdbed1bd6e73ff8bRobert Greenwalt                mWarningNotificationSent = false;
7049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
7059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
7069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7077171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        private Calendar calculatePeriodEnd(long now) {
7089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Calendar end = GregorianCalendar.getInstance();
7097171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            end.setTimeInMillis(now);
7109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            int day = end.get(Calendar.DAY_OF_MONTH);
7119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            end.set(Calendar.DAY_OF_MONTH, mPolicyResetDay);
7129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            end.set(Calendar.HOUR_OF_DAY, 0);
7139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            end.set(Calendar.MINUTE, 0);
7148c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt            end.set(Calendar.SECOND, 0);
7158c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt            end.set(Calendar.MILLISECOND, 0);
7169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (day >= mPolicyResetDay) {
7179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                int month = end.get(Calendar.MONTH);
7189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (month == Calendar.DECEMBER) {
7199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    end.set(Calendar.YEAR, end.get(Calendar.YEAR) + 1);
7209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    month = Calendar.JANUARY - 1;
7219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
7229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                end.set(Calendar.MONTH, month + 1);
7239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
7249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - remove!
7269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true")) {
7279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                end = GregorianCalendar.getInstance();
7287171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                end.setTimeInMillis(now);
7299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                end.add(Calendar.SECOND, TESTING_RESET_PERIOD_SEC);
7309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
7319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return end;
7329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
7339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private Calendar calculatePeriodStart(Calendar end) {
7349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Calendar start = (Calendar)end.clone();
7359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            int month = end.get(Calendar.MONTH);
7369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (end.get(Calendar.MONTH) == Calendar.JANUARY) {
7379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                month = Calendar.DECEMBER + 1;
7389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                start.set(Calendar.YEAR, start.get(Calendar.YEAR) - 1);
7399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
7409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            start.set(Calendar.MONTH, month - 1);
7419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - remove!!
7439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true")) {
7449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                start = (Calendar)end.clone();
7459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                start.add(Calendar.SECOND, -TESTING_RESET_PERIOD_SEC);
7469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
7479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return start;
7489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
7499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onResetAlarm() {
751687f2a07bf76863fba4a7dc1c92ae69cca049039Robert Greenwalt            if (VDBG || (mPolicyThreshold.get() != 0)) {
7529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Slog.d(TAG, "onResetAlarm - last period had " + mRecorder.getPeriodRx(0) +
7539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        " bytes read and " + mRecorder.getPeriodTx(0) + " written");
7549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
7559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
756b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            // when trusted cache outdated, try refreshing
757b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            if (mTime.getCacheAge() > mMaxNtpCacheAge) {
758b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                mTime.forceRefresh();
759b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            }
7609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
761b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            // as long as we have a trusted time cache, we always reset alarms,
762b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            // even if the refresh above failed.
763b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            if (mTime.hasCache()) {
764b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                final long now = mTime.currentTimeMillis();
7657171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                Calendar end = calculatePeriodEnd(now);
7667171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                Calendar start = calculatePeriodStart(end);
7679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7687171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                if (mRecorder.setNextPeriod(start, end)) {
76905d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                    onPollAlarm();
7707171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                }
7717171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
7727171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                mAlarmManager.cancel(mPendingResetIntent);
7737171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                long offset = end.getTimeInMillis() - now;
7747171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                // use Elapsed realtime so clock changes don't fool us.
7755a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME,
7767171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                        SystemClock.elapsedRealtime() + offset,
7777171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                        mPendingResetIntent);
7787171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            } else {
779b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                if (VDBG) Slog.d(TAG, "no trusted time, not resetting period");
7807171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            }
7817171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        }
7827171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    }
7837171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
7849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // records bytecount data for a given time and accumulates it into larger time windows
7859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // for logging and other purposes
7869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    //
7879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // since time can be changed (user or network action) we will have to track the time of the
7889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // last recording and deal with it.
7899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static class DataRecorder {
7909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long[] mPeriodRxData;
7919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long[] mPeriodTxData;
7929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        int mCurrentPeriod;
7939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        int mPeriodCount;
7949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Calendar mPeriodStart;
7969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Calendar mPeriodEnd;
7979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        ThrottleService mParent;
7999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Context mContext;
800e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        String mImsi = null;
801e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
802e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        TelephonyManager mTelephonyManager;
8039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        DataRecorder(Context context, ThrottleService parent) {
8059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mContext = context;
8069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mParent = parent;
8079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
808e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            mTelephonyManager = (TelephonyManager)mContext.getSystemService(
809e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                    Context.TELEPHONY_SERVICE);
810e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
8119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodCount = 6;
8139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodRxData = new long[mPeriodCount];
8149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodTxData = new long[mPeriodCount];
8159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodStart = Calendar.getInstance();
8179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodEnd = Calendar.getInstance();
8189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                retrieve();
8209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8237171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        boolean setNextPeriod(Calendar start, Calendar end) {
824e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            // TODO - how would we deal with a dual-IMSI device?
825e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            checkForSubscriberId();
8267171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            boolean startNewPeriod = true;
827bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt
82827fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt            if (start.equals(mPeriodStart) && end.equals(mPeriodEnd)) {
82927fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                // same endpoints - keep collecting
8305a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                if (VDBG) {
83127fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                    Slog.d(TAG, "same period (" + start.getTimeInMillis() + "," +
83227fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                            end.getTimeInMillis() +") - ammending data");
8339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
83427fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                startNewPeriod = false;
83527fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt            } else {
8365a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                if (VDBG) {
83727fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                    if(start.equals(mPeriodEnd) || start.after(mPeriodEnd)) {
83827fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                        Slog.d(TAG, "next period (" + start.getTimeInMillis() + "," +
83927fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                                end.getTimeInMillis() + ") - old end was " +
84027fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                                mPeriodEnd.getTimeInMillis() + ", following");
84127fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                    } else {
84227fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                        Slog.d(TAG, "new period (" + start.getTimeInMillis() + "," +
84327fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                                end.getTimeInMillis() + ") replacing old (" +
84427fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                                mPeriodStart.getTimeInMillis() + "," +
84527fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                                mPeriodEnd.getTimeInMillis() + ")");
84627fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                    }
8479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
8489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                synchronized (mParent) {
8499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    ++mCurrentPeriod;
8509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    if (mCurrentPeriod >= mPeriodCount) mCurrentPeriod = 0;
8519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodRxData[mCurrentPeriod] = 0;
8529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodTxData[mCurrentPeriod] = 0;
8539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
8549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            setPeriodStart(start);
8569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            setPeriodEnd(end);
8579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            record();
8587171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            return startNewPeriod;
8599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public long getPeriodEnd() {
8629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodEnd.getTimeInMillis();
8649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void setPeriodEnd(Calendar end) {
8689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodEnd = end;
8709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public long getPeriodStart() {
8749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodStart.getTimeInMillis();
8769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void setPeriodStart(Calendar start) {
8809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodStart = start;
8829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public int getPeriodCount() {
8869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodCount;
8889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void zeroData(int field) {
8929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                for(int period = 0; period<mPeriodCount; period++) {
8949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodRxData[period] = 0;
8959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodTxData[period] = 0;
8969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
8979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mCurrentPeriod = 0;
8989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
9009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
9019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
9029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        // if time moves backward accumulate all read/write that's lost into the now
9039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        // otherwise time moved forward.
9049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        void addData(long bytesRead, long bytesWritten) {
905e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            checkForSubscriberId();
9067171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
9079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
9089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodRxData[mCurrentPeriod] += bytesRead;
9099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodTxData[mCurrentPeriod] += bytesWritten;
9109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
9119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            record();
9129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
9139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
914b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt        private File getDataFile() {
915b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            File dataDir = Environment.getDataDirectory();
916b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            File throttleDir = new File(dataDir, "system/throttle");
917b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            throttleDir.mkdirs();
918e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            String mImsi = mTelephonyManager.getSubscriberId();
919e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            File dataFile;
920e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            if (mImsi == null) {
921e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                dataFile = useMRUFile(throttleDir);
922bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt                if (VDBG) Slog.v(TAG, "imsi not available yet, using " + dataFile);
923e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            } else {
924e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                String imsiHash = Integer.toString(mImsi.hashCode());
925e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                dataFile = new File(throttleDir, imsiHash);
926e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            }
927e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            // touch the file so it's not LRU
928e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            dataFile.setLastModified(System.currentTimeMillis());
929e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            checkAndDeleteLRUDataFile(throttleDir);
930b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            return dataFile;
931b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt        }
932b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt
933e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        // TODO - get broadcast (TelephonyIntents.ACTION_SIM_STATE_CHANGED) instead of polling
934e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        private void checkForSubscriberId() {
935e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            if (mImsi != null) return;
936e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
937e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            mImsi = mTelephonyManager.getSubscriberId();
938e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            if (mImsi == null) return;
939e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
9405a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt            if (VDBG) Slog.d(TAG, "finally have imsi - retreiving data");
941e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            retrieve();
942e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        }
943e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
944e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        private final static int MAX_SIMS_SUPPORTED = 3;
945e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
946e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        private void checkAndDeleteLRUDataFile(File dir) {
947e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            File[] files = dir.listFiles();
948e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
949b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            if (files == null || files.length <= MAX_SIMS_SUPPORTED) return;
950bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt            if (DBG) Slog.d(TAG, "Too many data files");
951e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            do {
952e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                File oldest = null;
953e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                for (File f : files) {
954e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                    if ((oldest == null) || (oldest.lastModified() > f.lastModified())) {
955e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                        oldest = f;
956e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                    }
957e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                }
958e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                if (oldest == null) return;
959bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt                if (DBG) Slog.d(TAG, " deleting " + oldest);
960e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                oldest.delete();
961e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                files = dir.listFiles();
962e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            } while (files.length > MAX_SIMS_SUPPORTED);
963e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        }
964e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
965e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        private File useMRUFile(File dir) {
966e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            File newest = null;
967e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            File[] files = dir.listFiles();
968e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
969b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey            if (files != null) {
970b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                for (File f : files) {
971b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                    if ((newest == null) || (newest.lastModified() < f.lastModified())) {
972b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                        newest = f;
973b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey                    }
974e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                }
975e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            }
976e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            if (newest == null) {
977e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                newest = new File(dir, "temp");
978e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            }
979e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            return newest;
980e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        }
981e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
982e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
983b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt        private static final int DATA_FILE_VERSION = 1;
9849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
985b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt        private void record() {
986b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            // 1 int version
9879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 1 int mPeriodCount
9889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13*6 long[PERIOD_COUNT] mPeriodRxData
9899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13*6 long[PERIOD_COUNT] mPeriodTxData
9909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 1  int mCurrentPeriod
9919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13 long periodStartMS
9929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13 long periodEndMS
993b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            // 200 chars max
9949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            StringBuilder builder = new StringBuilder();
995b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            builder.append(DATA_FILE_VERSION);
996b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            builder.append(":");
9979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mPeriodCount);
9989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(":");
999b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            for(int i = 0; i < mPeriodCount; i++) {
10009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(mPeriodRxData[i]);
10019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(":");
10029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
1003b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            for(int i = 0; i < mPeriodCount; i++) {
10049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(mPeriodTxData[i]);
10059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(":");
10069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
10079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mCurrentPeriod);
10089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(":");
10099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mPeriodStart.getTimeInMillis());
10109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(":");
10119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mPeriodEnd.getTimeInMillis());
10129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1013b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            BufferedWriter out = null;
1014b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            try {
10157171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                out = new BufferedWriter(new FileWriter(getDataFile()), 256);
1016b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                out.write(builder.toString());
1017b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            } catch (IOException e) {
1018b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                Slog.e(TAG, "Error writing data file");
1019b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                return;
1020b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            } finally {
1021b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                if (out != null) {
1022b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    try {
1023b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                        out.close();
1024b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    } catch (Exception e) {}
1025b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                }
1026b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            }
10279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
10289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
10299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void retrieve() {
103005d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            // clean out any old data first.  If we fail to read we don't want old stuff
103105d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            zeroData(0);
103205d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt
1033b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            File f = getDataFile();
1034b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            byte[] buffer;
1035b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            FileInputStream s = null;
1036b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            try {
1037b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                buffer = new byte[(int)f.length()];
1038b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                s = new FileInputStream(f);
1039b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                s.read(buffer);
1040b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            } catch (IOException e) {
1041b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                Slog.e(TAG, "Error reading data file");
1042b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                return;
1043b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            } finally {
1044b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                if (s != null) {
1045b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    try {
1046b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                        s.close();
1047b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    } catch (Exception e) {}
1048b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                }
1049b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            }
1050b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            String data = new String(buffer);
10517171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            if (data == null || data.length() == 0) {
10527171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                if (DBG) Slog.d(TAG, "data file empty");
10537171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                return;
10547171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            }
105539e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            String[] parsed = data.split(":");
105639e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            int parsedUsed = 0;
105739e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            if (parsed.length < 6) {
105839e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                Slog.e(TAG, "reading data file with insufficient length - ignoring");
105939e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                return;
106039e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            }
1061b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt
10629e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt            int periodCount;
10639e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt            long[] periodRxData;
10649e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt            long[] periodTxData;
10659e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt            int currentPeriod;
10669e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt            Calendar periodStart;
10679e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt            Calendar periodEnd;
10689e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt            try {
10699e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                if (Integer.parseInt(parsed[parsedUsed++]) != DATA_FILE_VERSION) {
10709e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                    Slog.e(TAG, "reading data file with bad version - ignoring");
10719e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                    return;
10729e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                }
10739e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt
10749e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                periodCount = Integer.parseInt(parsed[parsedUsed++]);
10759e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                if (parsed.length != 5 + (2 * periodCount)) {
10769e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                    Slog.e(TAG, "reading data file with bad length (" + parsed.length +
10779e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                            " != " + (5 + (2 * periodCount)) + ") - ignoring");
10789e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                    return;
10799e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                }
10809e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                periodRxData = new long[periodCount];
10819e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                for (int i = 0; i < periodCount; i++) {
10829e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                    periodRxData[i] = Long.parseLong(parsed[parsedUsed++]);
10839e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                }
10849e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                periodTxData = new long[periodCount];
10859e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                for (int i = 0; i < periodCount; i++) {
10869e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                    periodTxData[i] = Long.parseLong(parsed[parsedUsed++]);
10879e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                }
10889e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt
10899e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                currentPeriod = Integer.parseInt(parsed[parsedUsed++]);
10909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
10919e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                periodStart = new GregorianCalendar();
10929e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                periodStart.setTimeInMillis(Long.parseLong(parsed[parsedUsed++]));
10939e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                periodEnd = new GregorianCalendar();
10949e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                periodEnd.setTimeInMillis(Long.parseLong(parsed[parsedUsed++]));
10959e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt            } catch (Exception e) {
10969e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                Slog.e(TAG, "Error parsing data file - ignoring");
109739e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                return;
109839e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            }
109939e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt            synchronized (mParent) {
110039e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                mPeriodCount = periodCount;
110139e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                mPeriodRxData = periodRxData;
110239e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                mPeriodTxData = periodTxData;
11039e3983fbde2f86c116ffbc40491ff7aedd7d2fc7Robert Greenwalt                mCurrentPeriod = currentPeriod;
110439e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                mPeriodStart = periodStart;
110539e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                mPeriodEnd = periodEnd;
11069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
11079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
11089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
11099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long getPeriodRx(int which) {
11109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
11119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which > mPeriodCount) return 0;
11129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                which = mCurrentPeriod - which;
11139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which < 0) which += mPeriodCount;
11149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodRxData[which];
11159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
11169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
11179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long getPeriodTx(int which) {
11189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
11199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which > mPeriodCount) return 0;
11209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                which = mCurrentPeriod - which;
11219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which < 0) which += mPeriodCount;
11229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodTxData[which];
11239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
11249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
11259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
11269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
11279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    @Override
11289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
11299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        if (mContext.checkCallingOrSelfPermission(
11309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                android.Manifest.permission.DUMP)
11319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                != PackageManager.PERMISSION_GRANTED) {
11329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            pw.println("Permission Denial: can't dump ThrottleService " +
11339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    "from from pid=" + Binder.getCallingPid() + ", uid=" +
11349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Binder.getCallingUid());
11359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return;
11369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
11379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        pw.println();
11389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
113939e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt        pw.println("The threshold is " + mPolicyThreshold.get() +
11409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                ", after which you experince throttling to " +
114139e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt                mPolicyThrottleValue.get() + "kbps");
11429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        pw.println("Current period is " +
11439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                (mRecorder.getPeriodEnd() - mRecorder.getPeriodStart())/1000 + " seconds long " +
11447171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                "and ends in " + (getResetTime(mIface) - System.currentTimeMillis()) / 1000 +
11459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                " seconds.");
11469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        pw.println("Polling every " + mPolicyPollPeriodSec + " seconds");
114739e163f45afa1c86be91717c2ed216b66255a65fRobert Greenwalt        pw.println("Current Throttle Index is " + mThrottleIndex.get());
1148b7342acebcb7e5dc7da0cda77fbddf50e7dfdd7cJeff Sharkey        pw.println("mMaxNtpCacheAge=" + mMaxNtpCacheAge);
11498c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt
11509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        for (int i = 0; i < mRecorder.getPeriodCount(); i++) {
11519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            pw.println(" Period[" + i + "] - read:" + mRecorder.getPeriodRx(i) + ", written:" +
11529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mRecorder.getPeriodTx(i));
11539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
11549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
11559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt}
1156