SkiaCanvas.h revision 44dc270830758d5b0f5b099e7c0e308bdf027dfb
1c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger/* 2c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * Copyright (C) 2016 The Android Open Source Project 3c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * 4c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * Licensed under the Apache License, Version 2.0 (the "License"); 5c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * you may not use this file except in compliance with the License. 6c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * You may obtain a copy of the License at 7c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * 8c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * http://www.apache.org/licenses/LICENSE-2.0 9c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * 10c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * Unless required by applicable law or agreed to in writing, software 11c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * distributed under the License is distributed on an "AS IS" BASIS, 12c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * See the License for the specific language governing permissions and 14c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * limitations under the License. 15c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger */ 16c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger#pragma once 17c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 18c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger#include "hwui/Canvas.h" 19c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger#include "CanvasProperty.h" 20c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger#include "DeferredLayerUpdater.h" 21c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger#include "RenderNode.h" 22c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger#include "VectorDrawable.h" 23c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 24c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger#include <SkCanvas.h> 25f50806afb8982acbab4510a8d04bbcf13a2bcd9eStan Iliev#include <SkTLazy.h> 26c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 27c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenbergernamespace android { 28c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 29c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger// Holds an SkCanvas reference plus additional native data. 30c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenbergerclass SkiaCanvas : public Canvas { 31c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenbergerpublic: 32c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger explicit SkiaCanvas(const SkBitmap& bitmap); 33c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 34c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger /** 35c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * Create a new SkiaCanvas. 36c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * 37c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger * @param canvas SkCanvas to handle calls made to this SkiaCanvas. Must 386acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed * not be NULL. This constructor does not take ownership, so the caller 396acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed * must guarantee that it remains valid while the SkiaCanvas is valid. 40ea70d22dc8dc5d61f075edf6d03f86f6a68169cdMatt Sarett * @param xformToSRGB Indicates if bitmaps should be xformed to the sRGB 41ea70d22dc8dc5d61f075edf6d03f86f6a68169cdMatt Sarett * color space before drawing. This makes sense for software rendering. 42ea70d22dc8dc5d61f075edf6d03f86f6a68169cdMatt Sarett * For the picture case, it may make more sense to leave bitmaps as is, 43ea70d22dc8dc5d61f075edf6d03f86f6a68169cdMatt Sarett * and handle the xform when replaying the picture. 44c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger */ 45ea70d22dc8dc5d61f075edf6d03f86f6a68169cdMatt Sarett explicit SkiaCanvas(SkCanvas* canvas, XformToSRGB xformToSRGB); 46c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 47021693b967a2c5556dddd183eb0247df4079e1adStan Iliev virtual ~SkiaCanvas(); 48021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 49c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual SkCanvas* asSkCanvas() override { 506acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed return mCanvas; 51c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger } 52c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 53c0e7a90f1f5f98e85dbeda021fac0dff79725933Stan Iliev virtual void resetRecording(int width, int height, 54c0e7a90f1f5f98e85dbeda021fac0dff79725933Stan Iliev uirenderer::RenderNode* renderNode) override { 55c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger LOG_ALWAYS_FATAL("SkiaCanvas cannot be reset as a recording canvas"); 56c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger } 57c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 58c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual uirenderer::DisplayList* finishRecording() override { 59c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger LOG_ALWAYS_FATAL("SkiaCanvas does not produce a DisplayList"); 60c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger return nullptr; 61c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger } 62c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void insertReorderBarrier(bool enableReorder) override { 63c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger LOG_ALWAYS_FATAL("SkiaCanvas does not support reordering barriers"); 64c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger } 65c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 66c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void setBitmap(const SkBitmap& bitmap) override; 67c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 68c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual bool isOpaque() override; 69c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual int width() override; 70c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual int height() override; 71c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 72c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void setHighContrastText(bool highContrastText) override { 73c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger mHighContrastText = highContrastText; 74c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger } 75c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual bool isHighContrastText() override { return mHighContrastText; } 76c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 77c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual int getSaveCount() const override; 78c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual int save(SaveFlags::Flags flags) override; 79c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void restore() override; 80c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void restoreToCount(int saveCount) override; 81c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 82c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual int saveLayer(float left, float top, float right, float bottom, 83c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger const SkPaint* paint, SaveFlags::Flags flags) override; 84c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual int saveLayerAlpha(float left, float top, float right, float bottom, 85c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger int alpha, SaveFlags::Flags flags) override; 86c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 87c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void getMatrix(SkMatrix* outMatrix) const override; 88c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void setMatrix(const SkMatrix& matrix) override; 89c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void concat(const SkMatrix& matrix) override; 90c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void rotate(float degrees) override; 91c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void scale(float sx, float sy) override; 92c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void skew(float sx, float sy) override; 93c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void translate(float dx, float dy) override; 94c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 95c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual bool getClipBounds(SkRect* outRect) const override; 96c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual bool quickRejectRect(float left, float top, float right, float bottom) const override; 97c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual bool quickRejectPath(const SkPath& path) const override; 98c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual bool clipRect(float left, float top, float right, float bottom, 996e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed SkClipOp op) override; 1006e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed virtual bool clipPath(const SkPath* path, SkClipOp op) override; 101c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 102c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual SkDrawFilter* getDrawFilter() override; 103c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void setDrawFilter(SkDrawFilter* drawFilter) override; 104c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 10544dc270830758d5b0f5b099e7c0e308bdf027dfbMatt Sarett virtual SkCanvasState* captureCanvasState() const override; 10644dc270830758d5b0f5b099e7c0e308bdf027dfbMatt Sarett 107260ab726486317496bc12a57d599ea96dcde3284Mike Reed virtual void drawColor(int color, SkBlendMode mode) override; 108c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawPaint(const SkPaint& paint) override; 109c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 110c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawPoint(float x, float y, const SkPaint& paint) override; 111c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawPoints(const float* points, int count, const SkPaint& paint) override; 112c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawLine(float startX, float startY, float stopX, float stopY, 113c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger const SkPaint& paint) override; 114c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawLines(const float* points, int count, const SkPaint& paint) override; 115c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawRect(float left, float top, float right, float bottom, 116c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger const SkPaint& paint) override; 117c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawRegion(const SkRegion& region, const SkPaint& paint) override; 118c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawRoundRect(float left, float top, float right, float bottom, 119c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger float rx, float ry, const SkPaint& paint) override; 120c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) override; 121c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawOval(float left, float top, float right, float bottom, 122c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger const SkPaint& paint) override; 123c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawArc(float left, float top, float right, float bottom, 124c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) override; 125c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawPath(const SkPath& path, const SkPaint& paint) override; 126c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount, 127c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger const float* verts, const float* tex, const int* colors, 128c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger const uint16_t* indices, int indexCount, const SkPaint& paint) override; 129c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 130aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv virtual void drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) override; 131fc9999505a36c66892d7ccce85187936105f4f36sergeyv virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) override; 132fc9999505a36c66892d7ccce85187936105f4f36sergeyv virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, 133c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger float srcRight, float srcBottom, float dstLeft, float dstTop, 134c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger float dstRight, float dstBottom, const SkPaint* paint) override; 1355fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv virtual void drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight, 136c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger const float* vertices, const int* colors, const SkPaint* paint) override; 1375fd2a1cb2726afa7d40fe4750e9defd89c24ed37sergeyv virtual void drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& chunk, 138c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger float dstLeft, float dstTop, float dstRight, float dstBottom, 139c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger const SkPaint* paint) override; 140c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 141c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual bool drawTextAbsolutePos() const override { return true; } 142c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override; 143c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 144c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left, 145c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right, 146c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx, 147c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) override; 148c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawCircle(uirenderer::CanvasPropertyPrimitive* x, 149c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger uirenderer::CanvasPropertyPrimitive* y, uirenderer::CanvasPropertyPrimitive* radius, 150c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger uirenderer::CanvasPropertyPaint* paint) override; 151c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 152c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override; 153c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override; 154c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void callDrawGLFunction(Functor* functor, 155c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger uirenderer::GlFunctorLifecycleListener* listener) override; 156c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 157c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenbergerprotected: 158f50806afb8982acbab4510a8d04bbcf13a2bcd9eStan Iliev SkiaCanvas(); 159c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger void reset(SkCanvas* skiaCanvas); 160c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger void drawDrawable(SkDrawable* drawable) { mCanvas->drawDrawable(drawable); } 161c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 162c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger virtual void drawGlyphs(const uint16_t* text, const float* positions, int count, 163c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger const SkPaint& paint, float x, float y, 164c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger float boundsLeft, float boundsTop, float boundsRight, float boundsBottom, 165c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger float totalAdvance) override; 166afc221499d943386256feb9db46c119ff834bf79Yuqian Li virtual void drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset, 167afc221499d943386256feb9db46c119ff834bf79Yuqian Li const SkPaint& paint, const SkPath& path, size_t start, size_t end) override; 168c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 169c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenbergerprivate: 170c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger struct SaveRec { 171c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger int saveCount; 172c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger SaveFlags::Flags saveFlags; 173f50806afb8982acbab4510a8d04bbcf13a2bcd9eStan Iliev size_t clipIndex; 174c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger }; 175c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 176c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger bool mHighContrastText = false; 177c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 178f50806afb8982acbab4510a8d04bbcf13a2bcd9eStan Iliev const SaveRec* currentSaveRec() const; 179c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger void recordPartialSave(SaveFlags::Flags flags); 180f50806afb8982acbab4510a8d04bbcf13a2bcd9eStan Iliev 181f50806afb8982acbab4510a8d04bbcf13a2bcd9eStan Iliev template<typename T> 1826e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed void recordClip(const T&, SkClipOp); 183f50806afb8982acbab4510a8d04bbcf13a2bcd9eStan Iliev void applyPersistentClips(size_t clipStartIndex); 184c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 185c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger void drawPoints(const float* points, int count, const SkPaint& paint, 186c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger SkCanvas::PointMode mode); 187c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 188f50806afb8982acbab4510a8d04bbcf13a2bcd9eStan Iliev class Clip; 189f50806afb8982acbab4510a8d04bbcf13a2bcd9eStan Iliev 190ea70d22dc8dc5d61f075edf6d03f86f6a68169cdMatt Sarett std::unique_ptr<SkCanvas> mCanvasWrapper; // might own a wrapper on the canvas 1916acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed std::unique_ptr<SkCanvas> mCanvasOwned; // might own a canvas we allocated 1926acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed SkCanvas* mCanvas; // we do NOT own this canvas, it must survive us 1936acfe16b5650446dbdcce3bd779b52fb6533a41eMike Reed // unless it is the same as mCanvasOwned.get() 194c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger std::unique_ptr<SkDeque> mSaveStack; // lazily allocated, tracks partial saves. 195f50806afb8982acbab4510a8d04bbcf13a2bcd9eStan Iliev std::vector<Clip> mClipStack; // tracks persistent clips. 196c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger}; 197c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 198c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger} // namespace android 199c190813b938ecf28d9e76b07098e9637ced8808eDerek Sollenberger 200