1 /* 2 * Copyright 2010, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "DeviceMotionAndOrientationManager.h" 28 29 #include "DeviceMotionClientImpl.h" 30 #include "DeviceOrientationClientImpl.h" 31 #include "DeviceOrientationController.h" 32 #include "WebViewCore.h" 33 #include "Frame.h" 34 #include "Page.h" 35 36 #include <DeviceOrientationClientMock.h> 37 #include <JNIHelp.h> 38 39 using namespace WebCore; 40 41 namespace android { 42 43 DeviceMotionAndOrientationManager::DeviceMotionAndOrientationManager(WebViewCore* webViewCore) 44 : m_useMock(false) 45 , m_webViewCore(webViewCore) 46 { 47 } 48 49 void DeviceMotionAndOrientationManager::useMock() 50 { 51 m_useMock = true; 52 } 53 54 void DeviceMotionAndOrientationManager::setMockMotion(PassRefPtr<DeviceMotionData> motion) 55 { 56 // TODO: There is not yet a DeviceMotion mock. 57 } 58 59 void DeviceMotionAndOrientationManager::onMotionChange(PassRefPtr<DeviceMotionData> motion) 60 { 61 ASSERT(!m_useMock); 62 static_cast<DeviceMotionClientImpl*>(m_motionClient.get())->onMotionChange(motion); 63 } 64 65 void DeviceMotionAndOrientationManager::setMockOrientation(PassRefPtr<DeviceOrientation> orientation) 66 { 67 if (m_useMock) 68 static_cast<DeviceOrientationClientMock*>(orientationClient())->setOrientation(orientation); 69 } 70 71 void DeviceMotionAndOrientationManager::onOrientationChange(PassRefPtr<DeviceOrientation> orientation) 72 { 73 ASSERT(!m_useMock); 74 static_cast<DeviceOrientationClientImpl*>(m_orientationClient.get())->onOrientationChange(orientation); 75 } 76 77 void DeviceMotionAndOrientationManager::maybeSuspendClients() 78 { 79 if (!m_useMock) { 80 if (m_motionClient) 81 static_cast<DeviceMotionClientImpl*>(m_motionClient.get())->suspend(); 82 if (m_orientationClient) 83 static_cast<DeviceOrientationClientImpl*>(m_orientationClient.get())->suspend(); 84 } 85 } 86 87 void DeviceMotionAndOrientationManager::maybeResumeClients() 88 { 89 if (!m_useMock) { 90 if (m_motionClient) 91 static_cast<DeviceMotionClientImpl*>(m_motionClient.get())->resume(); 92 if (m_orientationClient) 93 static_cast<DeviceOrientationClientImpl*>(m_orientationClient.get())->resume(); 94 } 95 } 96 97 DeviceMotionClient* DeviceMotionAndOrientationManager::motionClient() 98 { 99 // TODO: There is not yet a DeviceMotion mock. 100 if (!m_motionClient) 101 m_motionClient.set(m_useMock ? 0 102 : static_cast<DeviceMotionClient*>(new DeviceMotionClientImpl(m_webViewCore))); 103 ASSERT(m_motionClient); 104 return m_motionClient.get(); 105 } 106 107 DeviceOrientationClient* DeviceMotionAndOrientationManager::orientationClient() 108 { 109 if (!m_orientationClient) 110 m_orientationClient.set(m_useMock ? new DeviceOrientationClientMock 111 : static_cast<DeviceOrientationClient*>(new DeviceOrientationClientImpl(m_webViewCore))); 112 ASSERT(m_orientationClient); 113 return m_orientationClient.get(); 114 } 115 116 // JNI for android.webkit.DeviceMotionAndOrientationManager 117 static const char* javaDeviceMotionAndOrientationManagerClass = "android/webkit/DeviceMotionAndOrientationManager"; 118 119 static WebViewCore* getWebViewCore(JNIEnv* env, jobject webViewCoreObject) 120 { 121 jclass webViewCoreClass = env->FindClass("android/webkit/WebViewCore"); 122 jfieldID nativeClassField = env->GetFieldID(webViewCoreClass, "mNativeClass", "I"); 123 env->DeleteLocalRef(webViewCoreClass); 124 return reinterpret_cast<WebViewCore*>(env->GetIntField(webViewCoreObject, nativeClassField)); 125 } 126 127 static void useMock(JNIEnv* env, jobject, jobject webViewCoreObject) 128 { 129 getWebViewCore(env, webViewCoreObject)->deviceMotionAndOrientationManager()->useMock(); 130 } 131 132 static void onMotionChange(JNIEnv* env, jobject, jobject webViewCoreObject, bool canProvideX, double x, bool canProvideY, double y, bool canProvideZ, double z, double interval) 133 { 134 // We only provide accelerationIncludingGravity. 135 RefPtr<DeviceMotionData::Acceleration> accelerationIncludingGravity = DeviceMotionData::Acceleration::create(canProvideX, x, canProvideY, y, canProvideZ, z); 136 bool canProvideInterval = canProvideX || canProvideY || canProvideZ; 137 RefPtr<DeviceMotionData> motion = DeviceMotionData::create(0, accelerationIncludingGravity.release(), 0, canProvideInterval, interval); 138 getWebViewCore(env, webViewCoreObject)->deviceMotionAndOrientationManager()->onMotionChange(motion.release()); 139 } 140 141 static void setMockOrientation(JNIEnv* env, jobject, jobject webViewCoreObject, bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma) 142 { 143 RefPtr<DeviceOrientation> orientation = DeviceOrientation::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma); 144 getWebViewCore(env, webViewCoreObject)->deviceMotionAndOrientationManager()->setMockOrientation(orientation.release()); 145 } 146 147 static void onOrientationChange(JNIEnv* env, jobject, jobject webViewCoreObject, bool canProvideAlpha, double alpha, bool canProvideBeta, double beta, bool canProvideGamma, double gamma) 148 { 149 RefPtr<DeviceOrientation> orientation = DeviceOrientation::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma); 150 getWebViewCore(env, webViewCoreObject)->deviceMotionAndOrientationManager()->onOrientationChange(orientation.release()); 151 } 152 153 static JNINativeMethod gDeviceMotionAndOrientationManagerMethods[] = { 154 { "nativeUseMock", "(Landroid/webkit/WebViewCore;)V", (void*) useMock }, 155 { "nativeOnMotionChange", "(Landroid/webkit/WebViewCore;ZDZDZDD)V", (void*) onMotionChange }, 156 { "nativeSetMockOrientation", "(Landroid/webkit/WebViewCore;ZDZDZD)V", (void*) setMockOrientation }, 157 { "nativeOnOrientationChange", "(Landroid/webkit/WebViewCore;ZDZDZD)V", (void*) onOrientationChange } 158 }; 159 160 int registerDeviceMotionAndOrientationManager(JNIEnv* env) 161 { 162 #ifndef NDEBUG 163 jclass deviceMotionAndOrientationManager = env->FindClass(javaDeviceMotionAndOrientationManagerClass); 164 LOG_ASSERT(deviceMotionAndOrientationManager, "Unable to find class"); 165 env->DeleteLocalRef(deviceMotionAndOrientationManager); 166 #endif 167 168 return jniRegisterNativeMethods(env, javaDeviceMotionAndOrientationManagerClass, gDeviceMotionAndOrientationManagerMethods, NELEM(gDeviceMotionAndOrientationManagerMethods)); 169 } 170 171 } // namespace android 172