Merge "GpsLocationProvider: Eliminate MIN_FIX_COUNT." into kraken
diff --git a/policy/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/com/android/internal/policy/impl/AccountUnlockScreen.java
index 9921069..cb88916 100644
--- a/policy/com/android/internal/policy/impl/AccountUnlockScreen.java
+++ b/policy/com/android/internal/policy/impl/AccountUnlockScreen.java
@@ -29,7 +29,6 @@
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.graphics.Rect;
-import android.telephony.TelephonyManager;
 import android.text.Editable;
 import android.text.InputFilter;
 import android.text.LoginFilter;
@@ -65,6 +64,7 @@
 
     private final KeyguardScreenCallback mCallback;
     private final LockPatternUtils mLockPatternUtils;
+    private KeyguardUpdateMonitor mUpdateMonitor;
 
     private TextView mTopHeader;
     private TextView mInstructions;
@@ -81,9 +81,11 @@
     /**
      * AccountUnlockScreen constructor.
      * @param configuration
+     * @param updateMonitor
      */
     public AccountUnlockScreen(Context context,Configuration configuration,
-            KeyguardScreenCallback callback, LockPatternUtils lockPatternUtils) {
+            KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback,
+            LockPatternUtils lockPatternUtils) {
         super(context);
         mCallback = callback;
         mLockPatternUtils = lockPatternUtils;
@@ -111,6 +113,9 @@
         mEmergencyCall = (Button) findViewById(R.id.emergencyCall);
         mEmergencyCall.setOnClickListener(this);
         mLockPatternUtils.updateEmergencyCallButtonState(mEmergencyCall);
+
+        mUpdateMonitor = updateMonitor;
+        mUpdateMonitor.registerInfoCallback(this);
     }
 
     public void afterTextChanged(Editable s) {
@@ -154,6 +159,7 @@
         if (mCheckingDialog != null) {
             mCheckingDialog.hide();
         }
+        mUpdateMonitor.removeCallback(this);
     }
 
     /** {@inheritDoc} */
diff --git a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
index c1b14c4..27706ef 100644
--- a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -601,6 +601,7 @@
                 unlockView = new AccountUnlockScreen(
                         mContext,
                         mConfiguration,
+                        mUpdateMonitor,
                         mKeyguardScreenCallback,
                         mLockPatternUtils);
             } catch (IllegalStateException e) {
diff --git a/policy/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/com/android/internal/policy/impl/PasswordUnlockScreen.java
index a0e4f93..39f2917 100644
--- a/policy/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -60,7 +60,7 @@
     private PasswordEntryKeyboardHelper mKeyboardHelper;
 
     private int mCreationOrientation;
-    private int mKeyboardHidden;
+    private int mCreationHardKeyboardHidden;
     private CountDownTimer mCountdownTimer;
     private TextView mTitle;
 
@@ -73,7 +73,7 @@
             KeyguardScreenCallback callback) {
         super(context);
 
-        mKeyboardHidden = configuration.hardKeyboardHidden;
+        mCreationHardKeyboardHidden = configuration.hardKeyboardHidden;
         mCreationOrientation = configuration.orientation;
         mUpdateMonitor = updateMonitor;
         mCallback = callback;
@@ -102,7 +102,7 @@
         mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
                 : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
 
-        mKeyboardView.setVisibility(mKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO
+        mKeyboardView.setVisibility(mCreationHardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_NO
                 ? View.INVISIBLE : View.VISIBLE);
         mPasswordEntry.requestFocus();
 
@@ -213,8 +213,10 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        if (getResources().getConfiguration().orientation != mCreationOrientation) {
-            mCallback.recreateMe(getResources().getConfiguration());
+        Configuration config = getResources().getConfiguration();
+        if (config.orientation != mCreationOrientation
+                || config.hardKeyboardHidden != mCreationHardKeyboardHidden) {
+            mCallback.recreateMe(config);
         }
     }
 
@@ -222,7 +224,8 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        if (newConfig.orientation != mCreationOrientation) {
+        if (newConfig.orientation != mCreationOrientation
+                || newConfig.hardKeyboardHidden != mCreationHardKeyboardHidden) {
             mCallback.recreateMe(newConfig);
         }
     }
diff --git a/services/java/com/android/server/ThrottleService.java b/services/java/com/android/server/ThrottleService.java
index 6ba96ae..dcc053d 100644
--- a/services/java/com/android/server/ThrottleService.java
+++ b/services/java/com/android/server/ThrottleService.java
@@ -44,6 +44,7 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
 import android.util.Slog;
 
 import com.android.internal.telephony.TelephonyProperties;
@@ -607,11 +608,17 @@
 
         ThrottleService mParent;
         Context mContext;
+        String mImsi = null;
+
+        TelephonyManager mTelephonyManager;
 
         DataRecorder(Context context, ThrottleService parent) {
             mContext = context;
             mParent = parent;
 
+            mTelephonyManager = (TelephonyManager)mContext.getSystemService(
+                    Context.TELEPHONY_SERVICE);
+
             synchronized (mParent) {
                 mPeriodCount = 6;
                 mPeriodRxData = new long[mPeriodCount];
@@ -626,6 +633,8 @@
         }
 
         void setNextPeriod(Calendar start, Calendar end) {
+            // TODO - how would we deal with a dual-IMSI device?
+            checkForSubscriberId();
             if (DBG) {
                 Slog.d(TAG, "setting next period to " + start.getTimeInMillis() +
                         " --until-- " + end.getTimeInMillis());
@@ -703,6 +712,7 @@
         // if time moves backward accumulate all read/write that's lost into the now
         // otherwise time moved forward.
         void addData(long bytesRead, long bytesWritten) {
+            checkForSubscriberId();
             synchronized (mParent) {
                 mPeriodRxData[mCurrentPeriod] += bytesRead;
                 mPeriodTxData[mCurrentPeriod] += bytesWritten;
@@ -714,10 +724,69 @@
             File dataDir = Environment.getDataDirectory();
             File throttleDir = new File(dataDir, "system/throttle");
             throttleDir.mkdirs();
-            File dataFile = new File(throttleDir, "data");
+            String mImsi = mTelephonyManager.getSubscriberId();
+            File dataFile;
+            if (mImsi == null) {
+                dataFile = useMRUFile(throttleDir);
+                Slog.d(TAG, "imsi not available yet, using " + dataFile);
+            } else {
+                String imsiHash = Integer.toString(mImsi.hashCode());
+                dataFile = new File(throttleDir, imsiHash);
+            }
+            // touch the file so it's not LRU
+            dataFile.setLastModified(System.currentTimeMillis());
+            checkAndDeleteLRUDataFile(throttleDir);
             return dataFile;
         }
 
+        // TODO - get broadcast (TelephonyIntents.ACTION_SIM_STATE_CHANGED) instead of polling
+        private void checkForSubscriberId() {
+            if (mImsi != null) return;
+
+            mImsi = mTelephonyManager.getSubscriberId();
+            if (mImsi == null) return;
+
+            Slog.d(TAG, "finally have imsi - retreiving data");
+            retrieve();
+        }
+
+        private final static int MAX_SIMS_SUPPORTED = 3;
+
+        private void checkAndDeleteLRUDataFile(File dir) {
+            File[] files = dir.listFiles();
+
+            if (files.length <= MAX_SIMS_SUPPORTED) return;
+            Slog.d(TAG, "Too many data files");
+            do {
+                File oldest = null;
+                for (File f : files) {
+                    if ((oldest == null) || (oldest.lastModified() > f.lastModified())) {
+                        oldest = f;
+                    }
+                }
+                if (oldest == null) return;
+                Slog.d(TAG, " deleting " + oldest);
+                oldest.delete();
+                files = dir.listFiles();
+            } while (files.length > MAX_SIMS_SUPPORTED);
+        }
+
+        private File useMRUFile(File dir) {
+            File newest = null;
+            File[] files = dir.listFiles();
+
+            for (File f : files) {
+                if ((newest == null) || (newest.lastModified() < f.lastModified())) {
+                    newest = f;
+                }
+            }
+            if (newest == null) {
+                newest = new File(dir, "temp");
+            }
+            return newest;
+        }
+
+
         private static final int DATA_FILE_VERSION = 1;
 
         private void record() {