Merge "Changed some parts of the code to prepare it for script support that will come in later commit."
diff --git a/core/java/android/provider/Mtp.java b/core/java/android/provider/Mtp.java
index 15f8666..bc764ac 100644
--- a/core/java/android/provider/Mtp.java
+++ b/core/java/android/provider/Mtp.java
@@ -308,6 +308,13 @@
         public static final int FORMAT_ABSTRACT_CONTACT = 0xBB81;
         public static final int FORMAT_VCARD_2 = 0xBB82;
 
+        // Object properties we support
+        public static final int PROPERTY_STORAGE_ID = 0xDC01;
+        public static final int PROPERTY_OBJECT_FORMAT = 0xDC02;
+        public static final int PROPERTY_OBJECT_SIZE = 0xDC04;
+        public static final int PROPERTY_OBJECT_FILE_NAME = 0xDC07;
+        public static final int PROPERTY_PARENT_OBJECT = 0xDC0B;
+
         /**
          * Object is not protected. It may be modified and deleted, and its properties
          * may be modified.
diff --git a/core/java/android/webkit/DeviceOrientationManager.java b/core/java/android/webkit/DeviceOrientationManager.java
new file mode 100644
index 0000000..778b043
--- /dev/null
+++ b/core/java/android/webkit/DeviceOrientationManager.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.util.Log;
+
+/**
+ * This class is simply a container for the methods used to configure WebKit's
+ * mock DeviceOrientationClient for use in LayoutTests.
+ *
+ * This could be part of WebViewCore, but have moved it to its own class to
+ * avoid bloat there.
+ * @hide
+ */
+public final class DeviceOrientationManager {
+    /**
+     * Sets whether the Page for the specified WebViewCore should use a mock DeviceOrientation
+     * client.
+     */
+    public static void useMock(WebViewCore webViewCore) {
+        assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
+        nativeUseMock(webViewCore);
+    }
+
+    /**
+     * Set the position for the mock DeviceOrientation service for the supplied WebViewCore.
+     */
+    public static void setMockOrientation(WebViewCore webViewCore, boolean canProvideAlpha,
+            double alpha, boolean canProvideBeta, double beta, boolean canProvideGamma,
+            double gamma) {
+        assert WebViewCore.THREAD_NAME.equals(Thread.currentThread().getName());
+        nativeSetMockOrientation(webViewCore, canProvideAlpha, alpha, canProvideBeta, beta,
+                canProvideGamma, gamma);
+    }
+
+    // Native functions
+    private static native void nativeUseMock(WebViewCore webViewCore);
+    private static native void nativeSetMockOrientation(WebViewCore webViewCore,
+            boolean canProvideAlpha, double alpha, boolean canProvideBeta, double beta,
+            boolean canProvideGamma, double gamma);
+}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index d1b0902..44f036b 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -66,6 +66,7 @@
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
+import android.webkit.DeviceOrientationManager;
 import android.webkit.WebTextView.AutoCompleteAdapter;
 import android.webkit.WebViewCore.EventHub;
 import android.webkit.WebViewCore.TouchEventData;
@@ -3747,6 +3748,26 @@
     }
 
     /**
+     * Called by DRT on UI thread, need to proxy to WebCore thread.
+     *
+     * @hide debug only
+     */
+    public void useMockDeviceOrientation() {
+        mWebViewCore.sendMessage(EventHub.USE_MOCK_DEVICE_ORIENTATION);
+    }
+
+    /**
+     * Called by DRT on WebCore thread.
+     *
+     * @hide debug only
+     */
+    public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
+            boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
+        DeviceOrientationManager.setMockOrientation(mWebViewCore, canProvideAlpha, alpha,
+                canProvideBeta, beta, canProvideGamma, gamma);
+    }
+
+    /**
      * Dump the V8 counters to standard output.
      * Note that you need a build with V8 and WEBCORE_INSTRUMENTATION set to
      * true. Otherwise, this will do nothing.
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index 3c28c94..9ec97cd 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -33,6 +33,7 @@
 import android.view.KeyEvent;
 import android.view.SurfaceView;
 import android.view.View;
+import android.webkit.DeviceOrientationManager;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -878,6 +879,8 @@
         // accessibility support
         static final int MODIFY_SELECTION = 190;
 
+        static final int USE_MOCK_DEVICE_ORIENTATION = 191;
+
         // private message ids
         private static final int DESTROY =     200;
 
@@ -1409,6 +1412,10 @@
                                     WebView.SET_TOUCH_HIGHLIGHT_RECTS, null)
                                     .sendToTarget();
                             break;
+
+                        case USE_MOCK_DEVICE_ORIENTATION:
+                            useMockDeviceOrientation();
+                            break;
                     }
                 }
             };
@@ -2481,6 +2488,10 @@
                 hMode, vMode).sendToTarget();
     }
 
+    private void useMockDeviceOrientation() {
+        DeviceOrientationManager.useMock(this);
+    }
+
     private native void nativePause();
     private native void nativeResume();
     private native void nativeFreeMemory();
diff --git a/media/java/android/media/MtpDatabase.java b/media/java/android/media/MtpDatabase.java
index 37f9f2c..88cce46 100644
--- a/media/java/android/media/MtpDatabase.java
+++ b/media/java/android/media/MtpDatabase.java
@@ -220,6 +220,50 @@
         return -1;
     }
 
+    private int[] getSupportedPlaybackFormats() {
+        return new int[] {
+            Mtp.Object.FORMAT_ASSOCIATION,
+            Mtp.Object.FORMAT_MP3,
+            Mtp.Object.FORMAT_MPEG,
+            Mtp.Object.FORMAT_EXIF_JPEG,
+            Mtp.Object.FORMAT_TIFF_EP,
+            Mtp.Object.FORMAT_GIF,
+            Mtp.Object.FORMAT_JFIF,
+            Mtp.Object.FORMAT_PNG,
+            Mtp.Object.FORMAT_TIFF,
+            Mtp.Object.FORMAT_WMA,
+            Mtp.Object.FORMAT_OGG,
+            Mtp.Object.FORMAT_AAC,
+            Mtp.Object.FORMAT_MP4_CONTAINER,
+            Mtp.Object.FORMAT_MP2,
+            Mtp.Object.FORMAT_3GP_CONTAINER,
+            Mtp.Object.FORMAT_ABSTRACT_AV_PLAYLIST,
+            Mtp.Object.FORMAT_WPL_PLAYLIST,
+            Mtp.Object.FORMAT_M3U_PLAYLIST,
+            Mtp.Object.FORMAT_PLS_PLAYLIST,
+        };
+    }
+
+    private int[] getSupportedCaptureFormats() {
+        // no capture formats yet
+        return null;
+    }
+
+    private int[] getSupportedObjectProperties(int handle) {
+        return new int[] {
+            Mtp.Object.PROPERTY_STORAGE_ID,
+            Mtp.Object.PROPERTY_OBJECT_FORMAT,
+            Mtp.Object.PROPERTY_OBJECT_SIZE,
+            Mtp.Object.PROPERTY_OBJECT_FILE_NAME,
+            Mtp.Object.PROPERTY_PARENT_OBJECT,
+        };
+    }
+
+    private int[] getSupportedDeviceProperties() {
+        // no device properties yet
+        return null;
+    }
+
     private int getObjectProperty(int handle, int property,
                             long[] outIntValue, char[] outStringValue) {
         Log.d(TAG, "getObjectProperty: " + property);
diff --git a/media/jni/android_media_MtpDatabase.cpp b/media/jni/android_media_MtpDatabase.cpp
index bfdc872..abbea30 100644
--- a/media/jni/android_media_MtpDatabase.cpp
+++ b/media/jni/android_media_MtpDatabase.cpp
@@ -40,6 +40,10 @@
 static jmethodID method_endSendObject;
 static jmethodID method_getObjectList;
 static jmethodID method_getNumObjects;
+static jmethodID method_getSupportedPlaybackFormats;
+static jmethodID method_getSupportedCaptureFormats;
+static jmethodID method_getSupportedObjectProperties;
+static jmethodID method_getSupportedDeviceProperties;
 static jmethodID method_getObjectProperty;
 static jmethodID method_getObjectInfo;
 static jmethodID method_getObjectFilePath;
@@ -87,6 +91,13 @@
                                             MtpObjectFormat format,
                                             MtpObjectHandle parent);
 
+    // callee should delete[] the results from these
+    // results can be NULL
+    virtual MtpObjectFormatList*    getSupportedPlaybackFormats();
+    virtual MtpObjectFormatList*    getSupportedCaptureFormats();
+    virtual MtpObjectPropertyList*  getSupportedObjectProperties(MtpObjectFormat format);
+    virtual MtpDevicePropertyList*  getSupportedDeviceProperties();
+
     virtual MtpResponseCode         getObjectProperty(MtpObjectHandle handle,
                                             MtpObjectProperty property,
                                             MtpDataPacket& packet);
@@ -190,6 +201,66 @@
                 (jint)storageID, (jint)format, (jint)parent);
 }
 
+MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
+            method_getSupportedPlaybackFormats);
+    if (!array)
+        return NULL;
+    MtpObjectFormatList* list = new MtpObjectFormatList();
+    jint* formats = env->GetIntArrayElements(array, 0);
+    jsize length = env->GetArrayLength(array);
+    for (int i = 0; i < length; i++)
+        list->push(formats[i]);
+   env->ReleaseIntArrayElements(array, formats, 0);
+   return list;
+}
+
+MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
+            method_getSupportedCaptureFormats);
+    if (!array)
+        return NULL;
+    MtpObjectFormatList* list = new MtpObjectFormatList();
+    jint* formats = env->GetIntArrayElements(array, 0);
+    jsize length = env->GetArrayLength(array);
+    for (int i = 0; i < length; i++)
+        list->push(formats[i]);
+   env->ReleaseIntArrayElements(array, formats, 0);
+   return list;
+}
+
+MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
+            method_getSupportedObjectProperties, (jint)format);
+    if (!array)
+        return NULL;
+    MtpObjectPropertyList* list = new MtpObjectPropertyList();
+    jint* properties = env->GetIntArrayElements(array, 0);
+    jsize length = env->GetArrayLength(array);
+    for (int i = 0; i < length; i++)
+        list->push(properties[i]);
+   env->ReleaseIntArrayElements(array, properties, 0);
+   return list;
+}
+
+MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
+    JNIEnv* env = AndroidRuntime::getJNIEnv();
+    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
+            method_getSupportedDeviceProperties);
+    if (!array)
+        return NULL;
+    MtpDevicePropertyList* list = new MtpDevicePropertyList();
+    jint* properties = env->GetIntArrayElements(array, 0);
+    jsize length = env->GetArrayLength(array);
+    for (int i = 0; i < length; i++)
+        list->push(properties[i]);
+   env->ReleaseIntArrayElements(array, properties, 0);
+   return list;
+}
+
 MtpResponseCode MyMtpDatabase::getObjectProperty(MtpObjectHandle handle,
                                             MtpObjectProperty property,
                                             MtpDataPacket& packet) {
@@ -460,6 +531,26 @@
         LOGE("Can't find getNumObjects");
         return -1;
     }
+    method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
+    if (method_getSupportedPlaybackFormats == NULL) {
+        LOGE("Can't find getSupportedPlaybackFormats");
+        return -1;
+    }
+    method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
+    if (method_getSupportedCaptureFormats == NULL) {
+        LOGE("Can't find getSupportedCaptureFormats");
+        return -1;
+    }
+    method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
+    if (method_getSupportedObjectProperties == NULL) {
+        LOGE("Can't find getSupportedObjectProperties");
+        return -1;
+    }
+    method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
+    if (method_getSupportedDeviceProperties == NULL) {
+        LOGE("Can't find getSupportedDeviceProperties");
+        return -1;
+    }
     method_getObjectProperty = env->GetMethodID(clazz, "getObjectProperty", "(II[J[C)I");
     if (method_getObjectProperty == NULL) {
         LOGE("Can't find getObjectProperty");
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index c159e20..9bfd00f 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -266,6 +266,13 @@
         putUInt16(*values++);
 }
 
+void MtpDataPacket::putAUInt16(const UInt16List* values) {
+    size_t count = (values ? values->size() : 0);
+    putUInt32(count);
+    for (size_t i = 0; i < count; i++)
+        putUInt16((*values)[i]);
+}
+
 void MtpDataPacket::putAInt32(const int32_t* values, int count) {
     putUInt32(count);
     for (int i = 0; i < count; i++)
diff --git a/media/mtp/MtpDataPacket.h b/media/mtp/MtpDataPacket.h
index e8314d7..b458286 100644
--- a/media/mtp/MtpDataPacket.h
+++ b/media/mtp/MtpDataPacket.h
@@ -74,6 +74,7 @@
     void                putAUInt8(const uint8_t* values, int count);
     void                putAInt16(const int16_t* values, int count);
     void                putAUInt16(const uint16_t* values, int count);
+    void                putAUInt16(const UInt16List* values);
     void                putAInt32(const int32_t* values, int count);
     void                putAUInt32(const uint32_t* values, int count);
     void                putAUInt32(const UInt32List* list);
diff --git a/media/mtp/MtpDatabase.h b/media/mtp/MtpDatabase.h
index 02bb0d9..17823df 100644
--- a/media/mtp/MtpDatabase.h
+++ b/media/mtp/MtpDatabase.h
@@ -51,6 +51,13 @@
                                             MtpObjectFormat format,
                                             MtpObjectHandle parent) = 0;
 
+    // callee should delete[] the results from these
+    // results can be NULL
+    virtual MtpObjectFormatList*    getSupportedPlaybackFormats() = 0;
+    virtual MtpObjectFormatList*    getSupportedCaptureFormats() = 0;
+    virtual MtpObjectPropertyList*  getSupportedObjectProperties(MtpObjectFormat format) = 0;
+    virtual MtpDevicePropertyList*  getSupportedDeviceProperties() = 0;
+
     virtual MtpResponseCode         getObjectProperty(MtpObjectHandle handle,
                                             MtpObjectProperty property,
                                             MtpDataPacket& packet) = 0;
diff --git a/media/mtp/MtpDebug.h b/media/mtp/MtpDebug.h
index 3935d33..5b53e31 100644
--- a/media/mtp/MtpDebug.h
+++ b/media/mtp/MtpDebug.h
@@ -17,7 +17,7 @@
 #ifndef _MTP_DEBUG_H
 #define _MTP_DEBUG_H
 
-#define LOG_NDEBUG 0
+// #define LOG_NDEBUG 0
 #include <utils/Log.h>
 
 #include "MtpTypes.h"
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 082d924..6d2eec3 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -78,46 +78,6 @@
     MTP_EVENT_OBJECT_REMOVED,
 };
 
-static const MtpObjectProperty kSupportedObjectProperties[] = {
-    MTP_PROPERTY_STORAGE_ID,
-    MTP_PROPERTY_OBJECT_FORMAT,
-    MTP_PROPERTY_OBJECT_SIZE,
-    MTP_PROPERTY_OBJECT_FILE_NAME,
-    MTP_PROPERTY_PARENT_OBJECT,
-};
-
-static const MtpObjectFormat kSupportedPlaybackFormats[] = {
-    // MTP_FORMAT_UNDEFINED,
-    MTP_FORMAT_ASSOCIATION,
-    // MTP_FORMAT_TEXT,
-    // MTP_FORMAT_HTML,
-    MTP_FORMAT_MP3,
-    //MTP_FORMAT_AVI,
-    MTP_FORMAT_MPEG,
-    // MTP_FORMAT_ASF,
-    MTP_FORMAT_EXIF_JPEG,
-    MTP_FORMAT_TIFF_EP,
-    // MTP_FORMAT_BMP,
-    MTP_FORMAT_GIF,
-    MTP_FORMAT_JFIF,
-    MTP_FORMAT_PNG,
-    MTP_FORMAT_TIFF,
-    MTP_FORMAT_WMA,
-    MTP_FORMAT_OGG,
-    MTP_FORMAT_AAC,
-    // MTP_FORMAT_FLAC,
-    // MTP_FORMAT_WMV,
-    MTP_FORMAT_MP4_CONTAINER,
-    MTP_FORMAT_MP2,
-    MTP_FORMAT_3GP_CONTAINER,
-    // MTP_FORMAT_ABSTRACT_AUDIO_ALBUM,
-    MTP_FORMAT_ABSTRACT_AV_PLAYLIST,
-    MTP_FORMAT_WPL_PLAYLIST,
-    MTP_FORMAT_M3U_PLAYLIST,
-    // MTP_FORMAT_MPL_PLAYLIST,
-    MTP_FORMAT_PLS_PLAYLIST,
-};
-
 MtpServer::MtpServer(int fd, MtpDatabase* database,
                     int fileGroup, int filePerm, int directoryPerm)
     :   mFD(fd),
@@ -354,6 +314,10 @@
     MtpStringBuffer   string;
     char prop_value[PROPERTY_VALUE_MAX];
 
+    MtpObjectFormatList* playbackFormats = mDatabase->getSupportedPlaybackFormats();
+    MtpObjectFormatList* captureFormats = mDatabase->getSupportedCaptureFormats();
+    MtpDevicePropertyList* deviceProperties = mDatabase->getSupportedDeviceProperties();
+
     // fill in device info
     mData.putUInt16(MTP_STANDARD_VERSION);
     mData.putUInt32(6); // MTP Vendor Extension ID
@@ -365,10 +329,9 @@
             sizeof(kSupportedOperationCodes) / sizeof(uint16_t)); // Operations Supported
     mData.putAUInt16(kSupportedEventCodes,
             sizeof(kSupportedEventCodes) / sizeof(uint16_t)); // Events Supported
-    mData.putEmptyArray(); // Device Properties Supported
-    mData.putEmptyArray(); // Capture Formats
-    mData.putAUInt16(kSupportedPlaybackFormats,
-            sizeof(kSupportedPlaybackFormats) / sizeof(uint16_t)); // Playback Formats
+    mData.putAUInt16(deviceProperties); // Device Properties Supported
+    mData.putAUInt16(captureFormats); // Capture Formats
+    mData.putAUInt16(playbackFormats);  // Playback Formats
     // FIXME
     string.set("Google, Inc.");
     mData.putString(string);   // Manufacturer
@@ -383,6 +346,10 @@
     string.set(prop_value);
     mData.putString(string);   // Serial Number
 
+    delete playbackFormats;
+    delete captureFormats;
+    delete deviceProperties;
+
     return MTP_RESPONSE_OK;
 }
 
@@ -443,8 +410,9 @@
     if (!mSessionOpen)
         return MTP_RESPONSE_SESSION_NOT_OPEN;
     MtpObjectFormat format = mRequest.getParameter(1);
-    mData.putAUInt16(kSupportedObjectProperties,
-            sizeof(kSupportedObjectProperties) / sizeof(uint16_t));
+    MtpDevicePropertyList* properties = mDatabase->getSupportedObjectProperties(format);
+    mData.putAUInt16(properties);
+    delete[] properties;
     return MTP_RESPONSE_OK;
 }
 
diff --git a/media/mtp/MtpTypes.h b/media/mtp/MtpTypes.h
index 2a895a7..7e3c009 100644
--- a/media/mtp/MtpTypes.h
+++ b/media/mtp/MtpTypes.h
@@ -78,6 +78,7 @@
 typedef Vector<int32_t> Int32List;
 typedef Vector<int64_t> Int64List;
 
+typedef UInt16List MtpObjectPropertyList;
 typedef UInt16List MtpDevicePropertyList;
 typedef UInt16List MtpObjectFormatList;
 typedef UInt32List MtpObjectHandleList;
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
index b62db51..740f544 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/CallbackProxy.java
@@ -510,6 +510,14 @@
         obtainMessage(SET_GEOLOCATION_PERMISSION, allow ? 1 : 0, 0).sendToTarget();
     }
 
+    public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
+            boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
+        // Configuration is in WebKit, so stay on WebCore thread, but go via the TestShellActivity
+        // as we need access to the Webview.
+        mLayoutTestController.setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta,
+                canProvideGamma, gamma);
+    }
+
     public void overridePreference(String key, boolean value) {
         Message message = obtainMessage(OVERRIDE_PREFERENCE);
         message.getData().putString("key", key);
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index acc0ff2..9f580a3 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -73,7 +73,6 @@
 
     static final String[] ignoreTestList = {
         "editing/selection/move-left-right.html", // Causes DumpRenderTree to hang
-        "fast/dom/DeviceOrientation/basic-operation.html", // Will cause crash until mock DeviceOrientationClient is hooked up.
         "fast/js/excessive-comma-usage.html", // Tests huge initializer list, causes OOM.
         "fast/js/regexp-charclass-crash.html", // RegExp is too large, causing OOM
         "fast/regex/test1.html", // Causes DumpRenderTree to hang with V8
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
index 15288b5..9be2f1c 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/LayoutTestController.java
@@ -71,4 +71,8 @@
 
     // For XSSAuditor tests
     public void setXSSAuditorEnabled(boolean flag);
+
+    // For DeviceOrientation tests
+    public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
+            boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma);
 }
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
index 8c7254c..db076da 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/TestShellActivity.java
@@ -150,6 +150,9 @@
         if (intent != null) {
             executeIntent(intent);
         }
+
+        // This is asynchronous, but it gets processed by WebCore before it starts loading pages.
+        mWebView.useMockDeviceOrientation();
     }
 
     @Override
@@ -494,6 +497,12 @@
         mGeolocationPermission = allow;
     }
 
+    public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
+            boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
+        mWebView.setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta,
+                canProvideGamma, gamma);
+    }
+
     public void overridePreference(String key, boolean value) {
         // TODO: We should look up the correct WebView for the frame which
         // called the layoutTestController method. Currently, we just use the
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
index 8ff5e63..6db9571 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestController.java
@@ -89,4 +89,12 @@
         Log.w(LOG_TAG + "::setMockGeolocationError", "code: " + code + " message: " + message);
         MockGeolocation.getInstance().setError(code, message);
     }
-}
\ No newline at end of file
+
+    public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
+            boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
+        // Configuration is in WebKit, so stay on WebCore thread, but go via LayoutTestsExecutor
+        // as we need access to the Webview.
+        mLayoutTestsExecutor.setMockDeviceOrientation(
+                canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma);
+    }
+}
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
index 047348d..8cc4921 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/LayoutTestsExecutor.java
@@ -308,6 +308,9 @@
         webViewSettings.setDomStorageEnabled(true);
         webViewSettings.setWorkersEnabled(false);
         webViewSettings.setXSSAuditorEnabled(false);
+
+        // This is asynchronous, but it gets processed by WebCore before it starts loading pages.
+        mCurrentWebView.useMockDeviceOrientation();
     }
 
     private void startTests() {
@@ -569,4 +572,10 @@
         msg.arg1 = allow ? 1 : 0;
         msg.sendToTarget();
     }
-}
\ No newline at end of file
+
+    public void setMockDeviceOrientation(boolean canProvideAlpha, double alpha,
+            boolean canProvideBeta, double beta, boolean canProvideGamma, double gamma) {
+        mCurrentWebView.setMockDeviceOrientation(canProvideAlpha, alpha, canProvideBeta, beta,
+                canProvideGamma, gamma);
+    }
+}
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
index 1b73f97..d9e7ec0 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
@@ -167,6 +167,7 @@
 
     /** TODO: Make it a setting */
     private static final String HTML_SUMMARY_RELATIVE_PATH = "summary.html";
+    private static final String TXT_SUMMARY_RELATIVE_PATH = "summary.txt";
 
     private int mCrashedTestsCount = 0;
     private List<AbstractResult> mFailedNotIgnoredTests = new ArrayList<AbstractResult>();
@@ -176,6 +177,8 @@
     private FileFilter mFileFilter;
     private String mResultsRootDirPath;
 
+    private String mTitleString;
+
     public Summarizer(FileFilter fileFilter, String resultsRootDirPath) {
         mFileFilter = fileFilter;
         mResultsRootDirPath = resultsRootDirPath;
@@ -198,6 +201,27 @@
     }
 
     public void summarize() {
+        createHtmlSummary();
+        createTxtSummary();
+    }
+
+    private void createTxtSummary() {
+        StringBuilder txt = new StringBuilder();
+
+        txt.append(getTitleString() + "\n");
+        if (mCrashedTestsCount > 0) {
+            txt.append("CRASHED (total among all tests): " + mCrashedTestsCount + "\n");
+            txt.append("-------------");
+        }
+        txt.append("FAILED:  " + mFailedNotIgnoredTests.size() + "\n");
+        txt.append("IGNORED: " + mIgnoredTests.size() + "\n");
+        txt.append("PASSED:  " + mPassedNotIgnoredTests.size() + "\n");
+
+        FsUtils.writeDataToStorage(new File(mResultsRootDirPath, TXT_SUMMARY_RELATIVE_PATH),
+                txt.toString().getBytes(), false);
+    }
+
+    private void createHtmlSummary() {
         StringBuilder html = new StringBuilder();
 
         html.append("<html><head>");
@@ -219,13 +243,20 @@
                 html.toString().getBytes(), false);
     }
 
+    private String getTitleString() {
+        if (mTitleString == null) {
+            int total = mFailedNotIgnoredTests.size() +
+                    mPassedNotIgnoredTests.size() +
+                    mIgnoredTests.size();
+            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
+            mTitleString = " - total of " + total + " tests - " + dateFormat.format(new Date());
+        }
+
+        return mTitleString;
+    }
+
     private void createTopSummaryTable(StringBuilder html) {
-        int total = mFailedNotIgnoredTests.size() +
-                mPassedNotIgnoredTests.size() +
-                mIgnoredTests.size();
-        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
-        html.append("<h1> - total of " + total + " tests - ");
-        html.append(dateFormat.format(new Date()) + "</h1>");
+        html.append("<h1>" + getTitleString() + "</h1>");
 
         html.append("<table class=\"summary\">");
         createSummaryTableRow(html, "CRASHED", mCrashedTestsCount);