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;
337171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwaltimport android.net.SntpClient;
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;
509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport android.util.Slog;
519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
527171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwaltimport com.android.internal.R;
535f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwaltimport com.android.internal.telephony.TelephonyProperties;
545f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt
55b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwaltimport java.io.BufferedWriter;
56b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwaltimport java.io.File;
579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.io.FileDescriptor;
58b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwaltimport java.io.FileInputStream;
59b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwaltimport java.io.FileWriter;
60b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwaltimport java.io.IOException;
619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.io.PrintWriter;
629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.util.Calendar;
639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.util.GregorianCalendar;
647171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwaltimport java.util.Properties;
659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltimport java.util.Random;
669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt// TODO - add comments - reference the ThrottleManager for public API
689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwaltpublic class ThrottleService extends IThrottleManager.Stub {
699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String TESTING_ENABLED_PROPERTY = "persist.throttle.testing";
719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String TAG = "ThrottleService";
73bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt    private static final boolean DBG = true;
74bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt    private static final boolean VDBG = false;
759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private Handler mHandler;
769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private HandlerThread mThread;
779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private Context mContext;
799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
80fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt    private static final int INITIAL_POLL_DELAY_SEC = 90;
819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int TESTING_POLLING_PERIOD_SEC = 60 * 1;
827171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    private static final int TESTING_RESET_PERIOD_SEC = 60 * 10;
83d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt    private static final long TESTING_THRESHOLD = 1 * 1024 * 1024;
849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
85d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt    private int mPolicyPollPeriodSec;
869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private long mPolicyThreshold;
879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private int mPolicyThrottleValue;
889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private int mPolicyResetDay; // 1-28
89d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt    private int mPolicyNotificationsAllowedMask;
909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private long mLastRead; // read byte count from last poll
929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private long mLastWrite; // write byte count from last poll
939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String ACTION_POLL = "com.android.server.ThrottleManager.action.POLL";
959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static int POLL_REQUEST = 0;
969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private PendingIntent mPendingPollIntent;
979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final String ACTION_RESET = "com.android.server.ThorottleManager.action.RESET";
989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static int RESET_REQUEST = 1;
999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private PendingIntent mPendingResetIntent;
1009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private INetworkManagementService mNMService;
1029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private AlarmManager mAlarmManager;
1039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private NotificationManager mNotificationManager;
1049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private DataRecorder mRecorder;
1069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
107d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt    private String mIface;
1089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int NOTIFICATION_WARNING   = 2;
1109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private Notification mThrottlingNotification;
1129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private boolean mWarningNotificationSent = false;
1139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
114fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt    private InterfaceObserver mInterfaceObserver;
11581aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt    private SettingsObserver mSettingsObserver;
11681aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt
11781aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt    private int mThrottleIndex; // 0 for none, 1 for first throttle val, 2 for next, etc
11881aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt    private static final int THROTTLE_INDEX_UNINITIALIZED = -1;
11981aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt    private static final int THROTTLE_INDEX_UNTHROTTLED   =  0;
12081aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt
1217171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    private static final String PROPERTIES_FILE = "/etc/gps.conf";
1227171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    private String mNtpServer;
1237171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    private boolean mNtpActive;
1247171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
1259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public ThrottleService(Context context) {
1265a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt        if (VDBG) Slog.v(TAG, "Starting ThrottleService");
1279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext = context;
1289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1297171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        mNtpActive = false;
1307171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
131fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        mIface = mContext.getResources().getString(R.string.config_datause_iface);
1329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
1339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Intent pollIntent = new Intent(ACTION_POLL, null);
1349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mPendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST, pollIntent, 0);
1359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Intent resetIntent = new Intent(ACTION_RESET, null);
1369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mPendingResetIntent = PendingIntent.getBroadcast(mContext, RESET_REQUEST, resetIntent, 0);
1379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
1399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mNMService = INetworkManagementService.Stub.asInterface(b);
1409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
1419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mNotificationManager = (NotificationManager)mContext.getSystemService(
1429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Context.NOTIFICATION_SERVICE);
1439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
1449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
145fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt    private static class InterfaceObserver extends INetworkManagementEventObserver.Stub {
146fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        private int mMsg;
147fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        private Handler mHandler;
148fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        private String mIface;
149fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
150fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        InterfaceObserver(Handler handler, int msg, String iface) {
151fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            super();
152fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            mHandler = handler;
153fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            mMsg = msg;
154fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            mIface = iface;
155fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        }
156fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
157fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        public void interfaceLinkStatusChanged(String iface, boolean link) {
158fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            if (link) {
159fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                if (TextUtils.equals(iface, mIface)) {
160fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                    mHandler.obtainMessage(mMsg).sendToTarget();
161fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                }
162fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            }
163fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        }
164fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
165fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        public void interfaceAdded(String iface) {
166fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            // TODO - an interface added in the UP state should also trigger a StatusChanged
167fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            // notification..
168fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            if (TextUtils.equals(iface, mIface)) {
169fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                mHandler.obtainMessage(mMsg).sendToTarget();
170fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            }
171fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        }
172fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
173fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        public void interfaceRemoved(String iface) {}
174fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt    }
175fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
176fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
17781aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt    private static class SettingsObserver extends ContentObserver {
17881aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        private int mMsg;
17981aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        private Handler mHandler;
18081aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        SettingsObserver(Handler handler, int msg) {
18181aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            super(handler);
18281aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            mHandler = handler;
18381aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            mMsg = msg;
18481aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        }
18581aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt
18681aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        void observe(Context context) {
18781aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            ContentResolver resolver = context.getContentResolver();
18881aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
18981aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt                    Settings.Secure.THROTTLE_POLLING_SEC), false, this);
19081aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
191d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    Settings.Secure.THROTTLE_THRESHOLD_BYTES), false, this);
19281aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
193d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    Settings.Secure.THROTTLE_VALUE_KBITSPS), false, this);
19481aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
19581aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt                    Settings.Secure.THROTTLE_RESET_DAY), false, this);
19681aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
19781aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt                    Settings.Secure.THROTTLE_NOTIFICATION_TYPE), false, this);
19881aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
199d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    Settings.Secure.THROTTLE_HELP_URI), false, this);
200d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt            resolver.registerContentObserver(Settings.Secure.getUriFor(
201d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt                    Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC), false, this);
20281aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        }
20381aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt
20481aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        @Override
20581aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        public void onChange(boolean selfChange) {
20681aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            mHandler.obtainMessage(mMsg).sendToTarget();
20781aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        }
20881aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt    }
20981aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt
2109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private void enforceAccessPermission() {
2119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext.enforceCallingOrSelfPermission(
2129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                android.Manifest.permission.ACCESS_NETWORK_STATE,
2139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                "ThrottleService");
2149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
2159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
21605d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt    private long ntpToWallTime(long ntpTime) {
21705d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt        long bestNow = getBestTime();
21805d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt        long localNow = System.currentTimeMillis();
21905d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt        return localNow + (ntpTime - bestNow);
22005d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt    }
22105d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt
222cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
2237171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    // return time in the local, system wall time, correcting for the use of ntp
22405d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt
2259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized long getResetTime(String iface) {
2269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
2277171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        long resetTime = 0;
228cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff        if (mRecorder != null) {
22905d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            resetTime = ntpToWallTime(mRecorder.getPeriodEnd());
230d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt        }
2317171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        return resetTime;
2329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
233cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff
234cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
23505d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt    // return time in the local, system wall time, correcting for the use of ntp
2369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized long getPeriodStartTime(String iface) {
2379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
2387171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        long startTime = 0;
239cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff        if (mRecorder != null) {
24005d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            startTime = ntpToWallTime(mRecorder.getPeriodStart());
241d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt        }
2427171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        return startTime;
2439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
2449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    //TODO - a better name?  getCliffByteCountThreshold?
245cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
2469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized long getCliffThreshold(String iface, int cliff) {
2479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
248cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff        if (cliff == 1) {
2499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return mPolicyThreshold;
2509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
2519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
2529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
2539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // TODO - a better name? getThrottleRate?
254cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
2559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized int getCliffLevel(String iface, int cliff) {
2569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
257cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff        if (cliff == 1) {
2589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return mPolicyThrottleValue;
2599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
2609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
2619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
2629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
263c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff    public String getHelpUri() {
264c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff        enforceAccessPermission();
265c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff        return Settings.Secure.getString(mContext.getContentResolver(),
266c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff                    Settings.Secure.THROTTLE_HELP_URI);
267c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff    }
268c9b6851af68bdc20c4903b16c344e9f116647219Irfan Sheriff
269cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
2709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized long getByteCount(String iface, int dir, int period, int ago) {
2719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
272cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff        if ((period == ThrottleManager.PERIOD_CYCLE) &&
2739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                (mRecorder != null)) {
2749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (dir == ThrottleManager.DIRECTION_TX) return mRecorder.getPeriodTx(ago);
2759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (dir == ThrottleManager.DIRECTION_RX) return mRecorder.getPeriodRx(ago);
2769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
2779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
2789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
2799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // TODO - a better name - getCurrentThrottleRate?
281cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff    // TODO - fetch for the iface
2829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    public synchronized int getThrottle(String iface) {
2839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        enforceAccessPermission();
284cf28236b3784e285632e272b99cf1f8fc01f016bIrfan Sheriff        if (mThrottleIndex == 1) {
2859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return mPolicyThrottleValue;
2869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
2879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        return 0;
2889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
2899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
2909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    void systemReady() {
2915a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt        if (VDBG) Slog.v(TAG, "systemReady");
2929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext.registerReceiver(
2939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            new BroadcastReceiver() {
2949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                @Override
2959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                public void onReceive(Context context, Intent intent) {
2969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mHandler.obtainMessage(EVENT_POLL_ALARM).sendToTarget();
2979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
2989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }, new IntentFilter(ACTION_POLL));
2999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mContext.registerReceiver(
3019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            new BroadcastReceiver() {
3029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                @Override
3039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                public void onReceive(Context context, Intent intent) {
3049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget();
3059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
3069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }, new IntentFilter(ACTION_RESET));
3079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        // use a new thread as we don't want to stall the system for file writes
3099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mThread = new HandlerThread(TAG);
3109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mThread.start();
3119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mHandler = new MyHandler(mThread.getLooper());
3129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        mHandler.obtainMessage(EVENT_REBOOT_RECOVERY).sendToTarget();
31381aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt
314fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        mInterfaceObserver = new InterfaceObserver(mHandler, EVENT_IFACE_UP, mIface);
315fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        try {
316fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            mNMService.registerObserver(mInterfaceObserver);
317fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        } catch (RemoteException e) {
318fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            Slog.e(TAG, "Could not register InterfaceObserver " + e);
319fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        }
320fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
32181aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        mSettingsObserver = new SettingsObserver(mHandler, EVENT_POLICY_CHANGED);
32281aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt        mSettingsObserver.observe(mContext);
3237171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
3247171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        FileInputStream stream = null;
3257171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        try {
3267171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            Properties properties = new Properties();
3277171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            File file = new File(PROPERTIES_FILE);
3287171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            stream = new FileInputStream(file);
3297171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            properties.load(stream);
3307171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            mNtpServer = properties.getProperty("NTP_SERVER", null);
3317171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        } catch (IOException e) {
3327171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            Slog.e(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
3337171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        } finally {
3347171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            if (stream != null) {
3357171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                try {
3367171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    stream.close();
3377171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                } catch (Exception e) {}
3387171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            }
3397171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        }
3409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
3419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_REBOOT_RECOVERY = 0;
3449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_POLICY_CHANGED  = 1;
3459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_POLL_ALARM      = 2;
3469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static final int EVENT_RESET_ALARM     = 3;
347fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt    private static final int EVENT_IFACE_UP        = 4;
3489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private class MyHandler extends Handler {
3499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public MyHandler(Looper l) {
3509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            super(l);
3519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
3529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        @Override
3549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public void handleMessage(Message msg) {
3559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            switch (msg.what) {
3569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_REBOOT_RECOVERY:
3579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onRebootRecovery();
3589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                break;
3599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_POLICY_CHANGED:
3609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onPolicyChanged();
3619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                break;
3629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_POLL_ALARM:
3639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onPollAlarm();
3649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                break;
3659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            case EVENT_RESET_ALARM:
3669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                onResetAlarm();
367fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                break;
368fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            case EVENT_IFACE_UP:
369fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                onIfaceUp();
3709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
3719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
3729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onRebootRecovery() {
3745a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt            if (VDBG) Slog.v(TAG, "onRebootRecovery");
3759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // check for sim change TODO
3769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // reregister for notification of policy change
3779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
37881aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            mThrottleIndex = THROTTLE_INDEX_UNINITIALIZED;
3799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mRecorder = new DataRecorder(mContext, ThrottleService.this);
3819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // get policy
3839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mHandler.obtainMessage(EVENT_POLICY_CHANGED).sendToTarget();
384fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt
385fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt            // if we poll now we won't have network connectivity or even imsi access
386fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt            // queue up a poll to happen in a little while - after ntp and imsi are avail
387fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt            // TODO - make this callback based (ie, listen for notificaitons)
388fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt            mHandler.sendMessageDelayed(mHandler.obtainMessage(EVENT_POLL_ALARM),
389fb9896b5cdb149594fa1b36ac77038d90091a957Robert Greenwalt                    INITIAL_POLL_DELAY_SEC * 1000);
3909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
3919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
3929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        // check for new policy info (threshold limit/value/etc)
3939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onPolicyChanged() {
3949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            boolean testing = SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true");
3959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
396d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            int pollingPeriod = mContext.getResources().getInteger(
3977171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    R.integer.config_datause_polling_period_sec);
3989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mPolicyPollPeriodSec = Settings.Secure.getInt(mContext.getContentResolver(),
3999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Settings.Secure.THROTTLE_POLLING_SEC, pollingPeriod);
4009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - remove testing stuff?
402d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            long defaultThreshold = mContext.getResources().getInteger(
4037171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    R.integer.config_datause_threshold_bytes);
404d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            int defaultValue = mContext.getResources().getInteger(
4057171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    R.integer.config_datause_throttle_kbitsps);
4069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (ThrottleService.this) {
4079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPolicyThreshold = Settings.Secure.getLong(mContext.getContentResolver(),
408d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                        Settings.Secure.THROTTLE_THRESHOLD_BYTES, defaultThreshold);
4099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPolicyThrottleValue = Settings.Secure.getInt(mContext.getContentResolver(),
410d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                        Settings.Secure.THROTTLE_VALUE_KBITSPS, defaultValue);
411d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                if (testing) {
412d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    mPolicyPollPeriodSec = TESTING_POLLING_PERIOD_SEC;
413d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    mPolicyThreshold = TESTING_THRESHOLD;
414d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                }
4159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
416d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt
4179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mPolicyResetDay = Settings.Secure.getInt(mContext.getContentResolver(),
4189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Settings.Secure.THROTTLE_RESET_DAY, -1);
4199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (mPolicyResetDay == -1 ||
4209e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    ((mPolicyResetDay < 1) || (mPolicyResetDay > 28))) {
4219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Random g = new Random();
4229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPolicyResetDay = 1 + g.nextInt(28); // 1-28
4239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Settings.Secure.putInt(mContext.getContentResolver(),
4249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Settings.Secure.THROTTLE_RESET_DAY, mPolicyResetDay);
4259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (ThrottleService.this) {
427d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                if (mIface == null) {
428d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    mPolicyThreshold = 0;
429d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                }
4309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
432d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            int defaultNotificationType = mContext.getResources().getInteger(
4337171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    R.integer.config_datause_notification_type);
4349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mPolicyNotificationsAllowedMask = Settings.Secure.getInt(mContext.getContentResolver(),
435d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    Settings.Secure.THROTTLE_NOTIFICATION_TYPE, defaultNotificationType);
4369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
437d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt            mMaxNtpCacheAgeSec = Settings.Secure.getInt(mContext.getContentResolver(),
438d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt                    Settings.Secure.THROTTLE_MAX_NTP_CACHE_AGE_SEC, MAX_NTP_CACHE_AGE_SEC);
439d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt
4405a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt            if (VDBG || (mPolicyThreshold != 0)) {
4415a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                Slog.d(TAG, "onPolicyChanged testing=" + testing +", period=" +
4425a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                        mPolicyPollPeriodSec + ", threshold=" + mPolicyThreshold + ", value=" +
4435a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                        mPolicyThrottleValue + ", resetDay=" + mPolicyResetDay + ", noteType=" +
4445a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                        mPolicyNotificationsAllowedMask + ", maxNtpCacheAge=" + mMaxNtpCacheAgeSec);
4455a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt            }
4469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4475bf16d6e8c0afae4e60590ffbdbed1bd6e73ff8bRobert Greenwalt            // force updates
4485bf16d6e8c0afae4e60590ffbdbed1bd6e73ff8bRobert Greenwalt            mThrottleIndex = THROTTLE_INDEX_UNINITIALIZED;
4495bf16d6e8c0afae4e60590ffbdbed1bd6e73ff8bRobert Greenwalt
45081aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            onResetAlarm();
4519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
452b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            onPollAlarm();
453b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt
45481aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            Intent broadcast = new Intent(ThrottleManager.POLICY_CHANGED_ACTION);
45581aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            mContext.sendBroadcast(broadcast);
4569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
4579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onPollAlarm() {
4599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long now = SystemClock.elapsedRealtime();
4609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long next = now + mPolicyPollPeriodSec*1000;
4617171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
4627171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            checkForAuthoritativeTime();
4637171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
4649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long incRead = 0;
4659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long incWrite = 0;
4669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            try {
467d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                incRead = mNMService.getInterfaceRxCounter(mIface) - mLastRead;
468d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                incWrite = mNMService.getInterfaceTxCounter(mIface) - mLastWrite;
4698c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                // handle iface resets - on some device the 3g iface comes and goes and gets
4708c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                // totals reset to 0.  Deal with it
4718c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                if ((incRead < 0) || (incWrite < 0)) {
4728c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                    incRead += mLastRead;
4738c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                    incWrite += mLastWrite;
4748c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                    mLastRead = 0;
4758c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                    mLastWrite = 0;
4768c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt                }
4779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            } catch (RemoteException e) {
4789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Slog.e(TAG, "got remoteException in onPollAlarm:" + e);
4799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4805f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt            // don't count this data if we're roaming.
4815f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt            boolean roaming = "true".equals(
4825f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt                    SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING));
4835f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt            if (!roaming) {
4845f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt                mRecorder.addData(incRead, incWrite);
4855f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt            }
4869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long periodRx = mRecorder.getPeriodRx(0);
4889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long periodTx = mRecorder.getPeriodTx(0);
4899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            long total = periodRx + periodTx;
4905a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt            if (VDBG || (mPolicyThreshold != 0)) {
491bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt                Slog.d(TAG, "onPollAlarm - roaming =" + roaming +
4925f996899b058f0eb6655d3fe3fd3a5d93256e6c5Robert Greenwalt                        ", read =" + incRead + ", written =" + incWrite + ", new total =" + total);
4939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
4949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mLastRead += incRead;
4959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mLastWrite += incWrite;
4969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            checkThrottleAndPostNotification(total);
4989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
4999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Intent broadcast = new Intent(ThrottleManager.THROTTLE_POLL_ACTION);
5009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_READ, periodRx);
5019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_WRITE, periodTx);
50205d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_START, getPeriodStartTime(mIface));
50305d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            broadcast.putExtra(ThrottleManager.EXTRA_CYCLE_END, getResetTime(mIface));
5049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mContext.sendStickyBroadcast(broadcast);
5059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
506d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            mAlarmManager.cancel(mPendingPollIntent);
5075a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, next, mPendingPollIntent);
5089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
5099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
510fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        private void onIfaceUp() {
511fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            // if we were throttled before, be sure and set it again - the iface went down
512fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            // (and may have disappeared all together) and these settings were lost
513fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            if (mThrottleIndex == 1) {
514fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                try {
515fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                    mNMService.setInterfaceThrottle(mIface, -1, -1);
516fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                    mNMService.setInterfaceThrottle(mIface,
517fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                            mPolicyThrottleValue, mPolicyThrottleValue);
518fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                } catch (Exception e) {
519fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                    Slog.e(TAG, "error setting Throttle: " + e);
520fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt                }
521fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt            }
522fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt        }
523fee4683f47b43626af98ed9aade27917d4da2d8aRobert Greenwalt
5249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void checkThrottleAndPostNotification(long currentTotal) {
525d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt            // is throttling enabled?
5267171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            if (mPolicyThreshold == 0) {
527cce83379ef5ddd122ffe6fcce431cb86d059a74bRobert Greenwalt                clearThrottleAndNotification();
5289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return;
5297171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            }
5307171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
5317171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            // have we spoken with an ntp server yet?
5327171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            // this is controversial, but we'd rather err towards not throttling
5337171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            if ((mNtpServer != null) && !mNtpActive) {
5347171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                return;
5357171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            }
5369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // check if we need to throttle
5389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (currentTotal > mPolicyThreshold) {
53981aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt                if (mThrottleIndex != 1) {
5409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    synchronized (ThrottleService.this) {
54181aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt                        mThrottleIndex = 1;
5429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    }
5439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    if (DBG) Slog.d(TAG, "Threshold " + mPolicyThreshold + " exceeded!");
5449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    try {
545d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                        mNMService.setInterfaceThrottle(mIface,
5469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                                mPolicyThrottleValue, mPolicyThrottleValue);
5479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    } catch (Exception e) {
5489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        Slog.e(TAG, "error setting Throttle: " + e);
5499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    }
5509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5517171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    mNotificationManager.cancel(R.drawable.stat_sys_throttled);
5529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5537171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    postNotification(R.string.throttled_notification_title,
5547171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                            R.string.throttled_notification_message,
5557171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                            R.drawable.stat_sys_throttled,
556c87dc6dc90d0953c10051dceb470ff05e2fb9300Robert Greenwalt                            Notification.FLAG_ONGOING_EVENT);
5579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
5599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, mPolicyThrottleValue);
5609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mContext.sendStickyBroadcast(broadcast);
5619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
5629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                } // else already up!
5639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            } else {
5645bf16d6e8c0afae4e60590ffbdbed1bd6e73ff8bRobert Greenwalt                clearThrottleAndNotification();
5659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if ((mPolicyNotificationsAllowedMask & NOTIFICATION_WARNING) != 0) {
5669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    // check if we should warn about throttle
567e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // pretend we only have 1/2 the time remaining that we actually do
568e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // if our burn rate in the period so far would have us exceed the limit
569e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // in that 1/2 window, warn the user.
570e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // this gets more generous in the early to middle period and converges back
571e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // to the limit as we move toward the period end.
572e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt
573e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // adding another factor - it must be greater than the total cap/4
574e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // else we may get false alarms very early in the period..  in the first
575e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // tenth of a percent of the period if we used more than a tenth of a percent
576e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    // of the cap we'd get a warning and that's not desired.
577e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    long start = mRecorder.getPeriodStart();
578e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    long end = mRecorder.getPeriodEnd();
579e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    long periodLength = end - start;
580e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    long now = System.currentTimeMillis();
581e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    long timeUsed = now - start;
582e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    long warningThreshold = 2*mPolicyThreshold*timeUsed/(timeUsed+periodLength);
583e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                    if ((currentTotal > warningThreshold) && (currentTotal > mPolicyThreshold/4)) {
584e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                        if (mWarningNotificationSent == false) {
585e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                            mWarningNotificationSent = true;
5867171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                            mNotificationManager.cancel(R.drawable.stat_sys_throttled);
5877171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                            postNotification(R.string.throttle_warning_notification_title,
5887171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                                    R.string.throttle_warning_notification_message,
5897171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                                    R.drawable.stat_sys_throttled,
590e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                                    0);
591e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                        }
5929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    } else {
593e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                        if (mWarningNotificationSent == true) {
5947171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                            mNotificationManager.cancel(R.drawable.stat_sys_throttled);
595e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                            mWarningNotificationSent =false;
596e2c0ce03631fc81651b8bde578e993c25e3291e9Robert Greenwalt                        }
5979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    }
5989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
5999e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
602c87dc6dc90d0953c10051dceb470ff05e2fb9300Robert Greenwalt        private void postNotification(int titleInt, int messageInt, int icon, int flags) {
6039e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Intent intent = new Intent();
6049e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - fix up intent
6052a7b730378a0c9d7c3dfbc47e9862169a149d347Robert Greenwalt            intent.setClassName("com.android.phone", "com.android.phone.DataUsage");
6069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
6079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
6099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Resources r = Resources.getSystem();
6119e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            CharSequence title = r.getText(titleInt);
6129e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            CharSequence message = r.getText(messageInt);
6139e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (mThrottlingNotification == null) {
6149e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification = new Notification();
6159e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification.when = 0;
6169e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                // TODO -  fixup icon
6179e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification.icon = icon;
6189e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mThrottlingNotification.defaults &= ~Notification.DEFAULT_SOUND;
6199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
620c87dc6dc90d0953c10051dceb470ff05e2fb9300Robert Greenwalt            mThrottlingNotification.flags = flags;
6219e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mThrottlingNotification.tickerText = title;
6229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mThrottlingNotification.setLatestEventInfo(mContext, title, message, pi);
6239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mNotificationManager.notify(mThrottlingNotification.icon, mThrottlingNotification);
6259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private synchronized void clearThrottleAndNotification() {
62981aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt            if (mThrottleIndex != THROTTLE_INDEX_UNTHROTTLED) {
6309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                synchronized (ThrottleService.this) {
63181aa0971d7a26ae16ed34fc7da97a55d97fb8e74Robert Greenwalt                    mThrottleIndex = THROTTLE_INDEX_UNTHROTTLED;
6329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
6339e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                try {
634d3bb93f6870581eebbf08b5b7fb0a9c5eaad8b16Robert Greenwalt                    mNMService.setInterfaceThrottle(mIface, -1, -1);
6359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                } catch (Exception e) {
6369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Slog.e(TAG, "error clearing Throttle: " + e);
6379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
6389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Intent broadcast = new Intent(ThrottleManager.THROTTLE_ACTION);
6399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                broadcast.putExtra(ThrottleManager.EXTRA_THROTTLE_LEVEL, -1);
6409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mContext.sendStickyBroadcast(broadcast);
6415bf16d6e8c0afae4e60590ffbdbed1bd6e73ff8bRobert Greenwalt                mNotificationManager.cancel(R.drawable.stat_sys_throttled);
6425bf16d6e8c0afae4e60590ffbdbed1bd6e73ff8bRobert Greenwalt                mWarningNotificationSent = false;
6439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6467171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        private Calendar calculatePeriodEnd(long now) {
6479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Calendar end = GregorianCalendar.getInstance();
6487171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            end.setTimeInMillis(now);
6499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            int day = end.get(Calendar.DAY_OF_MONTH);
6509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            end.set(Calendar.DAY_OF_MONTH, mPolicyResetDay);
6519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            end.set(Calendar.HOUR_OF_DAY, 0);
6529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            end.set(Calendar.MINUTE, 0);
6538c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt            end.set(Calendar.SECOND, 0);
6548c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt            end.set(Calendar.MILLISECOND, 0);
6559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (day >= mPolicyResetDay) {
6569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                int month = end.get(Calendar.MONTH);
6579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (month == Calendar.DECEMBER) {
6589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    end.set(Calendar.YEAR, end.get(Calendar.YEAR) + 1);
6599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    month = Calendar.JANUARY - 1;
6609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
6619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                end.set(Calendar.MONTH, month + 1);
6629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - remove!
6659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true")) {
6669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                end = GregorianCalendar.getInstance();
6677171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                end.setTimeInMillis(now);
6689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                end.add(Calendar.SECOND, TESTING_RESET_PERIOD_SEC);
6699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return end;
6719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private Calendar calculatePeriodStart(Calendar end) {
6739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            Calendar start = (Calendar)end.clone();
6749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            int month = end.get(Calendar.MONTH);
6759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (end.get(Calendar.MONTH) == Calendar.JANUARY) {
6769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                month = Calendar.DECEMBER + 1;
6779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                start.set(Calendar.YEAR, start.get(Calendar.YEAR) - 1);
6789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            start.set(Calendar.MONTH, month - 1);
6809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // TODO - remove!!
6829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            if (SystemProperties.get(TESTING_ENABLED_PROPERTY).equals("true")) {
6839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                start = (Calendar)end.clone();
6849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                start.add(Calendar.SECOND, -TESTING_RESET_PERIOD_SEC);
6859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return start;
6879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
6889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void onResetAlarm() {
6905a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt            if (VDBG || (mPolicyThreshold != 0)) {
6919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                Slog.d(TAG, "onResetAlarm - last period had " + mRecorder.getPeriodRx(0) +
6929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                        " bytes read and " + mRecorder.getPeriodTx(0) + " written");
6939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
6949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6957171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            long now = getBestTime();
6969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
6977171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            if (mNtpActive || (mNtpServer == null)) {
6987171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                Calendar end = calculatePeriodEnd(now);
6997171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                Calendar start = calculatePeriodStart(end);
7009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7017171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                if (mRecorder.setNextPeriod(start, end)) {
70205d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                    onPollAlarm();
7037171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                }
7047171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
7057171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                mAlarmManager.cancel(mPendingResetIntent);
7067171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                long offset = end.getTimeInMillis() - now;
7077171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                // use Elapsed realtime so clock changes don't fool us.
7085a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                mAlarmManager.set(AlarmManager.ELAPSED_REALTIME,
7097171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                        SystemClock.elapsedRealtime() + offset,
7107171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                        mPendingResetIntent);
7117171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            } else {
7125a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                if (VDBG) Slog.d(TAG, "no authoritative time - not resetting period");
7137171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            }
7147171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        }
7157171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    }
7167171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
7177171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    private void checkForAuthoritativeTime() {
7187171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        if (mNtpActive || (mNtpServer == null)) return;
7199e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
72005d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt        // will try to get the ntp time and switch to it if found.
72105d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt        // will also cache the time so we don't fetch it repeatedly.
72205d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt        getBestTime();
7239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
7249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
725d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt    private static final int MAX_NTP_CACHE_AGE_SEC = 60 * 60 * 24; // 1 day
72605d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt    private static final int MAX_NTP_FETCH_WAIT = 10 * 1000;
727d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt    private int mMaxNtpCacheAgeSec = MAX_NTP_CACHE_AGE_SEC;
72805d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt    private long cachedNtp;
72905d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt    private long cachedNtpTimestamp;
73005d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt
7317171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    private long getBestTime() {
73205d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt        if (mNtpServer != null) {
73305d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            if (mNtpActive) {
73405d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                long ntpAge = SystemClock.elapsedRealtime() - cachedNtpTimestamp;
735d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt                if (ntpAge < mMaxNtpCacheAgeSec * 1000) {
736bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt                    if (VDBG) Slog.v(TAG, "using cached time");
73705d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                    return cachedNtp + ntpAge;
73805d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                }
73905d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            }
74005d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            SntpClient client = new SntpClient();
74105d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            if (client.requestTime(mNtpServer, MAX_NTP_FETCH_WAIT)) {
74205d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                cachedNtp = client.getNtpTime();
74305d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                cachedNtpTimestamp = SystemClock.elapsedRealtime();
74405d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                if (!mNtpActive) {
74505d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                    mNtpActive = true;
7465a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                    if (VDBG) Slog.d(TAG, "found Authoritative time - reseting alarm");
74705d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                    mHandler.obtainMessage(EVENT_RESET_ALARM).sendToTarget();
74805d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                }
749bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt                if (VDBG) Slog.v(TAG, "using Authoritative time: " + cachedNtp);
75005d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt                return cachedNtp;
75105d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            }
7527171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        }
75305d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt        long time = System.currentTimeMillis();
754bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt        if (VDBG) Slog.v(TAG, "using User time: " + time);
75505d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt        mNtpActive = false;
7567171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        return time;
7577171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt    }
7587171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
7599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // records bytecount data for a given time and accumulates it into larger time windows
7609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // for logging and other purposes
7619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    //
7629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // since time can be changed (user or network action) we will have to track the time of the
7639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    // last recording and deal with it.
7649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    private static class DataRecorder {
7659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long[] mPeriodRxData;
7669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long[] mPeriodTxData;
7679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        int mCurrentPeriod;
7689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        int mPeriodCount;
7699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Calendar mPeriodStart;
7719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Calendar mPeriodEnd;
7729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        ThrottleService mParent;
7749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        Context mContext;
775e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        String mImsi = null;
776e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
777e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        TelephonyManager mTelephonyManager;
7789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        DataRecorder(Context context, ThrottleService parent) {
7809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mContext = context;
7819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            mParent = parent;
7829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
783e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            mTelephonyManager = (TelephonyManager)mContext.getSystemService(
784e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                    Context.TELEPHONY_SERVICE);
785e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
7869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
7879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodCount = 6;
7889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodRxData = new long[mPeriodCount];
7899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodTxData = new long[mPeriodCount];
7909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodStart = Calendar.getInstance();
7929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodEnd = Calendar.getInstance();
7939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                retrieve();
7959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
7969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
7979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
7987171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt        boolean setNextPeriod(Calendar start, Calendar end) {
799e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            // TODO - how would we deal with a dual-IMSI device?
800e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            checkForSubscriberId();
8017171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            boolean startNewPeriod = true;
802bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt
80327fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt            if (start.equals(mPeriodStart) && end.equals(mPeriodEnd)) {
80427fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                // same endpoints - keep collecting
8055a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                if (VDBG) {
80627fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                    Slog.d(TAG, "same period (" + start.getTimeInMillis() + "," +
80727fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                            end.getTimeInMillis() +") - ammending data");
8089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
80927fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                startNewPeriod = false;
81027fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt            } else {
8115a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                if (VDBG) {
81227fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                    if(start.equals(mPeriodEnd) || start.after(mPeriodEnd)) {
81327fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                        Slog.d(TAG, "next period (" + start.getTimeInMillis() + "," +
81427fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                                end.getTimeInMillis() + ") - old end was " +
81527fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                                mPeriodEnd.getTimeInMillis() + ", following");
81627fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                    } else {
81727fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                        Slog.d(TAG, "new period (" + start.getTimeInMillis() + "," +
81827fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                                end.getTimeInMillis() + ") replacing old (" +
81927fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                                mPeriodStart.getTimeInMillis() + "," +
82027fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                                mPeriodEnd.getTimeInMillis() + ")");
82127fba6797b07583ef6c280bc287bf327e47f5e66Robert Greenwalt                    }
8229e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
8239e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                synchronized (mParent) {
8249e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    ++mCurrentPeriod;
8259e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    if (mCurrentPeriod >= mPeriodCount) mCurrentPeriod = 0;
8269e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodRxData[mCurrentPeriod] = 0;
8279e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodTxData[mCurrentPeriod] = 0;
8289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
8299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            setPeriodStart(start);
8319e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            setPeriodEnd(end);
8329e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            record();
8337171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            return startNewPeriod;
8349e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8359e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8369e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public long getPeriodEnd() {
8379e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8389e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodEnd.getTimeInMillis();
8399e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8429e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void setPeriodEnd(Calendar end) {
8439e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8449e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodEnd = end;
8459e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8469e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public long getPeriodStart() {
8499e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodStart.getTimeInMillis();
8519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8539e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void setPeriodStart(Calendar start) {
8559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodStart = start;
8579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        public int getPeriodCount() {
8619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodCount;
8639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void zeroData(int field) {
8679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                for(int period = 0; period<mPeriodCount; period++) {
8699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodRxData[period] = 0;
8709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodTxData[period] = 0;
8719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
8729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mCurrentPeriod = 0;
8739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
8779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        // if time moves backward accumulate all read/write that's lost into the now
8789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        // otherwise time moved forward.
8799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        void addData(long bytesRead, long bytesWritten) {
880e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            checkForSubscriberId();
8817171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt
8829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
8839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodRxData[mCurrentPeriod] += bytesRead;
8849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodTxData[mCurrentPeriod] += bytesWritten;
8859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
8869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            record();
8879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
8889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
889b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt        private File getDataFile() {
890b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            File dataDir = Environment.getDataDirectory();
891b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            File throttleDir = new File(dataDir, "system/throttle");
892b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            throttleDir.mkdirs();
893e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            String mImsi = mTelephonyManager.getSubscriberId();
894e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            File dataFile;
895e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            if (mImsi == null) {
896e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                dataFile = useMRUFile(throttleDir);
897bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt                if (VDBG) Slog.v(TAG, "imsi not available yet, using " + dataFile);
898e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            } else {
899e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                String imsiHash = Integer.toString(mImsi.hashCode());
900e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                dataFile = new File(throttleDir, imsiHash);
901e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            }
902e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            // touch the file so it's not LRU
903e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            dataFile.setLastModified(System.currentTimeMillis());
904e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            checkAndDeleteLRUDataFile(throttleDir);
905b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            return dataFile;
906b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt        }
907b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt
908e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        // TODO - get broadcast (TelephonyIntents.ACTION_SIM_STATE_CHANGED) instead of polling
909e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        private void checkForSubscriberId() {
910e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            if (mImsi != null) return;
911e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
912e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            mImsi = mTelephonyManager.getSubscriberId();
913e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            if (mImsi == null) return;
914e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
9155a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt            if (VDBG) Slog.d(TAG, "finally have imsi - retreiving data");
916e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            retrieve();
917e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        }
918e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
919e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        private final static int MAX_SIMS_SUPPORTED = 3;
920e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
921e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        private void checkAndDeleteLRUDataFile(File dir) {
922e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            File[] files = dir.listFiles();
923e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
924e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            if (files.length <= MAX_SIMS_SUPPORTED) return;
925bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt            if (DBG) Slog.d(TAG, "Too many data files");
926e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            do {
927e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                File oldest = null;
928e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                for (File f : files) {
929e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                    if ((oldest == null) || (oldest.lastModified() > f.lastModified())) {
930e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                        oldest = f;
931e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                    }
932e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                }
933e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                if (oldest == null) return;
934bf7de397279519e0144ceb7264003bc2accbb092Robert Greenwalt                if (DBG) Slog.d(TAG, " deleting " + oldest);
935e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                oldest.delete();
936e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                files = dir.listFiles();
937e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            } while (files.length > MAX_SIMS_SUPPORTED);
938e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        }
939e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
940e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        private File useMRUFile(File dir) {
941e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            File newest = null;
942e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            File[] files = dir.listFiles();
943e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
944e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            for (File f : files) {
945e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                if ((newest == null) || (newest.lastModified() < f.lastModified())) {
946e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                    newest = f;
947e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                }
948e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            }
949e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            if (newest == null) {
950e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt                newest = new File(dir, "temp");
951e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            }
952e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt            return newest;
953e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt        }
954e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
955e6e98823412275d869ec15d71fd11bba98417c45Robert Greenwalt
956b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt        private static final int DATA_FILE_VERSION = 1;
9579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
958b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt        private void record() {
959b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            // 1 int version
9609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 1 int mPeriodCount
9619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13*6 long[PERIOD_COUNT] mPeriodRxData
9629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13*6 long[PERIOD_COUNT] mPeriodTxData
9639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 1  int mCurrentPeriod
9649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13 long periodStartMS
9659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            // 13 long periodEndMS
966b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            // 200 chars max
9679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            StringBuilder builder = new StringBuilder();
968b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            builder.append(DATA_FILE_VERSION);
969b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            builder.append(":");
9709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mPeriodCount);
9719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(":");
972b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            for(int i = 0; i < mPeriodCount; i++) {
9739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(mPeriodRxData[i]);
9749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(":");
9759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
976b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            for(int i = 0; i < mPeriodCount; i++) {
9779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(mPeriodTxData[i]);
9789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                builder.append(":");
9799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
9809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mCurrentPeriod);
9819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(":");
9829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mPeriodStart.getTimeInMillis());
9839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(":");
9849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            builder.append(mPeriodEnd.getTimeInMillis());
9859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
986b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            BufferedWriter out = null;
987b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            try {
9887171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                out = new BufferedWriter(new FileWriter(getDataFile()), 256);
989b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                out.write(builder.toString());
990b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            } catch (IOException e) {
991b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                Slog.e(TAG, "Error writing data file");
992b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                return;
993b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            } finally {
994b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                if (out != null) {
995b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    try {
996b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                        out.close();
997b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    } catch (Exception e) {}
998b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                }
999b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            }
10009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
10019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
10029e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        private void retrieve() {
100305d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            // clean out any old data first.  If we fail to read we don't want old stuff
100405d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt            zeroData(0);
100505d0673bfc5231f6dea4bc99627bbf44edf3a8d0Robert Greenwalt
1006b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            File f = getDataFile();
1007b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            byte[] buffer;
1008b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            FileInputStream s = null;
1009b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            try {
1010b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                buffer = new byte[(int)f.length()];
1011b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                s = new FileInputStream(f);
1012b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                s.read(buffer);
1013b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            } catch (IOException e) {
1014b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                Slog.e(TAG, "Error reading data file");
1015b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                return;
1016b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            } finally {
1017b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                if (s != null) {
1018b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    try {
1019b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                        s.close();
1020b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    } catch (Exception e) {}
1021b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                }
1022b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            }
1023b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt            String data = new String(buffer);
10247171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            if (data == null || data.length() == 0) {
10257171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                if (DBG) Slog.d(TAG, "data file empty");
10267171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                return;
10277171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt            }
10289e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
10299e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                String[] parsed = data.split(":");
10309e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                int parsedUsed = 0;
1031b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                if (parsed.length < 6) {
1032b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    Slog.e(TAG, "reading data file with insufficient length - ignoring");
1033b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    return;
1034b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                }
1035b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt
1036b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                if (Integer.parseInt(parsed[parsedUsed++]) != DATA_FILE_VERSION) {
1037b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    Slog.e(TAG, "reading data file with bad version - ignoring");
1038b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                    return;
1039b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                }
10409e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
10419e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodCount = Integer.parseInt(parsed[parsedUsed++]);
10427171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                if (parsed.length != 5 + (2 * mPeriodCount)) {
10435a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                    Slog.e(TAG, "reading data file with bad length (" + parsed.length +
10445a671d03e3abe522a761a43b0460f9f3816b14edRobert Greenwalt                            " != " + (5+(2*mPeriodCount)) + ") - ignoring");
10457171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                    return;
10467171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                }
10479e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
10489e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodRxData = new long[mPeriodCount];
1049b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                for(int i = 0; i < mPeriodCount; i++) {
10509e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodRxData[i] = Long.parseLong(parsed[parsedUsed++]);
10519e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
10529e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodTxData = new long[mPeriodCount];
1053b8912f5481f79182184b628d7722e1a5b91b27f6Robert Greenwalt                for(int i = 0; i < mPeriodCount; i++) {
10549e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mPeriodTxData[i] = Long.parseLong(parsed[parsedUsed++]);
10559e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                }
10569e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mCurrentPeriod = Integer.parseInt(parsed[parsedUsed++]);
10579e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodStart = new GregorianCalendar();
10589e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodStart.setTimeInMillis(Long.parseLong(parsed[parsedUsed++]));
10599e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodEnd = new GregorianCalendar();
10609e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPeriodEnd.setTimeInMillis(Long.parseLong(parsed[parsedUsed++]));
10619e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
10629e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
10639e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
10649e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long getPeriodRx(int which) {
10659e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
10669e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which > mPeriodCount) return 0;
10679e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                which = mCurrentPeriod - which;
10689e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which < 0) which += mPeriodCount;
10699e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodRxData[which];
10709e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
10719e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
10729e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        long getPeriodTx(int which) {
10739e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            synchronized (mParent) {
10749e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which > mPeriodCount) return 0;
10759e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                which = mCurrentPeriod - which;
10769e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                if (which < 0) which += mPeriodCount;
10779e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                return mPeriodTxData[which];
10789e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            }
10799e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
10809e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
10819e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
10829e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    @Override
10839e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
10849e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        if (mContext.checkCallingOrSelfPermission(
10859e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                android.Manifest.permission.DUMP)
10869e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                != PackageManager.PERMISSION_GRANTED) {
10879e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            pw.println("Permission Denial: can't dump ThrottleService " +
10889e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    "from from pid=" + Binder.getCallingPid() + ", uid=" +
10899e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    Binder.getCallingUid());
10909e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            return;
10919e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
10929e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        pw.println();
10939e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt
10949e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        pw.println("The threshold is " + mPolicyThreshold +
10959e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                ", after which you experince throttling to " +
10969e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                mPolicyThrottleValue + "kbps");
10979e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        pw.println("Current period is " +
10989e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                (mRecorder.getPeriodEnd() - mRecorder.getPeriodStart())/1000 + " seconds long " +
10997171ea8179e09270e4d6ab825a2320816eee39c5Robert Greenwalt                "and ends in " + (getResetTime(mIface) - System.currentTimeMillis()) / 1000 +
11009e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                " seconds.");
11019e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        pw.println("Polling every " + mPolicyPollPeriodSec + " seconds");
11028c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt        pw.println("Current Throttle Index is " + mThrottleIndex);
1103d1055a250c00b0c2516ec406a8cf9a5ab1c0b7aeRobert Greenwalt        pw.println("Max NTP Cache Age is " + mMaxNtpCacheAgeSec);
11048c7e609b530d5dcb34e02788958a84a99501c332Robert Greenwalt
11059e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        for (int i = 0; i < mRecorder.getPeriodCount(); i++) {
11069e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt            pw.println(" Period[" + i + "] - read:" + mRecorder.getPeriodRx(i) + ", written:" +
11079e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt                    mRecorder.getPeriodTx(i));
11089e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt        }
11099e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt    }
11109e696c29f06d45d2891e1d38fd8d9033a9e21bb9Robert Greenwalt}
1111