Merge "Update device password expiration/alarm behavior"
diff --git a/Android.mk b/Android.mk
index 0fe1164..efa7d69 100644
--- a/Android.mk
+++ b/Android.mk
@@ -407,8 +407,6 @@
                             resources/samples/CubeLiveWallpaper "Live Wallpaper" \
 		-samplecode $(sample_dir)/Home \
 		            resources/samples/Home "Home" \
-		-samplecode $(sample_dir)/HeavyWeight \
-		            resources/samples/HeavyWeight "Heavy Weight App" \
 		-samplecode $(sample_dir)/JetBoy \
 		            resources/samples/JetBoy "JetBoy" \
 		-samplecode $(sample_dir)/LunarLander \
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 75ba704..d164d11 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -9061,6 +9061,7 @@
         return mInBatchEditControllers;
     }
 
+    @ViewDebug.ExportedProperty(category = "text")
     private CharSequence            mText;
     private CharSequence            mTransformed;
     private BufferType              mBufferType = BufferType.NORMAL;
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 90423be..bf59753 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -95,6 +95,7 @@
     private final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
     public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
     private final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
+    private final static String DISABLE_LOCKSCREEN_KEY = "lockscreen.disabled";
 
     private final static String PASSWORD_HISTORY_KEY = "lockscreen.passwordhistory";
 
@@ -355,6 +356,26 @@
     }
 
     /**
+     * Disable showing lock screen at all when the DevicePolicyManager allows it.
+     * This is only meaningful if pattern, pin or password are not set.
+     *
+     * @param disable Disables lock screen when true
+     */
+    public void setLockScreenDisabled(boolean disable) {
+        setLong(DISABLE_LOCKSCREEN_KEY, disable ? 1 : 0);
+    }
+
+    /**
+     * Determine if LockScreen can be disabled. This is used, for example, to tell if we should
+     * show LockScreen or go straight to the home screen.
+     *
+     * @return true if lock screen is can be disabled
+     */
+    public boolean isLockScreenDisabled() {
+        return !isSecure() && getLong(DISABLE_LOCKSCREEN_KEY, 0) != 0;
+    }
+
+    /**
      * Save a lock pattern.
      * @param pattern The new pattern to save.
      */
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2de8590..ddc63dd 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -60,7 +60,7 @@
     <protected-broadcast android:name="android.app.action.EXIT_CAR_MODE" />
     <protected-broadcast android:name="android.app.action.ENTER_DESK_MODE" />
     <protected-broadcast android:name="android.app.action.EXIT_DESK_MODE" />
-
+    
     <protected-broadcast android:name="android.backup.intent.RUN" />
     <protected-broadcast android:name="android.backup.intent.CLEAR" />
     <protected-broadcast android:name="android.backup.intent.INIT" />
@@ -1278,7 +1278,7 @@
         android:description="@string/permlab_copyProtectedData"
         android:protectionLevel="signature" />
 
-    <!-- C2DM permission.
+    <!-- C2DM permission. 
          @hide Used internally.
      -->
     <permission android:name="android.intent.category.MASTER_CLEAR.permission.C2D_MESSAGE"
@@ -1332,7 +1332,6 @@
         </activity>
 
         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
-                android:permission="android.permission.ACCOUNT_MANAGER"
                 android:excludeFromRecents="true"
                 android:exported="true">
         </activity>
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 42b73b9..72af34d 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -281,7 +281,7 @@
         mUpdateMonitor.registerSimStateCallback(this);
 
         mLockPatternUtils = new LockPatternUtils(mContext);
-        mKeyguardViewProperties 
+        mKeyguardViewProperties
                 = new LockPatternKeyguardViewProperties(mLockPatternUtils, mUpdateMonitor);
 
         mKeyguardViewManager = new KeyguardViewManager(
@@ -589,6 +589,11 @@
                 return;
             }
 
+            if (mLockPatternUtils.isLockScreenDisabled()) {
+                if (DEBUG) Log.d(TAG, "doKeyguard: not showing because lockscreen is off");
+                return;
+            }
+
             if (DEBUG) Log.d(TAG, "doKeyguard: showing the lock screen");
             showLocked();
         }
@@ -1005,7 +1010,7 @@
                 Log.d(TAG, "playSounds: whichSound = " + whichSound + "; soundPath was null");
             }
         }
-    }        
+    }
 
     /**
      * Handle message sent by {@link #showLocked}.
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index bebd013..2651fd3 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -198,22 +198,26 @@
         public long token;
         public PackageInfo pkgInfo;
         public int pmToken; // in post-install restore, the PM's token for this transaction
+        public boolean needFullBackup;
 
         RestoreParams(IBackupTransport _transport, IRestoreObserver _obs,
-                long _token, PackageInfo _pkg, int _pmToken) {
+                long _token, PackageInfo _pkg, int _pmToken, boolean _needFullBackup) {
             transport = _transport;
             observer = _obs;
             token = _token;
             pkgInfo = _pkg;
             pmToken = _pmToken;
+            needFullBackup = _needFullBackup;
         }
 
-        RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token) {
+        RestoreParams(IBackupTransport _transport, IRestoreObserver _obs, long _token,
+                boolean _needFullBackup) {
             transport = _transport;
             observer = _obs;
             token = _token;
             pkgInfo = null;
             pmToken = 0;
+            needFullBackup = _needFullBackup;
         }
     }
 
@@ -323,7 +327,8 @@
                 RestoreParams params = (RestoreParams)msg.obj;
                 Slog.d(TAG, "MSG_RUN_RESTORE observer=" + params.observer);
                 (new PerformRestoreTask(params.transport, params.observer,
-                        params.token, params.pkgInfo, params.pmToken)).run();
+                        params.token, params.pkgInfo, params.pmToken,
+                        params.needFullBackup)).run();
                 break;
             }
 
@@ -1560,6 +1565,7 @@
         private PackageInfo mTargetPackage;
         private File mStateDir;
         private int mPmToken;
+        private boolean mNeedFullBackup;
 
         class RestoreRequest {
             public PackageInfo app;
@@ -1572,12 +1578,14 @@
         }
 
         PerformRestoreTask(IBackupTransport transport, IRestoreObserver observer,
-                long restoreSetToken, PackageInfo targetPackage, int pmToken) {
+                long restoreSetToken, PackageInfo targetPackage, int pmToken,
+                boolean needFullBackup) {
             mTransport = transport;
             mObserver = observer;
             mToken = restoreSetToken;
             mTargetPackage = targetPackage;
             mPmToken = pmToken;
+            mNeedFullBackup = needFullBackup;
 
             try {
                 mStateDir = new File(mBaseStateDir, transport.transportDirName());
@@ -1655,7 +1663,8 @@
                 // Pull the Package Manager metadata from the restore set first
                 pmAgent = new PackageManagerBackupAgent(
                         mPackageManager, agentPackages);
-                processOneRestore(omPackage, 0, IBackupAgent.Stub.asInterface(pmAgent.onBind()));
+                processOneRestore(omPackage, 0, IBackupAgent.Stub.asInterface(pmAgent.onBind()),
+                        mNeedFullBackup);
 
                 // Verify that the backup set includes metadata.  If not, we can't do
                 // signature/version verification etc, so we simply do not proceed with
@@ -1752,7 +1761,8 @@
 
                     // And then finally run the restore on this agent
                     try {
-                        processOneRestore(packageInfo, metaInfo.versionCode, agent);
+                        processOneRestore(packageInfo, metaInfo.versionCode, agent,
+                                mNeedFullBackup);
                         ++count;
                     } finally {
                         // unbind and tidy up even on timeout or failure, just in case
@@ -1822,7 +1832,8 @@
         }
 
         // Do the guts of a restore of one application, using mTransport.getRestoreData().
-        void processOneRestore(PackageInfo app, int appVersionCode, IBackupAgent agent) {
+        void processOneRestore(PackageInfo app, int appVersionCode, IBackupAgent agent,
+                boolean needFullBackup) {
             // !!! TODO: actually run the restore through mTransport
             final String packageName = app.packageName;
 
@@ -1901,6 +1912,14 @@
                 try { if (newState != null) newState.close(); } catch (IOException e) {}
                 backupData = newState = null;
                 mCurrentOperations.delete(token);
+
+                // If we know a priori that we'll need to perform a full post-restore backup
+                // pass, clear the new state file data.  This means we're discarding work that
+                // was just done by the app's agent, but this way the agent doesn't need to
+                // take any special action based on global device state.
+                if (needFullBackup) {
+                    newStateName.delete();
+                }
             }
         }
     }
@@ -2386,7 +2405,7 @@
             mWakelock.acquire();
             Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
             msg.obj = new RestoreParams(getTransport(mCurrentTransport), null,
-                    restoreSet, pkg, token);
+                    restoreSet, pkg, token, true);
             mBackupHandler.sendMessage(msg);
         } else {
             // Auto-restore disabled or no way to attempt a restore; just tell the Package
@@ -2517,7 +2536,7 @@
                         long oldId = Binder.clearCallingIdentity();
                         mWakelock.acquire();
                         Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
-                        msg.obj = new RestoreParams(mRestoreTransport, observer, token);
+                        msg.obj = new RestoreParams(mRestoreTransport, observer, token, true);
                         mBackupHandler.sendMessage(msg);
                         Binder.restoreCallingIdentity(oldId);
                         return 0;
@@ -2582,7 +2601,7 @@
             long oldId = Binder.clearCallingIdentity();
             mWakelock.acquire();
             Message msg = mBackupHandler.obtainMessage(MSG_RUN_RESTORE);
-            msg.obj = new RestoreParams(mRestoreTransport, observer, token, app, 0);
+            msg.obj = new RestoreParams(mRestoreTransport, observer, token, app, 0, false);
             mBackupHandler.sendMessage(msg);
             Binder.restoreCallingIdentity(oldId);
             return 0;
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java
index a79aead..d1aba437 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/FsUtils.java
@@ -39,9 +39,12 @@
 import org.apache.http.util.EntityUtils;
 
 import java.io.BufferedReader;
+import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -49,6 +52,7 @@
 import java.net.MalformedURLException;
 import java.net.SocketTimeoutException;
 import java.net.URL;
+import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -274,4 +278,37 @@
             Log.e(LOG_TAG, "Couldn't close stream!", e);
         }
     }
+
+    public static List<String> loadTestListFromStorage(String path) {
+        List<String> list = new ArrayList<String>();
+        if (path != null && !path.isEmpty()) {
+            try {
+                File file = new File(path);
+                Log.d(LOG_TAG, "test list loaded from " + path);
+                BufferedReader reader = new BufferedReader(new FileReader(file));
+                String line = null;
+                while ((line = reader.readLine()) != null) {
+                    list.add(line);
+                }
+                reader.close();
+            } catch (IOException ioe) {
+                Log.e(LOG_TAG, "failed to load test list", ioe);
+            }
+        }
+        return list;
+    }
+
+    public static void saveTestListToStorage(File file, int start, List<String> testList) {
+        try {
+            BufferedWriter writer = new BufferedWriter(
+                    new FileWriter(file));
+            for (String line : testList.subList(start, testList.size())) {
+                writer.write(line + '\n');
+            }
+            writer.flush();
+            writer.close();
+        } catch (IOException e) {
+            Log.e(LOG_TAG, "failed to write test list", e);
+        }
+    }
 }
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
index 7efb03f..ce546ec 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
@@ -21,17 +21,15 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.net.Uri;
 import android.net.http.SslError;
 import android.os.Bundle;
-import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.Messenger;
 import android.os.PowerManager;
-import android.os.Process;
 import android.os.PowerManager.WakeLock;
+import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.Window;
@@ -48,10 +46,7 @@
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
 
-import java.io.File;
 import java.lang.Thread.UncaughtExceptionHandler;
-import java.net.MalformedURLException;
-import java.net.URL;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -79,7 +74,7 @@
 
     private static final String LOG_TAG = "LayoutTestsExecutor";
 
-    public static final String EXTRA_TESTS_LIST = "TestsList";
+    public static final String EXTRA_TESTS_FILE = "TestsList";
     public static final String EXTRA_TEST_INDEX = "TestIndex";
 
     private static final int MSG_ACTUAL_RESULT_OBTAINED = 0;
@@ -305,7 +300,7 @@
         requestWindowFeature(Window.FEATURE_PROGRESS);
 
         Intent intent = getIntent();
-        mTestsList = intent.getStringArrayListExtra(EXTRA_TESTS_LIST);
+        mTestsList = FsUtils.loadTestListFromStorage(intent.getStringExtra(EXTRA_TESTS_FILE));
         mCurrentTestIndex = intent.getIntExtra(EXTRA_TEST_INDEX, -1);
         mTotalTestCount = mCurrentTestIndex + mTestsList.size();
 
@@ -735,4 +730,5 @@
         Log.i(LOG_TAG, mCurrentTestRelativePath + ": waitUntilDone() called");
         mLayoutTestControllerHandler.sendEmptyMessage(MSG_WAIT_UNTIL_DONE);
     }
+
 }
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListActivity.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListActivity.java
index 9db4d2b..e374c1b 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListActivity.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TestsListActivity.java
@@ -16,6 +16,8 @@
 
 package com.android.dumprendertree2;
 
+import com.android.dumprendertree2.scriptsupport.OnEverythingFinishedCallback;
+
 import android.app.Activity;
 import android.app.ProgressDialog;
 import android.content.Intent;
@@ -28,8 +30,7 @@
 import android.webkit.WebView;
 import android.widget.Toast;
 
-import com.android.dumprendertree2.scriptsupport.OnEverythingFinishedCallback;
-
+import java.io.File;
 import java.util.ArrayList;
 
 /**
@@ -189,12 +190,12 @@
         intent.setAction(Intent.ACTION_RUN);
 
         if (startFrom < mTotalTestCount) {
-            intent.putStringArrayListExtra(LayoutTestsExecutor.EXTRA_TESTS_LIST,
-                    new ArrayList<String>(mTestsList.subList(startFrom, mTotalTestCount)));
+            File testListFile = new File(getExternalFilesDir(null), "test_list.txt");
+            FsUtils.saveTestListToStorage(testListFile, startFrom, mTestsList);
+            intent.putExtra(LayoutTestsExecutor.EXTRA_TESTS_FILE, testListFile.getAbsolutePath());
             intent.putExtra(LayoutTestsExecutor.EXTRA_TEST_INDEX, startFrom);
         } else {
-            intent.putStringArrayListExtra(LayoutTestsExecutor.EXTRA_TESTS_LIST,
-                    new ArrayList<String>());
+            intent.putExtra(LayoutTestsExecutor.EXTRA_TESTS_FILE, "");
         }
 
         startActivity(intent);