AMM: Add graphics models.

Includes a description of the graphics models and adds sample code in
AmmTest.apk that exercises the relevant graphics APIs.

Bug: 69729799
Test: AmmTest.apk builds and runs on device.
Change-Id: I609c26d3233d3a9cc59e087f0b0e92129e0572a4
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java b/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java
index a326143..4577f4b 100644
--- a/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java
+++ b/tools/amm/AmmTest/src/com/android/amm/test/MainActivity.java
@@ -18,11 +18,15 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.widget.LinearLayout;
 
 public class MainActivity extends Activity {
 
   private BitmapUse mBitmapUse;
   private SoCodeUse mSoCodeUse;
+  private TextureViewUse mTextureViewUse;
+  private SurfaceViewUse mSurfaceViewUse;
+  private ThreadedRendererUse mThreadedRendererUse;
 
   @Override
   public void onCreate(Bundle savedInstanceState) {
@@ -30,6 +34,13 @@
 
     mBitmapUse = new BitmapUse();
     mSoCodeUse = new SoCodeUse();
+
+    LinearLayout ll = new LinearLayout(this);
+    mTextureViewUse = new TextureViewUse(this, ll, 200, 500);
+    mSurfaceViewUse = new SurfaceViewUse(this, ll, 240, 250);
+    setContentView(ll);
+
+    mThreadedRendererUse = new ThreadedRendererUse(this, 122, 152);
   }
 }
 
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java b/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java
new file mode 100644
index 0000000..0c17c77
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/SurfaceViewUse.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.amm.test;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.ViewGroup;
+
+class SurfaceViewUse {
+
+  private SurfaceView mSurfaceView;
+
+  /**
+   * Constructs a SurfaceView object with given dimensions.
+   * The surface view is added to the given ViewGroup object, which should be
+   * included in the main display.
+   */
+  public SurfaceViewUse(Context context, ViewGroup vg, int width, int height) {
+    mSurfaceView = new SurfaceView(context);
+    vg.addView(mSurfaceView, width, height);
+    mSurfaceView.post(new CycleRunnable());
+  }
+
+  // To force as many graphics buffers as will ever be used to actually be
+  // used, we cycle the color of the surface view a handful of times right
+  // when things start up.
+  private class CycleRunnable implements Runnable {
+    private int mCycles = 0;
+    private int mRed = 255;
+    private int mGreen = 0;
+    private int mBlue = 255;
+
+    public void run() {
+      if (mCycles < 10) {
+        mCycles++;
+        updateSurfaceView();
+        mSurfaceView.post(this);
+      }
+    }
+
+    private void updateSurfaceView() {
+      SurfaceHolder holder = mSurfaceView.getHolder();
+      Canvas canvas = holder.lockHardwareCanvas();
+      if (canvas != null) {
+        canvas.drawRGB(mRed, mGreen, mBlue);
+        int tmp = mRed;
+        holder.unlockCanvasAndPost(canvas);
+        mRed = mGreen;
+        mGreen = mBlue;
+        mBlue = tmp;
+      }
+    }
+  }
+}
+
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java b/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java
new file mode 100644
index 0000000..51ffcd2
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/TextureViewUse.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.amm.test;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.TextureView;
+import android.view.ViewGroup;
+
+class TextureViewUse {
+
+  private TextureView mTextureView;
+
+  /**
+   * Constructs a TextureView object with given dimensions.
+   * The texture view is added to the given ViewGroup object, which should be
+   * included in the main display.
+   */
+  public TextureViewUse(Context context, ViewGroup vg, int width, int height) {
+    mTextureView = new TextureView(context);
+    vg.addView(mTextureView, width, height);
+    mTextureView.post(new CycleRunnable());
+  }
+
+  // To force as many graphics buffers as will ever be used to actually be
+  // used, we cycle the color of the texture view a handful of times right
+  // when things start up.
+  private class CycleRunnable implements Runnable {
+    private int mCycles = 0;
+    private int mRed = 255;
+    private int mGreen = 255;
+    private int mBlue = 0;
+
+    public void run() {
+      if (mCycles < 10) {
+        mCycles++;
+        updateTextureView();
+        mTextureView.post(this);
+      }
+    }
+
+    private void updateTextureView() {
+      Canvas canvas = mTextureView.lockCanvas();
+      if (canvas != null) {
+        canvas.drawRGB(mRed, mGreen, mBlue);
+        int tmp = mRed;
+        mTextureView.unlockCanvasAndPost(canvas);
+        mRed = mGreen;
+        mGreen = mBlue;
+        mBlue = tmp;
+      }
+    }
+  }
+}
+
diff --git a/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java b/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java
new file mode 100644
index 0000000..9c25612
--- /dev/null
+++ b/tools/amm/AmmTest/src/com/android/amm/test/ThreadedRendererUse.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+package com.android.amm.test;
+
+import android.content.Context;
+import android.view.WindowManager;
+import android.widget.TextView;
+
+class ThreadedRendererUse {
+
+  private TextView mTextView;
+
+  /**
+   * Cause a threaded renderer EGL allocation to be used, with given
+   * dimensions.
+   */
+  public ThreadedRendererUse(Context context, int width, int height) {
+    mTextView = new TextView(context);
+    mTextView.setText("TRU");
+    mTextView.setBackgroundColor(0xffff0000);
+
+    // Adding a view to the WindowManager (as opposed to the app's root view
+    // hierarchy) causes a ThreadedRenderer and EGL allocations under the cover.
+    // We use a TextView here to trigger the use case, but we could use any
+    // other kind of view as well.
+    WindowManager wm = context.getSystemService(WindowManager.class);
+    WindowManager.LayoutParams layout = new WindowManager.LayoutParams();
+    layout.width = width;
+    layout.height = height;
+    wm.addView(mTextView, layout);
+
+    mTextView.post(new CycleRunnable());
+  }
+
+  // To force as many graphics buffers as will ever be used to actually be
+  // used, we cycle the text of the text view a handful of times right
+  // when things start up.
+  private class CycleRunnable implements Runnable {
+    private int mCycles = 0;
+
+    public void run() {
+      if (mCycles < 10) {
+        mCycles++;
+        mTextView.setText("TRU " + mCycles);
+        mTextView.post(this);
+      }
+    }
+  }
+}
+
diff --git a/tools/amm/models/Graphics.md b/tools/amm/models/Graphics.md
new file mode 100644
index 0000000..b327961
--- /dev/null
+++ b/tools/amm/models/Graphics.md
@@ -0,0 +1,22 @@
+# Graphics Models
+
+There are three components to the graphics model, each modeling EGL memory
+use:
+1. For each `android.view.TextureView` instance:
+    2 * (4 * width * height)
+
+2. For each `android.view.Surface$HwuiContext` instance:
+    3 * (4 * width * height)
+
+3. For each initialized `android.view.ThreadedRenderer`:
+    3 * (4 * width * height)
+
+Note: 4 is the number of bytes per pixel. 2 or 3 is the maximum number of
+buffers that may be allocated.
+
+The actionable breakdown is the breakdown by `TextureView`,
+`Surface$HwuiContext` and `ThreadedRenderer` instance, with further details
+about the width and height associated with each instance.
+
+For example, an application with a single 64x256 `TextureView` instance will
+be shown as taking up 128 KB.