Merge "New APIs for MTP and PTP host support"
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a25aae1..79890ef 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -4440,6 +4440,7 @@
         mFragments.dispatchPause();
         mCalled = false;
         onPause();
+        mResumed = false;
         if (!mCalled && getApplicationInfo().targetSdkVersion
                 >= android.os.Build.VERSION_CODES.GINGERBREAD) {
             throw new SuperNotCalledException(
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 34788a5..c095c06 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -376,6 +376,14 @@
             return true;
         }
 
+        case ACTIVITY_SLEPT_TRANSACTION: {
+            data.enforceInterface(IActivityManager.descriptor);
+            IBinder token = data.readStrongBinder();
+            activitySlept(token);
+            reply.writeNoException();
+            return true;
+        }
+
         case ACTIVITY_DESTROYED_TRANSACTION: {
             data.enforceInterface(IActivityManager.descriptor);
             IBinder token = data.readStrongBinder();
@@ -1719,6 +1727,17 @@
         data.recycle();
         reply.recycle();
     }
+    public void activitySlept(IBinder token) throws RemoteException
+    {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeStrongBinder(token);
+        mRemote.transact(ACTIVITY_SLEPT_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
+        reply.readException();
+        data.recycle();
+        reply.recycle();
+    }
     public void activityDestroyed(IBinder token) throws RemoteException
     {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4026ea0..81ef317 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -424,6 +424,10 @@
                 token);
         }
 
+        public final void scheduleSleeping(IBinder token, boolean sleeping) {
+            queueOrSendMessage(H.SLEEPING, token, sleeping ? 1 : 0);
+        }
+
         public final void scheduleResumeActivity(IBinder token, boolean isForward) {
             queueOrSendMessage(H.RESUME_ACTIVITY, token, isForward ? 1 : 0);
         }
@@ -932,6 +936,7 @@
         public static final int SCHEDULE_CRASH          = 134;
         public static final int DUMP_HEAP               = 135;
         public static final int DUMP_ACTIVITY           = 136;
+        public static final int SLEEPING                = 137;
         String codeToString(int code) {
             if (DEBUG_MESSAGES) {
                 switch (code) {
@@ -972,6 +977,7 @@
                     case SCHEDULE_CRASH: return "SCHEDULE_CRASH";
                     case DUMP_HEAP: return "DUMP_HEAP";
                     case DUMP_ACTIVITY: return "DUMP_ACTIVITY";
+                    case SLEEPING: return "SLEEPING";
                 }
             }
             return "(unknown)";
@@ -1104,6 +1110,9 @@
                 case DUMP_ACTIVITY:
                     handleDumpActivity((DumpComponentInfo)msg.obj);
                     break;
+                case SLEEPING:
+                    handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
+                    break;
             }
             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + msg.what);
         }
@@ -2651,6 +2660,42 @@
         }
     }
 
+    private final void handleSleeping(IBinder token, boolean sleeping) {
+        ActivityClientRecord r = mActivities.get(token);
+
+        if (r == null) {
+            Log.w(TAG, "handleSleeping: no activity for token " + token);
+            return;
+        }
+
+        if (sleeping) {
+            if (!r.stopped && !r.isPreHoneycomb()) {
+                try {
+                    // Now we are idle.
+                    r.activity.performStop();
+                } catch (Exception e) {
+                    if (!mInstrumentation.onException(r.activity, e)) {
+                        throw new RuntimeException(
+                                "Unable to stop activity "
+                                + r.intent.getComponent().toShortString()
+                                + ": " + e.toString(), e);
+                    }
+                }
+                r.stopped = true;
+            }
+            // Tell activity manager we slept.
+            try {
+                ActivityManagerNative.getDefault().activitySlept(r.token);
+            } catch (RemoteException ex) {
+            }
+        } else {
+            if (r.stopped && r.activity.mVisibleFromServer) {
+                r.activity.performRestart();
+                r.stopped = false;
+            }
+        }
+    }
+
     private final void deliverResults(ActivityClientRecord r, List<ResultInfo> results) {
         final int N = results.size();
         for (int i=0; i<N; i++) {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index d28e853..ef92933 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -97,6 +97,15 @@
             return true;
         }
 
+        case SCHEDULE_SLEEPING_TRANSACTION:
+        {
+            data.enforceInterface(IApplicationThread.descriptor);
+            IBinder b = data.readStrongBinder();
+            boolean sleeping = data.readInt() != 0;
+            scheduleSleeping(b, sleeping);
+            return true;
+        }
+
         case SCHEDULE_RESUME_ACTIVITY_TRANSACTION:
         {
             data.enforceInterface(IApplicationThread.descriptor);
@@ -503,6 +512,17 @@
         data.recycle();
     }
 
+    public final void scheduleSleeping(IBinder token,
+            boolean sleeping) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        data.writeInterfaceToken(IApplicationThread.descriptor);
+        data.writeStrongBinder(token);
+        data.writeInt(sleeping ? 1 : 0);
+        mRemote.transact(SCHEDULE_SLEEPING_TRANSACTION, data, null,
+                IBinder.FLAG_ONEWAY);
+        data.recycle();
+    }
+
     public final void scheduleResumeActivity(IBinder token, boolean isForward)
             throws RemoteException {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index abffbdb..5d4380b 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -124,6 +124,8 @@
     public void activityStopped(IBinder token, Bundle state,
             Bitmap thumbnail, CharSequence description) throws RemoteException;
     /* oneway */
+    public void activitySlept(IBinder token) throws RemoteException;
+    /* oneway */
     public void activityDestroyed(IBinder token) throws RemoteException;
     public String getCallingPackage(IBinder token) throws RemoteException;
     public ComponentName getCallingActivity(IBinder token) throws RemoteException;
@@ -553,4 +555,5 @@
     int DUMP_HEAP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+119;
     int START_ACTIVITIES_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+120;
     int START_ACTIVITIES_IN_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+121;
+    int ACTIVITY_SLEPT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+122;
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index ecd199c..16c3c5c 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -48,6 +48,7 @@
     void scheduleStopActivity(IBinder token, boolean showWindow,
             int configChanges) throws RemoteException;
     void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
+    void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;
     void scheduleResumeActivity(IBinder token, boolean isForward) throws RemoteException;
     void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
     void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
@@ -137,7 +138,7 @@
     int SCHEDULE_LOW_MEMORY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+23;
     int SCHEDULE_ACTIVITY_CONFIGURATION_CHANGED_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+24;
     int SCHEDULE_RELAUNCH_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+25;
-
+    int SCHEDULE_SLEEPING_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+26;
     int PROFILER_CONTROL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+27;
     int SET_SCHEDULING_GROUP_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+28;
     int SCHEDULE_CREATE_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+29;
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index abc457e..a595562 100644
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -222,7 +222,6 @@
 
     private int[] getObjectList(int storageID, int format, int parent) {
         // we can ignore storageID until we support multiple storages
-        Log.d(TAG, "getObjectList parent: " + parent);
         Cursor c = null;
         try {
             if (format != 0) {
@@ -235,7 +234,6 @@
                             PARENT_WHERE, new String[] { Integer.toString(parent) }, null);
             }
             if (c == null) {
-                Log.d(TAG, "null cursor");
                 return null;
             }
             int count = c.getCount();
@@ -245,7 +243,6 @@
                     c.moveToNext();
                     result[i] = c.getInt(0);
                 }
-                Log.d(TAG, "returning " + result);
                 return result;
             }
         } catch (RemoteException e) {
@@ -260,7 +257,6 @@
 
     private int getNumObjects(int storageID, int format, int parent) {
         // we can ignore storageID until we support multiple storages
-        Log.d(TAG, "getObjectList parent: " + parent);
         Cursor c = null;
         try {
             if (format != 0) {
@@ -529,8 +525,8 @@
         String newPath = path.substring(0, lastSlash + 1) + newName;
         File newFile = new File(newPath);
         boolean success = oldFile.renameTo(newFile);
-        Log.d(TAG, "renaming "+ path + " to " + newPath + (success ? " succeeded" : " failed"));
         if (!success) {
+            Log.w(TAG, "renaming "+ path + " to " + newPath + " failed");
             return MtpConstants.RESPONSE_GENERAL_ERROR;
         }
 
@@ -557,8 +553,6 @@
 
     private int setObjectProperty(int handle, int property,
                             long intValue, String stringValue) {
-        Log.d(TAG, "setObjectProperty: " + property);
-
         switch (property) {
             case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
                 return renameFile(handle, stringValue);
@@ -569,8 +563,6 @@
     }
 
     private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) {
-        Log.d(TAG, "getDeviceProperty: " + property);
-
         switch (property) {
             case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
             case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
@@ -616,8 +608,6 @@
     }
 
     private int setDeviceProperty(int property, long intValue, String stringValue) {
-        Log.d(TAG, "setDeviceProperty: " + property + " : " + stringValue);
-
         switch (property) {
             case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
             case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
@@ -638,7 +628,6 @@
 
     private boolean getObjectInfo(int handle, int[] outStorageFormatParent,
                         char[] outName, long[] outSizeModified) {
-        Log.d(TAG, "getObjectInfo: " + handle);
         Cursor c = null;
         try {
             c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION,
@@ -674,7 +663,6 @@
     }
 
     private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLengthFormat) {
-        Log.d(TAG, "getObjectFilePath: " + handle);
         if (handle == 0) {
             // special case root directory
             mMediaStoragePath.getChars(0, mMediaStoragePath.length(), outFilePath, 0);
@@ -708,7 +696,6 @@
     }
 
     private int deleteFile(int handle) {
-        Log.d(TAG, "deleteFile: " + handle);
         mDatabaseModified = true;
         String path = null;
         int format = 0;
@@ -754,7 +741,6 @@
     }
 
     private int[] getObjectReferences(int handle) {
-        Log.d(TAG, "getObjectReferences for: " + handle);
         Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
         Cursor c = null;
         try {
@@ -802,14 +788,11 @@
     }
 
     private void sessionStarted() {
-        Log.d(TAG, "sessionStarted");
         mDatabaseModified = false;
     }
 
     private void sessionEnded() {
-        Log.d(TAG, "sessionEnded");
         if (mDatabaseModified) {
-            Log.d(TAG, "sending ACTION_MTP_SESSION_END");
             mContext.sendBroadcast(new Intent(MediaStore.ACTION_MTP_SESSION_END));
             mDatabaseModified = false;
         }
diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java
index af6e8eb..2e69373 100644
--- a/media/java/android/mtp/MtpServer.java
+++ b/media/java/android/mtp/MtpServer.java
@@ -34,15 +34,6 @@
         native_setup(database, storagePath, reserveSpace);
     }
 
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            native_finalize();
-        } finally {
-            super.finalize();
-        }
-    }
-
     public void start() {
         native_start();
     }
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 9abf6a2..17d39e3 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -1031,7 +1031,6 @@
 android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
 {
 #ifdef HAVE_ANDROID_OS
-    LOGD("setup\n");
     MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
     env->SetIntField(thiz, field_context, (int)database);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
@@ -1042,7 +1041,6 @@
 android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
 {
 #ifdef HAVE_ANDROID_OS
-    LOGD("finalize\n");
     MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
     database->cleanup(env);
     delete database;
@@ -1081,8 +1079,6 @@
 {
     jclass clazz;
 
-    LOGD("register_android_mtp_MtpDatabase\n");
-
     clazz = env->FindClass("android/mtp/MtpDatabase");
     if (clazz == NULL) {
         LOGE("Can't find android/mtp/MtpDatabase");
diff --git a/media/jni/android_mtp_MtpServer.cpp b/media/jni/android_mtp_MtpServer.cpp
index 8908e67..1452d21 100644
--- a/media/jni/android_mtp_MtpServer.cpp
+++ b/media/jni/android_mtp_MtpServer.cpp
@@ -111,7 +111,6 @@
 
             sMutex.unlock();
 
-            LOGD("MtpThread mServer->run");
             mServer->run();
             sleep(1);
 
@@ -128,7 +127,6 @@
         env->DeleteGlobalRef(mJavaServer);
         sMutex.unlock();
 
-        LOGD("threadLoop returning");
         return false;
     }
 
@@ -160,8 +158,6 @@
         jstring storagePath, jlong reserveSpace)
 {
 #ifdef HAVE_ANDROID_OS
-    LOGD("setup\n");
-
     MtpDatabase* database = getMtpDatabase(env, javaDatabase);
     const char *storagePathStr = env->GetStringUTFChars(storagePath, NULL);
 
@@ -174,17 +170,9 @@
 }
 
 static void
-android_mtp_MtpServer_finalize(JNIEnv *env, jobject thiz)
-{
-    LOGD("finalize\n");
-}
-
-
-static void
 android_mtp_MtpServer_start(JNIEnv *env, jobject thiz)
 {
 #ifdef HAVE_ANDROID_OS
-    LOGD("start\n");
     MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
     thread->run("MtpThread");
 #endif // HAVE_ANDROID_OS
@@ -194,7 +182,6 @@
 android_mtp_MtpServer_stop(JNIEnv *env, jobject thiz)
 {
 #ifdef HAVE_ANDROID_OS
-    LOGD("stop\n");
     MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
     if (thread)
         thread->stop();
@@ -225,7 +212,6 @@
 android_mtp_MtpServer_set_ptp_mode(JNIEnv *env, jobject thiz, jboolean usePtp)
 {
 #ifdef HAVE_ANDROID_OS
-    LOGD("set_ptp_mode\n");
     MtpThread *thread = (MtpThread *)env->GetIntField(thiz, field_context);
     if (thread)
         thread->setPtpMode(usePtp);
@@ -237,7 +223,6 @@
 static JNINativeMethod gMethods[] = {
     {"native_setup",                "(Landroid/mtp/MtpDatabase;Ljava/lang/String;J)V",
                                             (void *)android_mtp_MtpServer_setup},
-    {"native_finalize",             "()V",  (void *)android_mtp_MtpServer_finalize},
     {"native_start",                "()V",  (void *)android_mtp_MtpServer_start},
     {"native_stop",                 "()V",  (void *)android_mtp_MtpServer_stop},
     {"native_send_object_added",    "(I)V", (void *)android_mtp_MtpServer_send_object_added},
@@ -251,8 +236,6 @@
 {
     jclass clazz;
 
-    LOGD("register_android_mtp_MtpServer\n");
-
     clazz = env->FindClass("android/mtp/MtpServer");
     if (clazz == NULL) {
         LOGE("Can't find android/mtp/MtpServer");
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index b1bd145..be004d2 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -130,7 +130,7 @@
     while (1) {
         int ret = mRequest.read(fd);
         if (ret < 0) {
-            LOGE("request read returned %d, errno: %d", ret, errno);
+            LOGV("request read returned %d, errno: %d", ret, errno);
             if (errno == ECANCELED) {
                 // return to top of loop and wait for next command
                 continue;
@@ -204,23 +204,23 @@
 
 void MtpServer::sendObjectAdded(MtpObjectHandle handle) {
     if (mSessionOpen) {
-        LOGD("sendObjectAdded %d\n", handle);
+        LOGV("sendObjectAdded %d\n", handle);
         mEvent.setEventCode(MTP_EVENT_OBJECT_ADDED);
         mEvent.setTransactionID(mRequest.getTransactionID());
         mEvent.setParameter(1, handle);
         int ret = mEvent.write(mFD);
-        LOGD("mEvent.write returned %d\n", ret);
+        LOGV("mEvent.write returned %d\n", ret);
     }
 }
 
 void MtpServer::sendObjectRemoved(MtpObjectHandle handle) {
     if (mSessionOpen) {
-        LOGD("sendObjectRemoved %d\n", handle);
+        LOGV("sendObjectRemoved %d\n", handle);
         mEvent.setEventCode(MTP_EVENT_OBJECT_REMOVED);
         mEvent.setTransactionID(mRequest.getTransactionID());
         mEvent.setParameter(1, handle);
         int ret = mEvent.write(mFD);
-        LOGD("mEvent.write returned %d\n", ret);
+        LOGV("mEvent.write returned %d\n", ret);
     }
 }
 
@@ -496,7 +496,7 @@
 MtpResponseCode MtpServer::doGetObjectPropValue() {
     MtpObjectHandle handle = mRequest.getParameter(1);
     MtpObjectProperty property = mRequest.getParameter(2);
-    LOGD("GetObjectPropValue %d %s\n", handle,
+    LOGV("GetObjectPropValue %d %s\n", handle,
             MtpDebug::getObjectPropCodeName(property));
 
     return mDatabase->getObjectPropertyValue(handle, property, mData);
@@ -505,7 +505,7 @@
 MtpResponseCode MtpServer::doSetObjectPropValue() {
     MtpObjectHandle handle = mRequest.getParameter(1);
     MtpObjectProperty property = mRequest.getParameter(2);
-    LOGD("SetObjectPropValue %d %s\n", handle,
+    LOGV("SetObjectPropValue %d %s\n", handle,
             MtpDebug::getObjectPropCodeName(property));
 
     return mDatabase->setObjectPropertyValue(handle, property, mData);
@@ -513,7 +513,7 @@
 
 MtpResponseCode MtpServer::doGetDevicePropValue() {
     MtpDeviceProperty property = mRequest.getParameter(1);
-    LOGD("GetDevicePropValue %s\n",
+    LOGV("GetDevicePropValue %s\n",
             MtpDebug::getDevicePropCodeName(property));
 
     return mDatabase->getDevicePropertyValue(property, mData);
@@ -521,7 +521,7 @@
 
 MtpResponseCode MtpServer::doSetDevicePropValue() {
     MtpDeviceProperty property = mRequest.getParameter(1);
-    LOGD("SetDevicePropValue %s\n",
+    LOGV("SetDevicePropValue %s\n",
             MtpDebug::getDevicePropCodeName(property));
 
     return mDatabase->setDevicePropertyValue(property, mData);
@@ -529,7 +529,7 @@
 
 MtpResponseCode MtpServer::doResetDevicePropValue() {
     MtpDeviceProperty property = mRequest.getParameter(1);
-    LOGD("ResetDevicePropValue %s\n",
+    LOGV("ResetDevicePropValue %s\n",
             MtpDebug::getDevicePropCodeName(property));
 
     return mDatabase->resetDeviceProperty(property);
@@ -543,7 +543,7 @@
     uint32_t property = mRequest.getParameter(3);
     int groupCode = mRequest.getParameter(4);
     int depth = mRequest.getParameter(5);
-   LOGD("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n",
+   LOGV("GetObjectPropList %d format: %s property: %s group: %d depth: %d\n",
             handle, MtpDebug::getFormatCodeName(format),
             MtpDebug::getObjectPropCodeName(property), groupCode, depth);
 
@@ -674,7 +674,7 @@
     mData.getString(modified);     // date modified
     // keywords follow
 
-    LOGD("name: %s format: %04X\n", (const char *)name, format);
+    LOGV("name: %s format: %04X\n", (const char *)name, format);
     time_t modifiedTime;
     if (!parseDateTime(modified, modifiedTime))
         modifiedTime = 0;
@@ -750,7 +750,7 @@
     mfr.offset = 0;
     mfr.length = mSendObjectFileSize;
 
-    LOGD("receiving %s\n", (const char *)mSendObjectFilePath);
+    LOGV("receiving %s\n", (const char *)mSendObjectFilePath);
     // transfer the file
     ret = ioctl(mFD, MTP_RECEIVE_FILE, (unsigned long)&mfr);
     close(mfr.fd);
@@ -854,7 +854,7 @@
 MtpResponseCode MtpServer::doGetObjectPropDesc() {
     MtpObjectProperty propCode = mRequest.getParameter(1);
     MtpObjectFormat format = mRequest.getParameter(2);
-    LOGD("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode),
+    LOGV("GetObjectPropDesc %s %s\n", MtpDebug::getObjectPropCodeName(propCode),
                                         MtpDebug::getFormatCodeName(format));
     MtpProperty* property = mDatabase->getObjectPropertyDesc(propCode, format);
     if (!property)
@@ -866,7 +866,7 @@
 
 MtpResponseCode MtpServer::doGetDevicePropDesc() {
     MtpDeviceProperty propCode = mRequest.getParameter(1);
-    LOGD("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode));
+    LOGV("GetDevicePropDesc %s\n", MtpDebug::getDevicePropCodeName(propCode));
     MtpProperty* property = mDatabase->getDevicePropertyDesc(propCode);
     if (!property)
         return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
diff --git a/media/mtp/MtpStorage.cpp b/media/mtp/MtpStorage.cpp
index abc23de..2fbbc51 100644
--- a/media/mtp/MtpStorage.cpp
+++ b/media/mtp/MtpStorage.cpp
@@ -38,7 +38,7 @@
         mMaxCapacity(0),
         mReserveSpace(reserveSpace)
 {
-    LOGD("MtpStorage id: %d path: %s\n", id, filePath);
+    LOGV("MtpStorage id: %d path: %s\n", id, filePath);
 }
 
 MtpStorage::~MtpStorage() {
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index b7a6372..8ea166f 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -5858,16 +5858,18 @@
         return pfd;
     }
 
+    // Actually is sleeping or shutting down or whatever else in the future
+    // is an inactive state.
+    public boolean isSleeping() {
+        return mSleeping || mShuttingDown;
+    }
+
     public void goingToSleep() {
         synchronized(this) {
             mSleeping = true;
             mWindowManager.setEventDispatching(false);
 
-            if (mMainStack.mResumedActivity != null) {
-                mMainStack.pauseIfSleepingLocked();
-            } else {
-                Slog.w(TAG, "goingToSleep with no resumed activity!");
-            }
+            mMainStack.stopIfSleepingLocked();
 
             // Initialize the wake times of all processes.
             checkExcessivePowerUsageLocked(false);
@@ -5891,7 +5893,7 @@
             mWindowManager.setEventDispatching(false);
 
             if (mMainStack.mResumedActivity != null) {
-                mMainStack.pauseIfSleepingLocked();
+                mMainStack.stopIfSleepingLocked();
                 final long endTime = System.currentTimeMillis() + timeout;
                 while (mMainStack.mResumedActivity != null
                         || mMainStack.mPausingActivity != null) {
@@ -5915,13 +5917,30 @@
         return timedout;
     }
     
+    public final void activitySlept(IBinder token) {
+        if (localLOGV) Slog.v(
+            TAG, "Activity slept: token=" + token);
+
+        ActivityRecord r = null;
+
+        final long origId = Binder.clearCallingIdentity();
+
+        synchronized (this) {
+            int index = mMainStack.indexOfTokenLocked(token);
+            if (index >= 0) {
+                r = (ActivityRecord)mMainStack.mHistory.get(index);
+                mMainStack.activitySleptLocked(r);
+            }
+        }
+
+        Binder.restoreCallingIdentity(origId);
+    }
+
     public void wakingUp() {
         synchronized(this) {
-            if (mMainStack.mGoingToSleep.isHeld()) {
-                mMainStack.mGoingToSleep.release();
-            }
             mWindowManager.setEventDispatching(true);
             mSleeping = false;
+            mMainStack.awakeFromSleepingLocked();
             mMainStack.resumeTopActivityLocked(null);
         }
     }
@@ -7520,6 +7539,11 @@
             pw.println("  Activities waiting to stop:");
             dumpHistoryList(pw, mMainStack.mStoppingActivities, "  ", "Stop", false);
         }
+        if (mMainStack.mGoingToSleepActivities.size() > 0) {
+            pw.println(" ");
+            pw.println("  Activities waiting to sleep:");
+            dumpHistoryList(pw, mMainStack.mGoingToSleepActivities, "  ", "Sleep", false);
+        }
         if (mMainStack.mFinishingActivities.size() > 0) {
             pw.println(" ");
             pw.println("  Activities waiting to finish:");
@@ -7531,6 +7555,7 @@
         pw.println("  mResumedActivity: " + mMainStack.mResumedActivity);
         pw.println("  mFocusedActivity: " + mFocusedActivity);
         pw.println("  mLastPausedActivity: " + mMainStack.mLastPausedActivity);
+        pw.println("  mSleepTimeout: " + mMainStack.mSleepTimeout);
 
         if (dumpAll && mRecentTasks.size() > 0) {
             pw.println(" ");
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index e29da1c..3dc3965 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -102,6 +102,7 @@
     boolean inHistory;      // are we in the history stack?
     int launchMode;         // the launch mode activity attribute.
     boolean visible;        // does this activity's window need to be shown?
+    boolean sleeping;       // have we told the activity to sleep?
     boolean waitingVisible; // true if waiting for a new act to become vis
     boolean nowVisible;     // is this activity's window visible?
     boolean thumbnailNeeded;// has someone requested a thumbnail?
@@ -168,9 +169,10 @@
                 pw.print(" launchMode="); pw.println(launchMode);
         pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
                 pw.print(" visible="); pw.print(visible);
-                pw.print(" frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
-                pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
+                pw.print(" sleeping="); pw.print(sleeping);
                 pw.print(" idle="); pw.println(idle);
+        pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
+                pw.print(" thumbnailNeeded="); pw.println(thumbnailNeeded);
         if (launchTime != 0 || startTime != 0) {
             pw.print(prefix); pw.print("launchTime=");
                     TimeUtils.formatDuration(launchTime, pw); pw.print(" startTime=");
@@ -597,7 +599,25 @@
     public boolean isInterestingToUserLocked() {
         return visible || nowVisible || state == ActivityState.PAUSING || 
                 state == ActivityState.RESUMED;
-     }
+    }
+
+    public void setSleeping(boolean _sleeping) {
+        if (sleeping == _sleeping) {
+            return;
+        }
+        if (app != null && app.thread != null) {
+            try {
+                app.thread.scheduleSleeping(this, _sleeping);
+                if (sleeping && !stack.mGoingToSleepActivities.contains(this)) {
+                    stack.mGoingToSleepActivities.add(this);
+                }
+                sleeping = _sleeping;
+            } catch (RemoteException e) {
+                Slog.w(ActivityStack.TAG, "Exception thrown when sleeping: "
+                        + intent.getComponent(), e);
+            }
+        }
+    }
     
     public String toString() {
         if (stringName != null) {
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index dd6ddd6..3761928 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -92,6 +92,9 @@
     // next activity.
     static final int PAUSE_TIMEOUT = 500;
 
+    // How long we can hold the sleep wake lock before giving up.
+    static final int SLEEP_TIMEOUT = 5*1000;
+
     // How long we can hold the launch wake lock before giving up.
     static final int LAUNCH_TIMEOUT = 10*1000;
 
@@ -158,6 +161,12 @@
             = new ArrayList<ActivityRecord>();
 
     /**
+     * List of activities that are in the process of going to sleep.
+     */
+    final ArrayList<ActivityRecord> mGoingToSleepActivities
+            = new ArrayList<ActivityRecord>();
+
+    /**
      * Animations that for the current transition have requested not to
      * be considered for the transition animation.
      */
@@ -238,9 +247,15 @@
     
     long mInitialStartTime = 0;
     
+    /**
+     * Set when we have taken too long waiting to go to sleep.
+     */
+    boolean mSleepTimeout = false;
+
     int mThumbnailWidth = -1;
     int mThumbnailHeight = -1;
 
+    static final int SLEEP_TIMEOUT_MSG = 8;
     static final int PAUSE_TIMEOUT_MSG = 9;
     static final int IDLE_TIMEOUT_MSG = 10;
     static final int IDLE_NOW_MSG = 11;
@@ -255,6 +270,13 @@
 
         public void handleMessage(Message msg) {
             switch (msg.what) {
+                case SLEEP_TIMEOUT_MSG: {
+                    if (mService.isSleeping()) {
+                        Slog.w(TAG, "Sleep timeout!  Sleeping now.");
+                        mSleepTimeout = true;
+                        checkReadyForSleepLocked();
+                    }
+                } break;
                 case PAUSE_TIMEOUT_MSG: {
                     IBinder token = (IBinder)msg.obj;
                     // We don't at this point know if the activity is fullscreen,
@@ -514,6 +536,7 @@
                 mService.mHomeProcess = app;
             }
             mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
+            r.sleeping = false;
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
                     System.identityHashCode(r),
                     r.info, r.icicle, results, newIntents, !andResume,
@@ -575,7 +598,7 @@
                 mService.addRecentTaskLocked(r.task);
             }
             completeResumeLocked(r);
-            pauseIfSleepingLocked();                
+            checkReadyForSleepLocked();
         } else {
             // This activity is not starting in the resumed state... which
             // should look like we asked it to pause+stop (but remain visible),
@@ -631,8 +654,8 @@
                 "activity", r.intent.getComponent(), false);
     }
     
-    void pauseIfSleepingLocked() {
-        if (mService.mSleeping || mService.mShuttingDown) {
+    void stopIfSleepingLocked() {
+        if (mService.isSleeping()) {
             if (!mGoingToSleep.isHeld()) {
                 mGoingToSleep.acquire();
                 if (mLaunchingActivity.isHeld()) {
@@ -640,16 +663,90 @@
                     mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
                 }
             }
+            mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
+            Message msg = mHandler.obtainMessage(SLEEP_TIMEOUT_MSG);
+            mHandler.sendMessageDelayed(msg, SLEEP_TIMEOUT);
+            checkReadyForSleepLocked();
+        }
+    }
 
-            // If we are not currently pausing an activity, get the current
-            // one to pause.  If we are pausing one, we will just let that stuff
-            // run and release the wake lock when all done.
-            if (mPausingActivity == null) {
-                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause...");
+    void awakeFromSleepingLocked() {
+        mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
+        mSleepTimeout = false;
+        if (mGoingToSleep.isHeld()) {
+            mGoingToSleep.release();
+        }
+        // Ensure activities are no longer sleeping.
+        for (int i=mHistory.size()-1; i>=0; i--) {
+            ActivityRecord r = (ActivityRecord)mHistory.get(i);
+            r.setSleeping(false);
+        }
+        mGoingToSleepActivities.clear();
+    }
+
+    void activitySleptLocked(ActivityRecord r) {
+        mGoingToSleepActivities.remove(r);
+        checkReadyForSleepLocked();
+    }
+
+    void checkReadyForSleepLocked() {
+        if (!mService.isSleeping()) {
+            // Do not care.
+            return;
+        }
+
+        if (!mSleepTimeout) {
+            if (mResumedActivity != null) {
+                // Still have something resumed; can't sleep until it is paused.
+                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
                 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
                 startPausingLocked(false, true);
+                return;
+            }
+            if (mPausingActivity != null) {
+                // Still waiting for something to pause; can't sleep yet.
+                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
+                return;
+            }
+
+            if (mStoppingActivities.size() > 0) {
+                // Still need to tell some activities to stop; can't sleep yet.
+                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
+                        + mStoppingActivities.size() + " activities");
+                Message msg = Message.obtain();
+                msg.what = IDLE_NOW_MSG;
+                mHandler.sendMessage(msg);
+                return;
+            }
+
+            ensureActivitiesVisibleLocked(null, 0);
+
+            // Make sure any stopped but visible activities are now sleeping.
+            // This ensures that the activity's onStop() is called.
+            for (int i=mHistory.size()-1; i>=0; i--) {
+                ActivityRecord r = (ActivityRecord)mHistory.get(i);
+                if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
+                    r.setSleeping(true);
+                }
+            }
+
+            if (mGoingToSleepActivities.size() > 0) {
+                // Still need to tell some activities to sleep; can't sleep yet.
+                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
+                        + mGoingToSleepActivities.size() + " activities");
+                return;
             }
         }
+
+        mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
+
+        if (mGoingToSleep.isHeld()) {
+            mGoingToSleep.release();
+        }
+        if (mService.mShuttingDown) {
+            mService.notifyAll();
+        }
+
     }
     
     public final Bitmap screenshotActivities(ActivityRecord who) {
@@ -813,6 +910,8 @@
                         Message msg = Message.obtain();
                         msg.what = IDLE_NOW_MSG;
                         mHandler.sendMessage(msg);
+                    } else {
+                        checkReadyForSleepLocked();
                     }
                 }
             } else {
@@ -822,15 +921,10 @@
             mPausingActivity = null;
         }
 
-        if (!mService.mSleeping && !mService.mShuttingDown) {
+        if (!mService.isSleeping()) {
             resumeTopActivityLocked(prev);
         } else {
-            if (mGoingToSleep.isHeld()) {
-                mGoingToSleep.release();
-            }
-            if (mService.mShuttingDown) {
-                mService.notifyAll();
-            }
+            checkReadyForSleepLocked();
         }
         
         if (prev != null) {
@@ -985,6 +1079,7 @@
                             TAG, "Making visible and scheduling visibility: " + r);
                     try {
                         mService.mWindowManager.setAppVisibility(r, true);
+                        r.sleeping = false;
                         r.app.thread.scheduleWindowVisibility(r, true);
                         r.stopFreezingScreenLocked(false);
                     } catch (Exception e) {
@@ -1114,6 +1209,8 @@
         // The activity may be waiting for stop, but that is no longer
         // appropriate for it.
         mStoppingActivities.remove(next);
+        mGoingToSleepActivities.remove(next);
+        next.sleeping = false;
         mWaitingVisibleActivities.remove(next);
 
         if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
@@ -1315,10 +1412,11 @@
                         System.identityHashCode(next),
                         next.task.taskId, next.shortComponentName);
                 
+                next.sleeping = false;
                 next.app.thread.scheduleResumeActivity(next,
                         mService.isNextTransitionForward());
                 
-                pauseIfSleepingLocked();
+                checkReadyForSleepLocked();
 
             } catch (Exception e) {
                 // Whoops, need to restart this activity!
@@ -2831,6 +2929,9 @@
                     mService.mWindowManager.setAppVisibility(r, false);
                 }
                 r.app.thread.scheduleStopActivity(r, r.visible, r.configChangeFlags);
+                if (mService.isSleeping()) {
+                    r.setSleeping(true);
+                }
             } catch (Exception e) {
                 // Maybe just ignore exceptions here...  if the process
                 // has crashed, our death notification will clean things
@@ -2874,7 +2975,7 @@
                     mService.mWindowManager.setAppVisibility(s, false);
                 }
             }
-            if (!s.waitingVisible && remove) {
+            if ((!s.waitingVisible || mService.isSleeping()) && remove) {
                 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
                 if (stops == null) {
                     stops = new ArrayList<ActivityRecord>();
@@ -3198,6 +3299,8 @@
                     Message msg = Message.obtain();
                     msg.what = IDLE_NOW_MSG;
                     mHandler.sendMessage(msg);
+                } else {
+                    checkReadyForSleepLocked();
                 }
             }
             r.state = ActivityState.STOPPING;
@@ -3207,6 +3310,7 @@
 
         // make sure the record is cleaned out of other places.
         mStoppingActivities.remove(r);
+        mGoingToSleepActivities.remove(r);
         mWaitingVisibleActivities.remove(r);
         if (mResumedActivity == r) {
             mResumedActivity = null;
@@ -3434,6 +3538,7 @@
     void removeHistoryRecordsForAppLocked(ProcessRecord app) {
         removeHistoryRecordsForAppLocked(mLRUActivities, app);
         removeHistoryRecordsForAppLocked(mStoppingActivities, app);
+        removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app);
         removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app);
         removeHistoryRecordsForAppLocked(mFinishingActivities, app);
     }