1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)package org.chromium.android_webview; 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochimport android.graphics.Picture; 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.Handler; 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.Looper; 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import android.os.Message; 113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)import android.os.SystemClock; 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciimport org.chromium.base.VisibleForTesting; 14a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochimport java.util.concurrent.Callable; 16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/** 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * This class is responsible for calling certain client callbacks on the UI thread. 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Most callbacks do no go through here, but get forwarded to AwContentsClient directly. The 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * messages processed here may originate from the IO or UI thread. 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch@VisibleForTesting 24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochpublic class AwContentsClientCallbackHelper { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(boliu): Consider removing DownloadInfo and LoginRequestInfo by using native 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // MessageLoop to post directly to AwContents. 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private static class DownloadInfo { 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String mUrl; 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String mUserAgent; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String mContentDisposition; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String mMimeType; 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final long mContentLength; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadInfo(String url, 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) String userAgent, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) String contentDisposition, 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) String mimeType, 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) long contentLength) { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mUrl = url; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mUserAgent = userAgent; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentDisposition = contentDisposition; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mMimeType = mimeType; 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentLength = contentLength; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private static class LoginRequestInfo { 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String mRealm; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String mAccount; 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String mArgs; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoginRequestInfo(String realm, String account, String args) { 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) mRealm = realm; 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) mAccount = account; 57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) mArgs = args; 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private static class OnReceivedErrorInfo { 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final int mErrorCode; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String mDescription; 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String mFailingUrl; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnReceivedErrorInfo(int errorCode, String description, String failingUrl) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mErrorCode = errorCode; 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mDescription = description; 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mFailingUrl = failingUrl; 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private static final int MSG_ON_LOAD_RESOURCE = 1; 74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private static final int MSG_ON_PAGE_STARTED = 2; 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private static final int MSG_ON_DOWNLOAD_START = 3; 76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private static final int MSG_ON_RECEIVED_LOGIN_REQUEST = 4; 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private static final int MSG_ON_RECEIVED_ERROR = 5; 78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private static final int MSG_ON_NEW_PICTURE = 6; 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private static final int MSG_ON_SCALE_CHANGED_SCALED = 7; 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Minimum period allowed between consecutive onNewPicture calls, to rate-limit the callbacks. 823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private static final long ON_NEW_PICTURE_MIN_PERIOD_MILLIS = 500; 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Timestamp of the most recent onNewPicture callback. 843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private long mLastPictureTime = 0; 853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // True when a onNewPicture callback is currenly in flight. 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) private boolean mHasPendingOnNewPicture = false; 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private final AwContentsClient mContentsClient; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) private final Handler mHandler; 911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) private class MyHandler extends Handler { 931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) private MyHandler(Looper looper) { 941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) super(looper); 951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) @Override 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void handleMessage(Message msg) { 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch(msg.what) { 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case MSG_ON_LOAD_RESOURCE: { 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String url = (String) msg.obj; 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentsClient.onLoadResource(url); 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case MSG_ON_PAGE_STARTED: { 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) final String url = (String) msg.obj; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentsClient.onPageStarted(url); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case MSG_ON_DOWNLOAD_START: { 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadInfo info = (DownloadInfo) msg.obj; 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentsClient.onDownloadStart(info.mUrl, info.mUserAgent, 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info.mContentDisposition, info.mMimeType, info.mContentLength); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case MSG_ON_RECEIVED_LOGIN_REQUEST: { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoginRequestInfo info = (LoginRequestInfo) msg.obj; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentsClient.onReceivedLoginRequest(info.mRealm, info.mAccount, info.mArgs); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case MSG_ON_RECEIVED_ERROR: { 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnReceivedErrorInfo info = (OnReceivedErrorInfo) msg.obj; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentsClient.onReceivedError(info.mErrorCode, info.mDescription, 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info.mFailingUrl); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch case MSG_ON_NEW_PICTURE: { 128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch Picture picture = null; 129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch try { 130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (msg.obj != null) picture = (Picture) ((Callable<?>) msg.obj).call(); 131ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } catch (Exception e) { 132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch throw new RuntimeException("Error getting picture", e); 133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch mContentsClient.onNewPicture(picture); 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) mLastPictureTime = SystemClock.uptimeMillis(); 1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) mHasPendingOnNewPicture = false; 137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch break; 138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case MSG_ON_SCALE_CHANGED_SCALED: { 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float oldScale = Float.intBitsToFloat(msg.arg1); 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) float newScale = Float.intBitsToFloat(msg.arg2); 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) mContentsClient.onScaleChangedScaled(oldScale, newScale); 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) throw new IllegalStateException( 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "AwContentsClientCallbackHelper: unhandled message " + msg.what); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) public AwContentsClientCallbackHelper(Looper looper, AwContentsClient contentsClient) { 1531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) mHandler = new MyHandler(looper); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mContentsClient = contentsClient; 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void postOnLoadResource(String url) { 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_LOAD_RESOURCE, url)); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void postOnPageStarted(String url) { 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_PAGE_STARTED, url)); 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void postOnDownloadStart(String url, String userAgent, String contentDisposition, 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) String mimeType, long contentLength) { 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DownloadInfo info = new DownloadInfo(url, userAgent, contentDisposition, mimeType, 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) contentLength); 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_DOWNLOAD_START, info)); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void postOnReceivedLoginRequest(String realm, String account, String args) { 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LoginRequestInfo info = new LoginRequestInfo(realm, account, args); 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_RECEIVED_LOGIN_REQUEST, info)); 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public void postOnReceivedError(int errorCode, String description, String failingUrl) { 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OnReceivedErrorInfo info = new OnReceivedErrorInfo(errorCode, description, failingUrl); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_RECEIVED_ERROR, info)); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 181ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 182ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch public void postOnNewPicture(Callable<Picture> pictureProvider) { 1833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (mHasPendingOnNewPicture) return; 1843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) mHasPendingOnNewPicture = true; 1853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) long pictureTime = java.lang.Math.max(mLastPictureTime + ON_NEW_PICTURE_MIN_PERIOD_MILLIS, 1863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) SystemClock.uptimeMillis()); 1873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) mHandler.sendMessageAtTime(mHandler.obtainMessage(MSG_ON_NEW_PICTURE, pictureProvider), 1883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) pictureTime); 189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 1904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public void postOnScaleChangedScaled(float oldScale, float newScale) { 1924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // The float->int->float conversion here is to avoid unnecessary allocations. The 1934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // documentation states that intBitsToFloat(floatToIntBits(a)) == a for all values of a 1944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // (except for NaNs which are collapsed to a single canonical NaN, but we don't care for 1954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // that case). 1964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) mHandler.sendMessage(mHandler.obtainMessage(MSG_ON_SCALE_CHANGED_SCALED, 1974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Float.floatToIntBits(oldScale), Float.floatToIntBits(newScale))); 1984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 200