18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* 28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Collabora Ltd. All rights reserved. 48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without 68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions 78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met: 88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright 98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer. 108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright 118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * notice, this list of conditions and the following disclaimer in the 128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * documentation and/or other materials provided with the distribution. 138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */ 268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h" 288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PluginPackage.h" 298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MIMETypeRegistry.h" 318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "npruntime_impl.h" 328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PluginDatabase.h" 338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "PluginDebug.h" 34dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/text/CString.h> 358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore { 378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool PluginPackage::fetchInfo() 398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!load()) 418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NPP_GetValueProcPtr gv = (NPP_GetValueProcPtr)m_module->resolve("NP_GetValue"); 448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project typedef char *(*NPP_GetMIMEDescriptionProcPtr)(); 458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NPP_GetMIMEDescriptionProcPtr gm = 468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project (NPP_GetMIMEDescriptionProcPtr)m_module->resolve("NP_GetMIMEDescription"); 470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (!gm || !gv) 488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project char *buf = 0; 510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch NPError err = gv(0, NPPVpluginNameString, (void*) &buf); 520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (err != NPERR_NO_ERROR) 538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_name = buf; 560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch err = gv(0, NPPVpluginDescriptionString, (void*) &buf); 570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch if (err != NPERR_NO_ERROR) 588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch 608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_description = buf; 61635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project determineModuleVersionFromDescription(); 628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 635ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen String mimeDescription = gm(); 645ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen setMIMEDescription(mimeDescription); 655ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen m_infoIsFromCache = false; 665ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen 675ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen return true; 685ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen} 695ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen 705ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsenvoid PluginPackage::setMIMEDescription(const String& mimeDescription) 715ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen{ 7228040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu m_fullMIMEDescription = mimeDescription.lower(); 735ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen 748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<String> types; 7528040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu mimeDescription.lower().split(UChar(';'), false, types); 76231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block for (unsigned i = 0; i < types.size(); ++i) { 778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<String> mime; 780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch types[i].split(UChar(':'), true, mime); 798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (mime.size() > 0) { 808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project Vector<String> exts; 818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (mime.size() > 1) 828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project mime[1].split(UChar(','), false, exts); 838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project determineQuirks(mime[0]); 848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_mimeToExtensions.add(mime[0], exts); 858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (mime.size() > 2) 868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_mimeToDescriptions.add(mime[0], mime[2]); 878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 91231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic NPError staticPluginQuirkRequiresGtkToolKit_NPN_GetValue(NPP instance, NPNVariable variable, void* value) 92231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 93231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (variable == NPNVToolkit) { 9421939df44de1705786c545cd1bf519d47250322dBen Murdoch *static_cast<uint32_t*>(value) = 2; 95231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return NPERR_NO_ERROR; 96231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 97231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 98231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return NPN_GetValue(instance, variable, value); 99231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 100231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 101e8b154fd68f9b33be40a3590e58347f353835f5cSteve Blockstatic void initializeGtk(QLibrary* module = 0) 102e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block{ 103e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Ensures missing Gtk initialization in some versions of Adobe's flash player 104e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // plugin do not cause crashes. See BR# 40567, 44324, and 44405 for details. 105e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (module) { 106e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block typedef void *(*gtk_init_ptr)(int*, char***); 107e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block gtk_init_ptr gtkInit = (gtk_init_ptr)module->resolve("gtk_init"); 108e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (gtkInit) { 109e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Prevent gtk_init() from replacing the X error handlers, since the Gtk 110e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // handlers abort when they receive an X error, thus killing the viewer. 111e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#ifdef Q_WS_X11 112e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block int (*old_error_handler)(Display*, XErrorEvent*) = XSetErrorHandler(0); 113e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block int (*old_io_error_handler)(Display*) = XSetIOErrorHandler(0); 114e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#endif 115e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block gtkInit(0, 0); 116e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#ifdef Q_WS_X11 117e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block XSetErrorHandler(old_error_handler); 118e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block XSetIOErrorHandler(old_io_error_handler); 119e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block#endif 120e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block return; 121e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block } 122e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block } 123e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 1242bde8e466a4451c7319e3a072d118917957d6554Steve Block QLibrary library(QLatin1String("libgtk-x11-2.0.so.0")); 125e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (library.load()) { 126e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block typedef void *(*gtk_init_check_ptr)(int*, char***); 127e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block gtk_init_check_ptr gtkInitCheck = (gtk_init_check_ptr)library.resolve("gtk_init_check"); 128e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // NOTE: We're using gtk_init_check() since gtk_init() calls exit() on failure. 129e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block if (gtkInitCheck) 130e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block (void) gtkInitCheck(0, 0); 131e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block } 132e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block} 133e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block 1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool PluginPackage::load() 1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{ 1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (m_isLoaded) { 1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_loadCount++; 1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_module = new QLibrary((QString)m_path); 1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_module->setLoadHints(QLibrary::ResolveAllSymbolsHint); 1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!m_module->load()) { 1440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch LOG(Plugins, "%s not loaded (%s)", m_path.utf8().data(), 145635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project m_module->errorString().toLatin1().constData()); 1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project } 1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_isLoaded = true; 1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NP_InitializeFuncPtr NP_Initialize; 1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NPError npErr; 1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project NP_Initialize = (NP_InitializeFuncPtr)m_module->resolve("NP_Initialize"); 1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_NPP_Shutdown = (NPP_ShutdownProcPtr)m_module->resolve("NP_Shutdown"); 1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (!NP_Initialize || !m_NPP_Shutdown) 1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project goto abort; 1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs)); 1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_pluginFuncs.size = sizeof(m_pluginFuncs); 1628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1635f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian initializeBrowserFuncs(); 1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (m_path.contains("npwrapper.")) { 166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // nspluginwrapper relies on the toolkit value to know if glib is available 167231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // It does so in NP_Initialize with a null instance, therefore it is done this way: 168231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block m_browserFuncs.getvalue = staticPluginQuirkRequiresGtkToolKit_NPN_GetValue; 169e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Workaround Adobe's failure to properly initialize Gtk in some versions 170e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // of their flash player plugin. 171e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block initializeGtk(); 172e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block } else if (m_path.contains("flashplayer")) { 173e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // Workaround Adobe's failure to properly initialize Gtk in some versions 174e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block // of their flash player plugin. 175e8b154fd68f9b33be40a3590e58347f353835f5cSteve Block initializeGtk(m_module); 17606ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen } 17706ea8e899e48f1f2f396b70e63fae369f2f23232Kristian Monsen 1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if defined(XP_UNIX) 1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project npErr = NP_Initialize(&m_browserFuncs, &m_pluginFuncs); 1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else 1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project npErr = NP_Initialize(&m_browserFuncs); 1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif 1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project if (npErr != NPERR_NO_ERROR) 1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project goto abort; 1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project m_loadCount++; 1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return true; 1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectabort: 1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project unloadWithoutShutdown(); 1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project return false; 1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project 19421939df44de1705786c545cd1bf519d47250322dBen Murdochuint16_t PluginPackage::NPVersion() const 195692e5dbf12901edacf14812a6fae25462920af42Steve Block{ 196692e5dbf12901edacf14812a6fae25462920af42Steve Block return NP_VERSION_MINOR; 197692e5dbf12901edacf14812a6fae25462920af42Steve Block} 1985ddde30071f639962dd557c453f2ad01f8f0fd00Kristian Monsen 1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} 200