Isolate SpriteIcon into its own file.

This is to isolate differences between internal master and AOSP so that
the open source intern can work on a relatively new project.

It also isolates a divergent piece of code into SpriteIcon.cpp.

Bug: None
Test: Pointer icons in ApiDemos still work.
Change-Id: I1bf8f23411ad7170de2497d6fee0f70b015e9b5f
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 88d6033..5252cd0 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -17,6 +17,7 @@
     srcs: [
         "PointerController.cpp",
         "SpriteController.cpp",
+        "SpriteIcon.cpp",
     ],
 
     shared_libs: [
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index 804644c..acd8bce 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -23,11 +23,6 @@
 #include <utils/String8.h>
 #include <gui/Surface.h>
 
-#include <android/graphics/bitmap.h>
-#include <android/graphics/canvas.h>
-#include <android/graphics/paint.h>
-#include <android/native_window.h>
-
 namespace android {
 
 // --- SpriteController ---
@@ -130,8 +125,8 @@
         SpriteUpdate& update = updates.editItemAt(i);
 
         if (update.state.surfaceControl == NULL && update.state.wantSurfaceVisible()) {
-            update.state.surfaceWidth = update.state.icon.bitmap.getInfo().width;
-            update.state.surfaceHeight = update.state.icon.bitmap.getInfo().height;
+            update.state.surfaceWidth = update.state.icon.width();
+            update.state.surfaceHeight = update.state.icon.height();
             update.state.surfaceDrawn = false;
             update.state.surfaceVisible = false;
             update.state.surfaceControl = obtainSurface(
@@ -152,8 +147,8 @@
         }
 
         if (update.state.wantSurfaceVisible()) {
-            int32_t desiredWidth = update.state.icon.bitmap.getInfo().width;
-            int32_t desiredHeight = update.state.icon.bitmap.getInfo().height;
+            int32_t desiredWidth = update.state.icon.width();
+            int32_t desiredHeight = update.state.icon.height();
             if (update.state.surfaceWidth < desiredWidth
                     || update.state.surfaceHeight < desiredHeight) {
                 needApplyTransaction = true;
@@ -194,36 +189,9 @@
         if (update.state.surfaceControl != NULL && !update.state.surfaceDrawn
                 && update.state.wantSurfaceVisible()) {
             sp<Surface> surface = update.state.surfaceControl->getSurface();
-            ANativeWindow_Buffer outBuffer;
-            status_t status = surface->lock(&outBuffer, NULL);
-            if (status) {
-                ALOGE("Error %d locking sprite surface before drawing.", status);
-            } else {
-                graphics::Paint paint;
-                paint.setBlendMode(ABLEND_MODE_SRC);
-
-                graphics::Canvas canvas(outBuffer, (int32_t) surface->getBuffersDataSpace());
-                canvas.drawBitmap(update.state.icon.bitmap, 0, 0, &paint);
-
-                const int iconWidth = update.state.icon.bitmap.getInfo().width;
-                const int iconHeight = update.state.icon.bitmap.getInfo().height;
-
-                if (outBuffer.width > iconWidth) {
-                    paint.setBlendMode(ABLEND_MODE_CLEAR); // clear to transparent
-                    canvas.drawRect({iconWidth, 0, outBuffer.width, iconHeight}, paint);
-                }
-                if (outBuffer.height > iconHeight) {
-                    paint.setBlendMode(ABLEND_MODE_CLEAR); // clear to transparent
-                    canvas.drawRect({0, iconHeight, outBuffer.width, outBuffer.height}, paint);
-                }
-
-                status = surface->unlockAndPost();
-                if (status) {
-                    ALOGE("Error %d unlocking and posting sprite surface after drawing.", status);
-                } else {
-                    update.state.surfaceDrawn = true;
-                    update.surfaceChanged = surfaceChanged = true;
-                }
+            if (update.state.icon.draw(surface)) {
+                update.state.surfaceDrawn = true;
+                update.surfaceChanged = surfaceChanged = true;
             }
         }
     }
diff --git a/libs/input/SpriteController.h b/libs/input/SpriteController.h
index 2513544..137b564 100644
--- a/libs/input/SpriteController.h
+++ b/libs/input/SpriteController.h
@@ -20,9 +20,10 @@
 #include <utils/RefBase.h>
 #include <utils/Looper.h>
 
-#include <android/graphics/bitmap.h>
 #include <gui/SurfaceComposerClient.h>
 
+#include "SpriteIcon.h"
+
 namespace android {
 
 /*
@@ -51,35 +52,6 @@
 };
 
 /*
- * Icon that a sprite displays, including its hotspot.
- */
-struct SpriteIcon {
-    inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) { }
-    inline SpriteIcon(const graphics::Bitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY) :
-            bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) { }
-
-    graphics::Bitmap bitmap;
-    int32_t style;
-    float hotSpotX;
-    float hotSpotY;
-
-    inline SpriteIcon copy() const {
-        return SpriteIcon(bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888), style, hotSpotX, hotSpotY);
-    }
-
-    inline void reset() {
-        bitmap.reset();
-        style = 0;
-        hotSpotX = 0;
-        hotSpotY = 0;
-    }
-
-    inline bool isValid() const {
-        return bitmap.isValid() && !bitmap.isEmpty();
-    }
-};
-
-/*
  * A sprite is a simple graphical object that is displayed on-screen above other layers.
  * The basic sprite class is an interface.
  * The implementation is provided by the sprite controller.
diff --git a/libs/input/SpriteIcon.cpp b/libs/input/SpriteIcon.cpp
new file mode 100644
index 0000000..b7e51e2
--- /dev/null
+++ b/libs/input/SpriteIcon.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#include "SpriteIcon.h"
+
+#include <android/graphics/bitmap.h>
+#include <android/graphics/canvas.h>
+#include <android/graphics/paint.h>
+#include <android/native_window.h>
+#include <log/log.h>
+
+namespace android {
+
+bool SpriteIcon::draw(sp<Surface> surface) const {
+    ANativeWindow_Buffer outBuffer;
+    status_t status = surface->lock(&outBuffer, NULL);
+    if (status) {
+        ALOGE("Error %d locking sprite surface before drawing.", status);
+        return false;
+    }
+
+    graphics::Paint paint;
+    paint.setBlendMode(ABLEND_MODE_SRC);
+
+    graphics::Canvas canvas(outBuffer, (int32_t)surface->getBuffersDataSpace());
+    canvas.drawBitmap(bitmap, 0, 0, &paint);
+
+    const int iconWidth = width();
+    const int iconHeight = height();
+
+    if (outBuffer.width > iconWidth) {
+        paint.setBlendMode(ABLEND_MODE_CLEAR); // clear to transparent
+        canvas.drawRect({iconWidth, 0, outBuffer.width, iconHeight}, paint);
+    }
+    if (outBuffer.height > iconHeight) {
+        paint.setBlendMode(ABLEND_MODE_CLEAR); // clear to transparent
+        canvas.drawRect({0, iconHeight, outBuffer.width, outBuffer.height}, paint);
+    }
+
+    status = surface->unlockAndPost();
+    if (status) {
+        ALOGE("Error %d unlocking and posting sprite surface after drawing.", status);
+    }
+    return !status;
+}
+
+} // namespace android
diff --git a/libs/input/SpriteIcon.h b/libs/input/SpriteIcon.h
new file mode 100644
index 0000000..a257d7e
--- /dev/null
+++ b/libs/input/SpriteIcon.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2020 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.
+ */
+
+#ifndef _UI_SPRITE_ICON_H
+#define _UI_SPRITE_ICON_H
+
+#include <android/graphics/bitmap.h>
+#include <gui/Surface.h>
+
+namespace android {
+
+/*
+ * Icon that a sprite displays, including its hotspot.
+ */
+struct SpriteIcon {
+    inline SpriteIcon() : style(0), hotSpotX(0), hotSpotY(0) {}
+    inline SpriteIcon(const graphics::Bitmap& bitmap, int32_t style, float hotSpotX, float hotSpotY)
+          : bitmap(bitmap), style(style), hotSpotX(hotSpotX), hotSpotY(hotSpotY) {}
+
+    graphics::Bitmap bitmap;
+    int32_t style;
+    float hotSpotX;
+    float hotSpotY;
+
+    inline SpriteIcon copy() const {
+        return SpriteIcon(bitmap.copy(ANDROID_BITMAP_FORMAT_RGBA_8888), style, hotSpotX, hotSpotY);
+    }
+
+    inline void reset() {
+        bitmap.reset();
+        style = 0;
+        hotSpotX = 0;
+        hotSpotY = 0;
+    }
+
+    inline bool isValid() const { return bitmap.isValid() && !bitmap.isEmpty(); }
+
+    inline int32_t width() const { return bitmap.getInfo().width; }
+    inline int32_t height() const { return bitmap.getInfo().height; }
+
+    // Draw the bitmap onto the given surface. Returns true if it's successful, or false otherwise.
+    // Note it doesn't set any metadata to the surface.
+    bool draw(const sp<Surface> surface) const;
+};
+
+} // namespace android
+
+#endif // _UI_SPRITE_ICON_H