summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--power_profile/camera_avg/Application/build.gradle56
-rw-r--r--power_profile/camera_avg/Application/src/main/AndroidManifest.xml40
-rw-r--r--power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/AutoFitTextureView.java76
-rw-r--r--power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/CameraActivity.java35
-rw-r--r--power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/CameraAvgFragment.java1036
-rw-r--r--power_profile/camera_avg/Application/src/main/res/drawable-hdpi/ic_action_info.pngbin0 -> 1025 bytes
-rw-r--r--power_profile/camera_avg/Application/src/main/res/drawable-hdpi/ic_launcher.pngbin0 -> 4251 bytes
-rw-r--r--power_profile/camera_avg/Application/src/main/res/drawable-hdpi/tile.9.pngbin0 -> 196 bytes
-rw-r--r--power_profile/camera_avg/Application/src/main/res/drawable-mdpi/ic_action_info.pngbin0 -> 665 bytes
-rw-r--r--power_profile/camera_avg/Application/src/main/res/drawable-mdpi/ic_launcher.pngbin0 -> 2622 bytes
-rw-r--r--power_profile/camera_avg/Application/src/main/res/drawable-xhdpi/ic_action_info.pngbin0 -> 1355 bytes
-rw-r--r--power_profile/camera_avg/Application/src/main/res/drawable-xhdpi/ic_launcher.pngbin0 -> 5911 bytes
-rw-r--r--power_profile/camera_avg/Application/src/main/res/drawable-xxhdpi/ic_action_info.pngbin0 -> 2265 bytes
-rw-r--r--power_profile/camera_avg/Application/src/main/res/drawable-xxhdpi/ic_launcher.pngbin0 -> 10488 bytes
-rw-r--r--power_profile/camera_avg/Application/src/main/res/layout-land/fragment_camera_avg.xml59
-rw-r--r--power_profile/camera_avg/Application/src/main/res/layout/activity_camera.xml21
-rw-r--r--power_profile/camera_avg/Application/src/main/res/layout/fragment_camera_avg.xml54
-rw-r--r--power_profile/camera_avg/Application/src/main/res/values-sw600dp/dimens.xml24
-rw-r--r--power_profile/camera_avg/Application/src/main/res/values-sw600dp/template-styles.xml25
-rw-r--r--power_profile/camera_avg/Application/src/main/res/values-v11/styles.xml22
-rw-r--r--power_profile/camera_avg/Application/src/main/res/values-v21/styles.xml23
-rw-r--r--power_profile/camera_avg/Application/src/main/res/values/colors.xml19
-rw-r--r--power_profile/camera_avg/Application/src/main/res/values/strings.xml32
-rw-r--r--power_profile/camera_avg/Application/src/main/res/values/styles.xml39
-rw-r--r--power_profile/camera_avg/Application/src/main/res/values/template-dimens.xml32
-rw-r--r--power_profile/camera_avg/Application/tests/AndroidManifest.xml38
-rw-r--r--power_profile/camera_avg/Application/tests/src/com/example/android/cameraavg/tests/SampleTests.java57
-rw-r--r--power_profile/camera_avg/LICENSE647
-rw-r--r--power_profile/camera_avg/gradle/wrapper/gradle-wrapper.jarbin0 -> 49896 bytes
-rw-r--r--power_profile/camera_avg/gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xpower_profile/camera_avg/gradlew164
-rw-r--r--power_profile/camera_avg/gradlew.bat90
-rw-r--r--power_profile/camera_avg/screenshots/icon-web.pngbin0 -> 64937 bytes
-rw-r--r--power_profile/camera_avg/screenshots/main.pngbin0 -> 1212538 bytes
-rw-r--r--power_profile/camera_avg/settings.gradle1
35 files changed, 2596 insertions, 0 deletions
diff --git a/power_profile/camera_avg/Application/build.gradle b/power_profile/camera_avg/Application/build.gradle
new file mode 100644
index 00000000..8f09e20f
--- /dev/null
+++ b/power_profile/camera_avg/Application/build.gradle
@@ -0,0 +1,56 @@
+buildscript {
+ repositories {
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.3.2'
+ }
+}
+
+apply plugin: 'com.android.application'
+
+repositories {
+ jcenter()
+}
+
+dependencies {
+ compile "com.android.support:support-v4:25.3.1"
+ compile "com.android.support:support-v13:25.3.1"
+ compile "com.android.support:cardview-v7:25.3.1"
+ compile "com.android.support:appcompat-v7:25.3.1"
+}
+
+// The sample build uses multiple directories to
+// keep boilerplate and common code separate from
+// the main sample code.
+List<String> dirs = [
+ 'main', // main sample code; look here for the interesting stuff.
+ 'common', // components that are reused by multiple samples
+ 'template'] // boilerplate code that is generated by the sample template process
+
+android {
+ compileSdkVersion 25
+ buildToolsVersion "25.0.3"
+
+ defaultConfig {
+ minSdkVersion 21
+ targetSdkVersion 25
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_7
+ targetCompatibility JavaVersion.VERSION_1_7
+ }
+
+ sourceSets {
+ main {
+ dirs.each { dir ->
+ java.srcDirs "src/${dir}/java"
+ res.srcDirs "src/${dir}/res"
+ }
+ }
+ androidTest.setRoot('tests')
+ androidTest.java.srcDirs = ['tests/src']
+ }
+}
diff --git a/power_profile/camera_avg/Application/src/main/AndroidManifest.xml b/power_profile/camera_avg/Application/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..65aa029c
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/AndroidManifest.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2014 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.powerprofile.cameraavg">
+
+ <uses-permission android:name="android.permission.CAMERA" />
+
+ <uses-feature android:name="android.hardware.camera" />
+ <uses-feature android:name="android.hardware.camera.autofocus" />
+
+ <application android:allowBackup="true"
+ android:label="@string/app_name"
+ android:icon="@drawable/ic_launcher"
+ android:theme="@style/Theme.AppCompat.Light.NoActionBar">
+
+ <activity android:name=".CameraActivity"
+ android:label="@string/app_name">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/AutoFitTextureView.java b/power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/AutoFitTextureView.java
new file mode 100644
index 00000000..8e13f158
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/AutoFitTextureView.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2014 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.example.android.powerprofile.cameraavg;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.TextureView;
+
+/**
+ * A {@link TextureView} that can be adjusted to a specified aspect ratio.
+ */
+public class AutoFitTextureView extends TextureView {
+
+ private int mRatioWidth = 0;
+ private int mRatioHeight = 0;
+
+ public AutoFitTextureView(Context context) {
+ this(context, null);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AutoFitTextureView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ /**
+ * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
+ * calculated from the parameters. Note that the actual sizes of parameters don't matter, that
+ * is, calling setAspectRatio(2, 3) and setAspectRatio(4, 6) make the same result.
+ *
+ * @param width Relative horizontal size
+ * @param height Relative vertical size
+ */
+ public void setAspectRatio(int width, int height) {
+ if (width < 0 || height < 0) {
+ throw new IllegalArgumentException("Size cannot be negative.");
+ }
+ mRatioWidth = width;
+ mRatioHeight = height;
+ requestLayout();
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ if (0 == mRatioWidth || 0 == mRatioHeight) {
+ setMeasuredDimension(width, height);
+ } else {
+ if (width < height * mRatioWidth / mRatioHeight) {
+ setMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
+ } else {
+ setMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
+ }
+ }
+ }
+
+}
diff --git a/power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/CameraActivity.java b/power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/CameraActivity.java
new file mode 100644
index 00000000..aaf49962
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/CameraActivity.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2014 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.example.android.powerprofile.cameraavg;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class CameraActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_camera);
+ if (null == savedInstanceState) {
+ getFragmentManager().beginTransaction()
+ .replace(R.id.container, CameraAvgFragment.newInstance())
+ .commit();
+ }
+ }
+
+}
diff --git a/power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/CameraAvgFragment.java b/power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/CameraAvgFragment.java
new file mode 100644
index 00000000..ec3e7149
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/java/com/example/android/powerprofile/cameraavg/CameraAvgFragment.java
@@ -0,0 +1,1036 @@
+/*
+ * Copyright 2014 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.example.android.powerprofile.cameraavg;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.app.Fragment;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.graphics.ImageFormat;
+import android.graphics.Matrix;
+import android.graphics.Point;
+import android.graphics.RectF;
+import android.graphics.SurfaceTexture;
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraManager;
+import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.params.StreamConfigurationMap;
+import android.media.Image;
+import android.media.ImageReader;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.support.annotation.NonNull;
+import android.support.v13.app.FragmentCompat;
+import android.support.v4.content.ContextCompat;
+import android.util.Log;
+import android.util.Size;
+import android.util.SparseIntArray;
+import android.view.LayoutInflater;
+import android.view.Surface;
+import android.view.TextureView;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+public class CameraAvgFragment extends Fragment
+ implements View.OnClickListener, FragmentCompat.OnRequestPermissionsResultCallback {
+
+ /**
+ * Conversion from screen rotation to JPEG orientation.
+ */
+ private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
+ private static final int REQUEST_CAMERA_PERMISSION = 1;
+ private static final String FRAGMENT_DIALOG = "dialog";
+
+ static {
+ ORIENTATIONS.append(Surface.ROTATION_0, 90);
+ ORIENTATIONS.append(Surface.ROTATION_90, 0);
+ ORIENTATIONS.append(Surface.ROTATION_180, 270);
+ ORIENTATIONS.append(Surface.ROTATION_270, 180);
+ }
+
+ /**
+ * Tag for the {@link Log}.
+ */
+ private static final String TAG = "CameraAvgFragment";
+
+ /**
+ * Camera state: Showing camera preview.
+ */
+ private static final int STATE_PREVIEW = 0;
+
+ /**
+ * Camera state: Waiting for the focus to be locked.
+ */
+ private static final int STATE_WAITING_LOCK = 1;
+
+ /**
+ * Camera state: Waiting for the exposure to be precapture state.
+ */
+ private static final int STATE_WAITING_PRECAPTURE = 2;
+
+ /**
+ * Camera state: Waiting for the exposure state to be something other than precapture.
+ */
+ private static final int STATE_WAITING_NON_PRECAPTURE = 3;
+
+ /**
+ * Camera state: Picture was taken.
+ */
+ private static final int STATE_PICTURE_TAKEN = 4;
+
+ /**
+ * Max preview width that is guaranteed by Camera2 API
+ */
+ private static final int MAX_PREVIEW_WIDTH = 1920;
+
+ /**
+ * Max preview height that is guaranteed by Camera2 API
+ */
+ private static final int MAX_PREVIEW_HEIGHT = 1080;
+
+ /**
+ * {@link TextureView.SurfaceTextureListener} handles several lifecycle events on a
+ * {@link TextureView}.
+ */
+ private final TextureView.SurfaceTextureListener mSurfaceTextureListener
+ = new TextureView.SurfaceTextureListener() {
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
+ openCamera(width, height);
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
+ configureTransform(width, height);
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture texture) {
+ }
+
+ };
+
+ /**
+ * ID of the current {@link CameraDevice}.
+ */
+ private String mCameraId;
+
+ /**
+ * An {@link AutoFitTextureView} for camera preview.
+ */
+ private AutoFitTextureView mTextureView;
+
+ /**
+ * A {@link CameraCaptureSession } for camera preview.
+ */
+ private CameraCaptureSession mCaptureSession;
+
+ /**
+ * A reference to the opened {@link CameraDevice}.
+ */
+ private CameraDevice mCameraDevice;
+
+ /**
+ * The {@link Size} of camera preview.
+ */
+ private Size mPreviewSize;
+
+ /**
+ * {@link CameraDevice.StateCallback} is called when {@link CameraDevice} changes its state.
+ */
+ private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
+
+ @Override
+ public void onOpened(@NonNull CameraDevice cameraDevice) {
+ // This method is called when the camera is opened. We start camera preview here.
+ mCameraOpenCloseLock.release();
+ mCameraDevice = cameraDevice;
+ createCameraPreviewSession();
+ }
+
+ @Override
+ public void onDisconnected(@NonNull CameraDevice cameraDevice) {
+ mCameraOpenCloseLock.release();
+ cameraDevice.close();
+ mCameraDevice = null;
+ }
+
+ @Override
+ public void onError(@NonNull CameraDevice cameraDevice, int error) {
+ mCameraOpenCloseLock.release();
+ cameraDevice.close();
+ mCameraDevice = null;
+ Activity activity = getActivity();
+ if (null != activity && !activity.isFinishing()) {
+ activity.finish();
+ }
+ }
+
+ };
+
+ /**
+ * An additional thread for running tasks that shouldn't block the UI.
+ */
+ private HandlerThread mBackgroundThread;
+
+ /**
+ * A {@link Handler} for running tasks in the background.
+ */
+ private Handler mBackgroundHandler;
+
+ /**
+ * An {@link ImageReader} that handles still image capture.
+ */
+ private ImageReader mImageReader;
+
+ /**
+ * This is the output file for our picture.
+ */
+ private File mFile;
+
+ /**
+ * This a callback object for the {@link ImageReader}. "onImageAvailable" will be called when a
+ * still image is ready to be saved.
+ */
+ private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
+ = new ImageReader.OnImageAvailableListener() {
+
+ @Override
+ public void onImageAvailable(ImageReader reader) {
+ mBackgroundHandler.post(new ImageSaver(reader.acquireNextImage(), mFile));
+ }
+ };
+
+ /**
+ * {@link CaptureRequest.Builder} for the camera preview
+ */
+ private CaptureRequest.Builder mPreviewRequestBuilder;
+
+ /**
+ * {@link CaptureRequest} generated by {@link #mPreviewRequestBuilder}
+ */
+ private CaptureRequest mPreviewRequest;
+
+ /**
+ * The current state of camera state for taking pictures.
+ *
+ * @see #mCaptureCallback
+ */
+ private int mState = STATE_PREVIEW;
+
+ /**
+ * A {@link Semaphore} to prevent the app from exiting before closing the camera.
+ */
+ private Semaphore mCameraOpenCloseLock = new Semaphore(1);
+
+ /**
+ * Whether the current camera device supports Flash or not.
+ */
+ private boolean mFlashSupported;
+
+ /**
+ * Orientation of the camera sensor
+ */
+ private int mSensorOrientation;
+
+ /**
+ * A {@link CameraCaptureSession.CaptureCallback} that handles events related to JPEG capture.
+ */
+ private CameraCaptureSession.CaptureCallback mCaptureCallback
+ = new CameraCaptureSession.CaptureCallback() {
+
+ private void process(CaptureResult result) {
+ switch (mState) {
+ case STATE_PREVIEW: {
+ // We have nothing to do when the camera preview is working normally.
+ break;
+ }
+ case STATE_WAITING_LOCK: {
+ Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
+ if (afState == null) {
+ captureStillPicture();
+ } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
+ CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
+ // CONTROL_AE_STATE can be null on some devices
+ Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
+ if (aeState == null ||
+ aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
+ mState = STATE_PICTURE_TAKEN;
+ captureStillPicture();
+ } else {
+ runPrecaptureSequence();
+ }
+ }
+ break;
+ }
+ case STATE_WAITING_PRECAPTURE: {
+ // CONTROL_AE_STATE can be null on some devices
+ Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
+ if (aeState == null ||
+ aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE ||
+ aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) {
+ mState = STATE_WAITING_NON_PRECAPTURE;
+ }
+ break;
+ }
+ case STATE_WAITING_NON_PRECAPTURE: {
+ // CONTROL_AE_STATE can be null on some devices
+ Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
+ if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
+ mState = STATE_PICTURE_TAKEN;
+ captureStillPicture();
+ }
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void onCaptureProgressed(@NonNull CameraCaptureSession session,
+ @NonNull CaptureRequest request,
+ @NonNull CaptureResult partialResult) {
+ process(partialResult);
+ }
+
+ @Override
+ public void onCaptureCompleted(@NonNull CameraCaptureSession session,
+ @NonNull CaptureRequest request,
+ @NonNull TotalCaptureResult result) {
+ process(result);
+ }
+
+ };
+
+ /**
+ * Shows a {@link Toast} on the UI thread.
+ *
+ * @param text The message to show
+ */
+ private void showToast(final String text) {
+ final Activity activity = getActivity();
+ if (activity != null) {
+ activity.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ Toast.makeText(activity, text, Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+ }
+
+ /**
+ * Given {@code choices} of {@code Size}s supported by a camera, choose the smallest one that
+ * is at least as large as the respective texture view size, and that is at most as large as the
+ * respective max size, and whose aspect ratio matches with the specified value. If such size
+ * doesn't exist, choose the largest one that is at most as large as the respective max size,
+ * and whose aspect ratio matches with the specified value.
+ *
+ * @param choices The list of sizes that the camera supports for the intended output
+ * class
+ * @param textureViewWidth The width of the texture view relative to sensor coordinate
+ * @param textureViewHeight The height of the texture view relative to sensor coordinate
+ * @param maxWidth The maximum width that can be chosen
+ * @param maxHeight The maximum height that can be chosen
+ * @param aspectRatio The aspect ratio
+ * @return The optimal {@code Size}, or an arbitrary one if none were big enough
+ */
+ private static Size chooseOptimalSize(Size[] choices, int textureViewWidth,
+ int textureViewHeight, int maxWidth, int maxHeight, Size aspectRatio) {
+
+ // Collect the supported resolutions that are at least as big as the preview Surface
+ List<Size> bigEnough = new ArrayList<>();
+ // Collect the supported resolutions that are smaller than the preview Surface
+ List<Size> notBigEnough = new ArrayList<>();
+ int w = aspectRatio.getWidth();
+ int h = aspectRatio.getHeight();
+ for (Size option : choices) {
+ if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight &&
+ option.getHeight() == option.getWidth() * h / w) {
+ if (option.getWidth() >= textureViewWidth &&
+ option.getHeight() >= textureViewHeight) {
+ bigEnough.add(option);
+ } else {
+ notBigEnough.add(option);
+ }
+ }
+ }
+
+ // Pick the smallest of those big enough. If there is no one big enough, pick the
+ // largest of those not big enough.
+ if (bigEnough.size() > 0) {
+ return Collections.min(bigEnough, new CompareSizesByArea());
+ } else if (notBigEnough.size() > 0) {
+ return Collections.max(notBigEnough, new CompareSizesByArea());
+ } else {
+ Log.e(TAG, "Couldn't find any suitable preview size");
+ return choices[0];
+ }
+ }
+
+ public static CameraAvgFragment newInstance() {
+ return new CameraAvgFragment();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_camera_avg, container, false);
+ }
+
+ @Override
+ public void onViewCreated(final View view, Bundle savedInstanceState) {
+ view.findViewById(R.id.picture).setOnClickListener(this);
+ view.findViewById(R.id.info).setOnClickListener(this);
+ mTextureView = (AutoFitTextureView) view.findViewById(R.id.texture);
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ mFile = new File(getActivity().getExternalFilesDir(null), "pic.jpg");
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ startBackgroundThread();
+
+ // When the screen is turned off and turned back on, the SurfaceTexture is already
+ // available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open
+ // a camera and start preview from here (otherwise, we wait until the surface is ready in
+ // the SurfaceTextureListener).
+ if (mTextureView.isAvailable()) {
+ openCamera(mTextureView.getWidth(), mTextureView.getHeight());
+ } else {
+ mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ closeCamera();
+ stopBackgroundThread();
+ super.onPause();
+ }
+
+ private void requestCameraPermission() {
+ if (FragmentCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
+ new ConfirmationDialog().show(getChildFragmentManager(), FRAGMENT_DIALOG);
+ } else {
+ FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA},
+ REQUEST_CAMERA_PERMISSION);
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
+ @NonNull int[] grantResults) {
+ if (requestCode == REQUEST_CAMERA_PERMISSION) {
+ if (grantResults.length != 1 || grantResults[0] != PackageManager.PERMISSION_GRANTED) {
+ ErrorDialog.newInstance(getString(R.string.request_permission))
+ .show(getChildFragmentManager(), FRAGMENT_DIALOG);
+ }
+ } else {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+ }
+
+ /**
+ * Sets up member variables related to camera.
+ *
+ * @param width The width of available size for camera preview
+ * @param height The height of available size for camera preview
+ */
+ private void setUpCameraOutputs(int width, int height) {
+ Activity activity = getActivity();
+ CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
+ try {
+ for (String cameraId : manager.getCameraIdList()) {
+ CameraCharacteristics characteristics
+ = manager.getCameraCharacteristics(cameraId);
+
+ // We don't use a front facing camera in this sample.
+ Integer facing = characteristics.get(CameraCharacteristics.LENS_FACING);
+ if (facing != null && facing == CameraCharacteristics.LENS_FACING_FRONT) {
+ continue;
+ }
+
+ StreamConfigurationMap map = characteristics.get(
+ CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ if (map == null) {
+ continue;
+ }
+
+ // For still image captures, we use the largest available size.
+ Size largest = Collections.max(
+ Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
+ new CompareSizesByArea());
+ mImageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(),
+ ImageFormat.JPEG, /*maxImages*/2);
+ mImageReader.setOnImageAvailableListener(
+ mOnImageAvailableListener, mBackgroundHandler);
+
+ // Find out if we need to swap dimension to get the preview size relative to sensor
+ // coordinate.
+ int displayRotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ //noinspection ConstantConditions
+ mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
+ boolean swappedDimensions = false;
+ switch (displayRotation) {
+ case Surface.ROTATION_0:
+ case Surface.ROTATION_180:
+ if (mSensorOrientation == 90 || mSensorOrientation == 270) {
+ swappedDimensions = true;
+ }
+ break;
+ case Surface.ROTATION_90:
+ case Surface.ROTATION_270:
+ if (mSensorOrientation == 0 || mSensorOrientation == 180) {
+ swappedDimensions = true;
+ }
+ break;
+ default:
+ Log.e(TAG, "Display rotation is invalid: " + displayRotation);
+ }
+
+ Point displaySize = new Point();
+ activity.getWindowManager().getDefaultDisplay().getSize(displaySize);
+ int rotatedPreviewWidth = width;
+ int rotatedPreviewHeight = height;
+ int maxPreviewWidth = displaySize.x;
+ int maxPreviewHeight = displaySize.y;
+
+ if (swappedDimensions) {
+ rotatedPreviewWidth = height;
+ rotatedPreviewHeight = width;
+ maxPreviewWidth = displaySize.y;
+ maxPreviewHeight = displaySize.x;
+ }
+
+ if (maxPreviewWidth > MAX_PREVIEW_WIDTH) {
+ maxPreviewWidth = MAX_PREVIEW_WIDTH;
+ }
+
+ if (maxPreviewHeight > MAX_PREVIEW_HEIGHT) {
+ maxPreviewHeight = MAX_PREVIEW_HEIGHT;
+ }
+
+ // Danger, W.R.! Attempting to use too large a preview size could exceed the camera
+ // bus' bandwidth limitation, resulting in gorgeous previews but the storage of
+ // garbage capture data.
+ mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
+ rotatedPreviewWidth, rotatedPreviewHeight, maxPreviewWidth,
+ maxPreviewHeight, largest);
+
+ // We fit the aspect ratio of TextureView to the size of preview we picked.
+ int orientation = getResources().getConfiguration().orientation;
+ if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ mTextureView.setAspectRatio(
+ mPreviewSize.getWidth(), mPreviewSize.getHeight());
+ } else {
+ mTextureView.setAspectRatio(
+ mPreviewSize.getHeight(), mPreviewSize.getWidth());
+ }
+
+ // Check if the flash is supported.
+ Boolean available = characteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
+ mFlashSupported = available == null ? false : available;
+
+ mCameraId = cameraId;
+ return;
+ }
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ } catch (NullPointerException e) {
+ // Currently an NPE is thrown when the Camera2API is used but not supported on the
+ // device this code runs.
+ ErrorDialog.newInstance(getString(R.string.camera_error))
+ .show(getChildFragmentManager(), FRAGMENT_DIALOG);
+ }
+ }
+
+ /**
+ * Opens the camera specified by {@link CameraAvgFragment#mCameraId}.
+ */
+ private void openCamera(int width, int height) {
+ if (ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
+ != PackageManager.PERMISSION_GRANTED) {
+ requestCameraPermission();
+ return;
+ }
+ setUpCameraOutputs(width, height);
+ configureTransform(width, height);
+ Activity activity = getActivity();
+ CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
+ try {
+ if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
+ throw new RuntimeException("Time out waiting to lock camera opening.");
+ }
+ manager.openCamera(mCameraId, mStateCallback, mBackgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock camera opening.", e);
+ }
+ }
+
+ /**
+ * Closes the current {@link CameraDevice}.
+ */
+ private void closeCamera() {
+ try {
+ mCameraOpenCloseLock.acquire();
+ if (null != mCaptureSession) {
+ mCaptureSession.close();
+ mCaptureSession = null;
+ }
+ if (null != mCameraDevice) {
+ mCameraDevice.close();
+ mCameraDevice = null;
+ }
+ if (null != mImageReader) {
+ mImageReader.close();
+ mImageReader = null;
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException("Interrupted while trying to lock camera closing.", e);
+ } finally {
+ mCameraOpenCloseLock.release();
+ }
+ }
+
+ /**
+ * Starts a background thread and its {@link Handler}.
+ */
+ private void startBackgroundThread() {
+ mBackgroundThread = new HandlerThread("CameraBackground");
+ mBackgroundThread.start();
+ mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
+ }
+
+ /**
+ * Stops the background thread and its {@link Handler}.
+ */
+ private void stopBackgroundThread() {
+ mBackgroundThread.quitSafely();
+ try {
+ mBackgroundThread.join();
+ mBackgroundThread = null;
+ mBackgroundHandler = null;
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Creates a new {@link CameraCaptureSession} for camera preview.
+ */
+ private void createCameraPreviewSession() {
+ try {
+ SurfaceTexture texture = mTextureView.getSurfaceTexture();
+ assert texture != null;
+
+ // We configure the size of default buffer to be the size of camera preview we want.
+ texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
+
+ // This is the output Surface we need to start preview.
+ Surface surface = new Surface(texture);
+
+ // We set up a CaptureRequest.Builder with the output Surface.
+ mPreviewRequestBuilder
+ = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
+ mPreviewRequestBuilder.addTarget(surface);
+
+ // Here, we create a CameraCaptureSession for camera preview.
+ mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),
+ new CameraCaptureSession.StateCallback() {
+
+ @Override
+ public void onConfigured(
+ @NonNull CameraCaptureSession cameraCaptureSession) {
+ // The camera is already closed
+ if (null == mCameraDevice) {
+ return;
+ }
+
+ // When the session is ready, we start displaying the preview.
+ mCaptureSession = cameraCaptureSession;
+ try {
+ // Auto focus should be continuous for camera preview.
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
+ // Flash is automatically enabled when necessary.
+ setAutoFlash(mPreviewRequestBuilder);
+
+ // Finally, we start displaying the camera preview.
+ mPreviewRequest = mPreviewRequestBuilder.build();
+ mCaptureSession.setRepeatingRequest(mPreviewRequest,
+ mCaptureCallback, mBackgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onConfigureFailed(
+ @NonNull CameraCaptureSession cameraCaptureSession) {
+ showToast("Failed");
+ }
+ }, null
+ );
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
+ * This method should be called after the camera preview size is determined in
+ * setUpCameraOutputs and also the size of `mTextureView` is fixed.
+ *
+ * @param viewWidth The width of `mTextureView`
+ * @param viewHeight The height of `mTextureView`
+ */
+ private void configureTransform(int viewWidth, int viewHeight) {
+ Activity activity = getActivity();
+ if (null == mTextureView || null == mPreviewSize || null == activity) {
+ return;
+ }
+ int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ Matrix matrix = new Matrix();
+ RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
+ RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
+ float centerX = viewRect.centerX();
+ float centerY = viewRect.centerY();
+ if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
+ bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
+ matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
+ float scale = Math.max(
+ (float) viewHeight / mPreviewSize.getHeight(),
+ (float) viewWidth / mPreviewSize.getWidth());
+ matrix.postScale(scale, scale, centerX, centerY);
+ matrix.postRotate(90 * (rotation - 2), centerX, centerY);
+ } else if (Surface.ROTATION_180 == rotation) {
+ matrix.postRotate(180, centerX, centerY);
+ }
+ mTextureView.setTransform(matrix);
+ }
+
+ /**
+ * Initiate a still image capture.
+ */
+ private void takePicture() {
+ lockFocus();
+ }
+
+ /**
+ * Lock the focus as the first step for a still image capture.
+ */
+ private void lockFocus() {
+ try {
+ // This is how to tell the camera to lock focus.
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
+ CameraMetadata.CONTROL_AF_TRIGGER_START);
+ // Tell #mCaptureCallback to wait for the lock.
+ mState = STATE_WAITING_LOCK;
+ mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
+ mBackgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Run the precapture sequence for capturing a still image. This method should be called when
+ * we get a response in {@link #mCaptureCallback} from {@link #lockFocus()}.
+ */
+ private void runPrecaptureSequence() {
+ try {
+ // This is how to tell the camera to trigger.
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
+ CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
+ // Tell #mCaptureCallback to wait for the precapture sequence to be set.
+ mState = STATE_WAITING_PRECAPTURE;
+ mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
+ mBackgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Capture a still picture. This method should be called when we get a response in
+ * {@link #mCaptureCallback} from {@link #lockFocus()}.
+ */
+ private void captureStillPicture() {
+ try {
+ final Activity activity = getActivity();
+ if (null == activity || null == mCameraDevice) {
+ return;
+ }
+ // This is the CaptureRequest.Builder that we use to take a picture.
+ final CaptureRequest.Builder captureBuilder =
+ mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
+ captureBuilder.addTarget(mImageReader.getSurface());
+
+ // Use the same AE and AF modes as the preview.
+ captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
+ CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
+ setAutoFlash(captureBuilder);
+
+ // Orientation
+ int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
+ captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));
+
+ CameraCaptureSession.CaptureCallback CaptureCallback
+ = new CameraCaptureSession.CaptureCallback() {
+
+ @Override
+ public void onCaptureCompleted(@NonNull CameraCaptureSession session,
+ @NonNull CaptureRequest request,
+ @NonNull TotalCaptureResult result) {
+ showToast("Saved: " + mFile);
+ Log.d(TAG, mFile.toString());
+ unlockFocus();
+ }
+ };
+
+ mCaptureSession.stopRepeating();
+ mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Retrieves the JPEG orientation from the specified screen rotation.
+ *
+ * @param rotation The screen rotation.
+ * @return The JPEG orientation (one of 0, 90, 270, and 360)
+ */
+ private int getOrientation(int rotation) {
+ // Sensor orientation is 90 for most devices, or 270 for some devices (eg. Nexus 5X)
+ // We have to take that into account and rotate JPEG properly.
+ // For devices with orientation of 90, we simply return our mapping from ORIENTATIONS.
+ // For devices with orientation of 270, we need to rotate the JPEG 180 degrees.
+ return (ORIENTATIONS.get(rotation) + mSensorOrientation + 270) % 360;
+ }
+
+ /**
+ * Unlock the focus. This method should be called when still image capture sequence is
+ * finished.
+ */
+ private void unlockFocus() {
+ try {
+ // Reset the auto-focus trigger
+ mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER,
+ CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
+ setAutoFlash(mPreviewRequestBuilder);
+ mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback,
+ mBackgroundHandler);
+ // After this, the camera will go back to the normal state of preview.
+ mState = STATE_PREVIEW;
+ mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback,
+ mBackgroundHandler);
+ } catch (CameraAccessException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onClick(View view) {
+ switch (view.getId()) {
+ case R.id.picture: {
+ takePicture();
+ break;
+ }
+ case R.id.info: {
+ Activity activity = getActivity();
+ if (null != activity) {
+ new AlertDialog.Builder(activity)
+ .setMessage(R.string.intro_message)
+ .setPositiveButton(android.R.string.ok, null)
+ .show();
+ }
+ break;
+ }
+ }
+ }
+
+ private void setAutoFlash(CaptureRequest.Builder requestBuilder) {
+ if (mFlashSupported) {
+ requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,
+ CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
+ }
+ }
+
+ /**
+ * Saves a JPEG {@link Image} into the specified {@link File}.
+ */
+ private static class ImageSaver implements Runnable {
+
+ /**
+ * The JPEG image
+ */
+ private final Image mImage;
+ /**
+ * The file we save the image into.
+ */
+ private final File mFile;
+
+ public ImageSaver(Image image, File file) {
+ mImage = image;
+ mFile = file;
+ }
+
+ @Override
+ public void run() {
+ ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
+ byte[] bytes = new byte[buffer.remaining()];
+ buffer.get(bytes);
+ FileOutputStream output = null;
+ try {
+ output = new FileOutputStream(mFile);
+ output.write(bytes);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ mImage.close();
+ if (null != output) {
+ try {
+ output.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Compares two {@code Size}s based on their areas.
+ */
+ static class CompareSizesByArea implements Comparator<Size> {
+
+ @Override
+ public int compare(Size lhs, Size rhs) {
+ // We cast here to ensure the multiplications won't overflow
+ return Long.compare((long) lhs.getWidth() * lhs.getHeight(),
+ (long) rhs.getWidth() * rhs.getHeight());
+ }
+
+ }
+
+ /**
+ * Shows an error message dialog.
+ */
+ public static class ErrorDialog extends DialogFragment {
+
+ private static final String ARG_MESSAGE = "message";
+
+ public static ErrorDialog newInstance(String message) {
+ ErrorDialog dialog = new ErrorDialog();
+ Bundle args = new Bundle();
+ args.putString(ARG_MESSAGE, message);
+ dialog.setArguments(args);
+ return dialog;
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Activity activity = getActivity();
+ return new AlertDialog.Builder(activity)
+ .setMessage(getArguments().getString(ARG_MESSAGE))
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialogInterface, int i) {
+ if (activity != null && !activity.isFinishing()) {
+ activity.finish();
+ }
+ }
+ })
+ .create();
+ }
+
+ }
+
+ /**
+ * Shows OK/Cancel confirmation dialog about camera permission.
+ */
+ public static class ConfirmationDialog extends DialogFragment {
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Fragment parent = getParentFragment();
+ return new AlertDialog.Builder(getActivity())
+ .setMessage(R.string.request_permission)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ FragmentCompat.requestPermissions(parent,
+ new String[]{Manifest.permission.CAMERA},
+ REQUEST_CAMERA_PERMISSION);
+ }
+ })
+ .setNegativeButton(android.R.string.cancel,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Activity activity = parent.getActivity();
+ if (activity != null && !activity.isFinishing()) {
+ activity.finish();
+ }
+ }
+ })
+ .create();
+ }
+ }
+
+}
diff --git a/power_profile/camera_avg/Application/src/main/res/drawable-hdpi/ic_action_info.png b/power_profile/camera_avg/Application/src/main/res/drawable-hdpi/ic_action_info.png
new file mode 100644
index 00000000..32bd1aab
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/drawable-hdpi/ic_action_info.png
Binary files differ
diff --git a/power_profile/camera_avg/Application/src/main/res/drawable-hdpi/ic_launcher.png b/power_profile/camera_avg/Application/src/main/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..ac6cf278
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/power_profile/camera_avg/Application/src/main/res/drawable-hdpi/tile.9.png b/power_profile/camera_avg/Application/src/main/res/drawable-hdpi/tile.9.png
new file mode 100644
index 00000000..13586288
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/drawable-hdpi/tile.9.png
Binary files differ
diff --git a/power_profile/camera_avg/Application/src/main/res/drawable-mdpi/ic_action_info.png b/power_profile/camera_avg/Application/src/main/res/drawable-mdpi/ic_action_info.png
new file mode 100644
index 00000000..8efbbf8b
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/drawable-mdpi/ic_action_info.png
Binary files differ
diff --git a/power_profile/camera_avg/Application/src/main/res/drawable-mdpi/ic_launcher.png b/power_profile/camera_avg/Application/src/main/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..65f92a52
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/power_profile/camera_avg/Application/src/main/res/drawable-xhdpi/ic_action_info.png b/power_profile/camera_avg/Application/src/main/res/drawable-xhdpi/ic_action_info.png
new file mode 100644
index 00000000..ba143ea7
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/drawable-xhdpi/ic_action_info.png
Binary files differ
diff --git a/power_profile/camera_avg/Application/src/main/res/drawable-xhdpi/ic_launcher.png b/power_profile/camera_avg/Application/src/main/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..6fd13181
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/power_profile/camera_avg/Application/src/main/res/drawable-xxhdpi/ic_action_info.png b/power_profile/camera_avg/Application/src/main/res/drawable-xxhdpi/ic_action_info.png
new file mode 100644
index 00000000..394eb7e5
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/drawable-xxhdpi/ic_action_info.png
Binary files differ
diff --git a/power_profile/camera_avg/Application/src/main/res/drawable-xxhdpi/ic_launcher.png b/power_profile/camera_avg/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..4513cf2e
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/power_profile/camera_avg/Application/src/main/res/layout-land/fragment_camera_avg.xml b/power_profile/camera_avg/Application/src/main/res/layout-land/fragment_camera_avg.xml
new file mode 100644
index 00000000..9b8f509e
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/layout-land/fragment_camera_avg.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2014 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.
+-->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.example.android.powerprofile.cameraavg.AutoFitTextureView
+ android:id="@+id/texture"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true" />
+
+ <FrameLayout
+ android:id="@+id/control"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ android:layout_toRightOf="@id/texture"
+ android:background="@color/control_background"
+ android:orientation="horizontal">
+
+ <Button
+ android:id="@+id/picture"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/picture" />
+
+ <ImageButton
+ android:id="@+id/info"
+ style="@style/Widget.AppCompat.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|bottom"
+ android:contentDescription="@string/description_info"
+ android:padding="20dp"
+ android:src="@drawable/ic_action_info" />
+
+ </FrameLayout>
+
+</RelativeLayout>
diff --git a/power_profile/camera_avg/Application/src/main/res/layout/activity_camera.xml b/power_profile/camera_avg/Application/src/main/res/layout/activity_camera.xml
new file mode 100644
index 00000000..3833ad0d
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/layout/activity_camera.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2014 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.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#000" />
diff --git a/power_profile/camera_avg/Application/src/main/res/layout/fragment_camera_avg.xml b/power_profile/camera_avg/Application/src/main/res/layout/fragment_camera_avg.xml
new file mode 100644
index 00000000..4137a7b2
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/layout/fragment_camera_avg.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2014 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <com.example.android.powerprofile.cameraavg.AutoFitTextureView
+ android:id="@+id/texture"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true" />
+
+ <FrameLayout
+ android:id="@+id/control"
+ android:layout_width="match_parent"
+ android:layout_height="112dp"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentStart="true"
+ android:background="@color/control_background">
+
+ <Button
+ android:id="@+id/picture"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:text="@string/picture" />
+
+ <ImageButton
+ android:id="@+id/info"
+ android:contentDescription="@string/description_info"
+ style="@style/Widget.AppCompat.Button.Borderless"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|right"
+ android:padding="20dp"
+ android:src="@drawable/ic_action_info" />
+
+ </FrameLayout>
+
+</RelativeLayout>
diff --git a/power_profile/camera_avg/Application/src/main/res/values-sw600dp/dimens.xml b/power_profile/camera_avg/Application/src/main/res/values-sw600dp/dimens.xml
new file mode 100644
index 00000000..22074a2b
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/values-sw600dp/dimens.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright 2013 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.
+ -->
+
+<resources>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_huge</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/power_profile/camera_avg/Application/src/main/res/values-sw600dp/template-styles.xml b/power_profile/camera_avg/Application/src/main/res/values-sw600dp/template-styles.xml
new file mode 100644
index 00000000..03d19741
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/values-sw600dp/template-styles.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright 2013 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.
+ -->
+
+<resources>
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceLarge</item>
+ <item name="android:lineSpacingMultiplier">1.2</item>
+ <item name="android:shadowDy">-6.5</item>
+ </style>
+
+</resources>
diff --git a/power_profile/camera_avg/Application/src/main/res/values-v11/styles.xml b/power_profile/camera_avg/Application/src/main/res/values-v11/styles.xml
new file mode 100644
index 00000000..8c1ea66f
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/values-v11/styles.xml
@@ -0,0 +1,22 @@
+<!--
+ Copyright 2013 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.
+ -->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Holo.Light" />
+
+</resources>
diff --git a/power_profile/camera_avg/Application/src/main/res/values-v21/styles.xml b/power_profile/camera_avg/Application/src/main/res/values-v21/styles.xml
new file mode 100644
index 00000000..9d010fc3
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/values-v21/styles.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2013 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.
+-->
+
+<resources>
+
+ <!-- Activity themes -->
+ <style name="Theme.Base" parent="android:Theme.Material.Light" />
+
+</resources>
diff --git a/power_profile/camera_avg/Application/src/main/res/values/colors.xml b/power_profile/camera_avg/Application/src/main/res/values/colors.xml
new file mode 100644
index 00000000..4b75d2b2
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/values/colors.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright 2015 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.
+-->
+<resources>
+ <color name="control_background">#cc4285f4</color>
+</resources>
diff --git a/power_profile/camera_avg/Application/src/main/res/values/strings.xml b/power_profile/camera_avg/Application/src/main/res/values/strings.xml
new file mode 100644
index 00000000..e281775b
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/values/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2014 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.
+-->
+<resources>
+ <string name="app_name">CameraAvg</string>
+ <string name="intro_message">
+ <![CDATA[
+
+
+ This app takes a photo every 6 milliseconds. It can be used to
+ generate a power profile.
+
+
+ ]]>
+ </string>
+ <string name="picture">Picture</string>
+ <string name="description_info">Info</string>
+ <string name="request_permission">This sample needs camera permission.</string>
+ <string name="camera_error">This device doesn\'t support Camera2 API.</string>
+</resources>
diff --git a/power_profile/camera_avg/Application/src/main/res/values/styles.xml b/power_profile/camera_avg/Application/src/main/res/values/styles.xml
new file mode 100644
index 00000000..8956124c
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/values/styles.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ Copyright 2014 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.
+-->
+<resources>
+
+ <!-- Activity themes -->
+
+ <style name="Theme.Base" parent="android:Theme.Light" />
+
+ <style name="Theme.Sample" parent="Theme.Base" />
+ <!-- Widget styling -->
+
+ <style name="Widget" />
+
+ <style name="Widget.SampleMessage">
+ <item name="android:textAppearance">?android:textAppearanceMedium</item>
+ <item name="android:lineSpacingMultiplier">1.1</item>
+ </style>
+
+ <style name="Widget.SampleMessageTile">
+ <item name="android:background">@drawable/tile</item>
+ <item name="android:shadowColor">#7F000000</item>
+ <item name="android:shadowDy">-3.5</item>
+ <item name="android:shadowRadius">2</item>
+ </style>
+
+</resources>
diff --git a/power_profile/camera_avg/Application/src/main/res/values/template-dimens.xml b/power_profile/camera_avg/Application/src/main/res/values/template-dimens.xml
new file mode 100644
index 00000000..39e710b5
--- /dev/null
+++ b/power_profile/camera_avg/Application/src/main/res/values/template-dimens.xml
@@ -0,0 +1,32 @@
+<!--
+ Copyright 2013 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.
+ -->
+
+<resources>
+
+ <!-- Define standard dimensions to comply with Holo-style grids and rhythm. -->
+
+ <dimen name="margin_tiny">4dp</dimen>
+ <dimen name="margin_small">8dp</dimen>
+ <dimen name="margin_medium">16dp</dimen>
+ <dimen name="margin_large">32dp</dimen>
+ <dimen name="margin_huge">64dp</dimen>
+
+ <!-- Semantic definitions -->
+
+ <dimen name="horizontal_page_margin">@dimen/margin_medium</dimen>
+ <dimen name="vertical_page_margin">@dimen/margin_medium</dimen>
+
+</resources>
diff --git a/power_profile/camera_avg/Application/tests/AndroidManifest.xml b/power_profile/camera_avg/Application/tests/AndroidManifest.xml
new file mode 100644
index 00000000..8f30cedb
--- /dev/null
+++ b/power_profile/camera_avg/Application/tests/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2013 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 name must be unique so suffix with "tests" so package loader doesn't ignore us -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.powerprofile.cameraavg.tests"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <!-- We add an application tag here just so that we can indicate that
+ this package needs to link against the android.test library,
+ which is needed when building test cases. -->
+ <application>
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <!--
+ Specifies the instrumentation test runner used to run the tests.
+ -->
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.example.android.powerprofile.cameraavg"
+ android:label="Tests for com.example.android.powerprofile.cameraavg" />
+
+</manifest>
diff --git a/power_profile/camera_avg/Application/tests/src/com/example/android/cameraavg/tests/SampleTests.java b/power_profile/camera_avg/Application/tests/src/com/example/android/cameraavg/tests/SampleTests.java
new file mode 100644
index 00000000..d33f470d
--- /dev/null
+++ b/power_profile/camera_avg/Application/tests/src/com/example/android/cameraavg/tests/SampleTests.java
@@ -0,0 +1,57 @@
+/*
+* Copyright (C) 2013 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.example.android.powerprofile.cameraavg.tests;
+
+import com.example.android.powerprofile.cameraavg.*;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+/**
+* Tests for Camera2Basic sample.
+*/
+public class SampleTests extends ActivityInstrumentationTestCase2<CameraActivity> {
+
+ private CameraActivity mTestActivity;
+
+ public SampleTests() {
+ super(CameraActivity.class);
+ }
+
+ @Override
+ protected void setUp() {
+ super.setUp();
+
+ // Starts the activity under test using the default Intent with:
+ // action = {@link Intent#ACTION_MAIN}
+ // flags = {@link Intent#FLAG_ACTIVITY_NEW_TASK}
+ // All other fields are null or empty.
+ mTestActivity = getActivity();
+ }
+
+ /**
+ * Test if the test fixture has been set up correctly.
+ */
+ public void testPreconditions() {
+ //Try to add a message to add context to your assertions. These messages will be shown if
+ //a tests fails and make it easy to understand why a test failed
+ assertNotNull("mTestActivity is null", mTestActivity);
+ }
+
+ /**
+ * Add more tests below.
+ */
+
+}
diff --git a/power_profile/camera_avg/LICENSE b/power_profile/camera_avg/LICENSE
new file mode 100644
index 00000000..4f229463
--- /dev/null
+++ b/power_profile/camera_avg/LICENSE
@@ -0,0 +1,647 @@
+Apache License
+--------------
+
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ 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.
+
+All image and audio files (including *.png, *.jpg, *.svg, *.mp3, *.wav
+and *.ogg) are licensed under the CC-BY-NC license. All other files are
+licensed under the Apache 2 license.
+
+CC-BY-NC License
+----------------
+
+Attribution-NonCommercial-ShareAlike 4.0 International
+
+=======================================================================
+
+Creative Commons Corporation ("Creative Commons") is not a law firm and
+does not provide legal services or legal advice. Distribution of
+Creative Commons public licenses does not create a lawyer-client or
+other relationship. Creative Commons makes its licenses and related
+information available on an "as-is" basis. Creative Commons gives no
+warranties regarding its licenses, any material licensed under their
+terms and conditions, or any related information. Creative Commons
+disclaims all liability for damages resulting from their use to the
+fullest extent possible.
+
+Using Creative Commons Public Licenses
+
+Creative Commons public licenses provide a standard set of terms and
+conditions that creators and other rights holders may use to share
+original works of authorship and other material subject to copyright
+and certain other rights specified in the public license below. The
+following considerations are for informational purposes only, are not
+exhaustive, and do not form part of our licenses.
+
+ Considerations for licensors: Our public licenses are
+ intended for use by those authorized to give the public
+ permission to use material in ways otherwise restricted by
+ copyright and certain other rights. Our licenses are
+ irrevocable. Licensors should read and understand the terms
+ and conditions of the license they choose before applying it.
+ Licensors should also secure all rights necessary before
+ applying our licenses so that the public can reuse the
+ material as expected. Licensors should clearly mark any
+ material not subject to the license. This includes other CC-
+ licensed material, or material used under an exception or
+ limitation to copyright. More considerations for licensors:
+ wiki.creativecommons.org/Considerations_for_licensors
+
+ Considerations for the public: By using one of our public
+ licenses, a licensor grants the public permission to use the
+ licensed material under specified terms and conditions. If
+ the licensor's permission is not necessary for any reason--for
+ example, because of any applicable exception or limitation to
+ copyright--then that use is not regulated by the license. Our
+ licenses grant only permissions under copyright and certain
+ other rights that a licensor has authority to grant. Use of
+ the licensed material may still be restricted for other
+ reasons, including because others have copyright or other
+ rights in the material. A licensor may make special requests,
+ such as asking that all changes be marked or described.
+ Although not required by our licenses, you are encouraged to
+ respect those requests where reasonable. More_considerations
+ for the public:
+ wiki.creativecommons.org/Considerations_for_licensees
+
+=======================================================================
+
+Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
+Public License
+
+By exercising the Licensed Rights (defined below), You accept and agree
+to be bound by the terms and conditions of this Creative Commons
+Attribution-NonCommercial-ShareAlike 4.0 International Public License
+("Public License"). To the extent this Public License may be
+interpreted as a contract, You are granted the Licensed Rights in
+consideration of Your acceptance of these terms and conditions, and the
+Licensor grants You such rights in consideration of benefits the
+Licensor receives from making the Licensed Material available under
+these terms and conditions.
+
+
+Section 1 -- Definitions.
+
+ a. Adapted Material means material subject to Copyright and Similar
+ Rights that is derived from or based upon the Licensed Material
+ and in which the Licensed Material is translated, altered,
+ arranged, transformed, or otherwise modified in a manner requiring
+ permission under the Copyright and Similar Rights held by the
+ Licensor. For purposes of this Public License, where the Licensed
+ Material is a musical work, performance, or sound recording,
+ Adapted Material is always produced where the Licensed Material is
+ synched in timed relation with a moving image.
+
+ b. Adapter's License means the license You apply to Your Copyright
+ and Similar Rights in Your contributions to Adapted Material in
+ accordance with the terms and conditions of this Public License.
+
+ c. BY-NC-SA Compatible License means a license listed at
+ creativecommons.org/compatiblelicenses, approved by Creative
+ Commons as essentially the equivalent of this Public License.
+
+ d. Copyright and Similar Rights means copyright and/or similar rights
+ closely related to copyright including, without limitation,
+ performance, broadcast, sound recording, and Sui Generis Database
+ Rights, without regard to how the rights are labeled or
+ categorized. For purposes of this Public License, the rights
+ specified in Section 2(b)(1)-(2) are not Copyright and Similar
+ Rights.
+
+ e. Effective Technological Measures means those measures that, in the
+ absence of proper authority, may not be circumvented under laws
+ fulfilling obligations under Article 11 of the WIPO Copyright
+ Treaty adopted on December 20, 1996, and/or similar international
+ agreements.
+
+ f. Exceptions and Limitations means fair use, fair dealing, and/or
+ any other exception or limitation to Copyright and Similar Rights
+ that applies to Your use of the Licensed Material.
+
+ g. License Elements means the license attributes listed in the name
+ of a Creative Commons Public License. The License Elements of this
+ Public License are Attribution, NonCommercial, and ShareAlike.
+
+ h. Licensed Material means the artistic or literary work, database,
+ or other material to which the Licensor applied this Public
+ License.
+
+ i. Licensed Rights means the rights granted to You subject to the
+ terms and conditions of this Public License, which are limited to
+ all Copyright and Similar Rights that apply to Your use of the
+ Licensed Material and that the Licensor has authority to license.
+
+ j. Licensor means the individual(s) or entity(ies) granting rights
+ under this Public License.
+
+ k. NonCommercial means not primarily intended for or directed towards
+ commercial advantage or monetary compensation. For purposes of
+ this Public License, the exchange of the Licensed Material for
+ other material subject to Copyright and Similar Rights by digital
+ file-sharing or similar means is NonCommercial provided there is
+ no payment of monetary compensation in connection with the
+ exchange.
+
+ l. Share means to provide material to the public by any means or
+ process that requires permission under the Licensed Rights, such
+ as reproduction, public display, public performance, distribution,
+ dissemination, communication, or importation, and to make material
+ available to the public including in ways that members of the
+ public may access the material from a place and at a time
+ individually chosen by them.
+
+ m. Sui Generis Database Rights means rights other than copyright
+ resulting from Directive 96/9/EC of the European Parliament and of
+ the Council of 11 March 1996 on the legal protection of databases,
+ as amended and/or succeeded, as well as other essentially
+ equivalent rights anywhere in the world.
+
+ n. You means the individual or entity exercising the Licensed Rights
+ under this Public License. Your has a corresponding meaning.
+
+
+Section 2 -- Scope.
+
+ a. License grant.
+
+ 1. Subject to the terms and conditions of this Public License,
+ the Licensor hereby grants You a worldwide, royalty-free,
+ non-sublicensable, non-exclusive, irrevocable license to
+ exercise the Licensed Rights in the Licensed Material to:
+
+ a. reproduce and Share the Licensed Material, in whole or
+ in part, for NonCommercial purposes only; and
+
+ b. produce, reproduce, and Share Adapted Material for
+ NonCommercial purposes only.
+
+ 2. Exceptions and Limitations. For the avoidance of doubt, where
+ Exceptions and Limitations apply to Your use, this Public
+ License does not apply, and You do not need to comply with
+ its terms and conditions.
+
+ 3. Term. The term of this Public License is specified in Section
+ 6(a).
+
+ 4. Media and formats; technical modifications allowed. The
+ Licensor authorizes You to exercise the Licensed Rights in
+ all media and formats whether now known or hereafter created,
+ and to make technical modifications necessary to do so. The
+ Licensor waives and/or agrees not to assert any right or
+ authority to forbid You from making technical modifications
+ necessary to exercise the Licensed Rights, including
+ technical modifications necessary to circumvent Effective
+ Technological Measures. For purposes of this Public License,
+ simply making modifications authorized by this Section 2(a)
+ (4) never produces Adapted Material.
+
+ 5. Downstream recipients.
+
+ a. Offer from the Licensor -- Licensed Material. Every
+ recipient of the Licensed Material automatically
+ receives an offer from the Licensor to exercise the
+ Licensed Rights under the terms and conditions of this
+ Public License.
+
+ b. Additional offer from the Licensor -- Adapted Material.
+ Every recipient of Adapted Material from You
+ automatically receives an offer from the Licensor to
+ exercise the Licensed Rights in the Adapted Material
+ under the conditions of the Adapter's License You apply.
+
+ c. No downstream restrictions. You may not offer or impose
+ any additional or different terms or conditions on, or
+ apply any Effective Technological Measures to, the
+ Licensed Material if doing so restricts exercise of the
+ Licensed Rights by any recipient of the Licensed
+ Material.
+
+ 6. No endorsement. Nothing in this Public License constitutes or
+ may be construed as permission to assert or imply that You
+ are, or that Your use of the Licensed Material is, connected
+ with, or sponsored, endorsed, or granted official status by,
+ the Licensor or others designated to receive attribution as
+ provided in Section 3(a)(1)(A)(i).
+
+ b. Other rights.
+
+ 1. Moral rights, such as the right of integrity, are not
+ licensed under this Public License, nor are publicity,
+ privacy, and/or other similar personality rights; however, to
+ the extent possible, the Licensor waives and/or agrees not to
+ assert any such rights held by the Licensor to the limited
+ extent necessary to allow You to exercise the Licensed
+ Rights, but not otherwise.
+
+ 2. Patent and trademark rights are not licensed under this
+ Public License.
+
+ 3. To the extent possible, the Licensor waives any right to
+ collect royalties from You for the exercise of the Licensed
+ Rights, whether directly or through a collecting society
+ under any voluntary or waivable statutory or compulsory
+ licensing scheme. In all other cases the Licensor expressly
+ reserves any right to collect such royalties, including when
+ the Licensed Material is used other than for NonCommercial
+ purposes.
+
+
+Section 3 -- License Conditions.
+
+Your exercise of the Licensed Rights is expressly made subject to the
+following conditions.
+
+ a. Attribution.
+
+ 1. If You Share the Licensed Material (including in modified
+ form), You must:
+
+ a. retain the following if it is supplied by the Licensor
+ with the Licensed Material:
+
+ i. identification of the creator(s) of the Licensed
+ Material and any others designated to receive
+ attribution, in any reasonable manner requested by
+ the Licensor (including by pseudonym if
+ designated);
+
+ ii. a copyright notice;
+
+ iii. a notice that refers to this Public License;
+
+ iv. a notice that refers to the disclaimer of
+ warranties;
+
+ v. a URI or hyperlink to the Licensed Material to the
+ extent reasonably practicable;
+
+ b. indicate if You modified the Licensed Material and
+ retain an indication of any previous modifications; and
+
+ c. indicate the Licensed Material is licensed under this
+ Public License, and include the text of, or the URI or
+ hyperlink to, this Public License.
+
+ 2. You may satisfy the conditions in Section 3(a)(1) in any
+ reasonable manner based on the medium, means, and context in
+ which You Share the Licensed Material. For example, it may be
+ reasonable to satisfy the conditions by providing a URI or
+ hyperlink to a resource that includes the required
+ information.
+ 3. If requested by the Licensor, You must remove any of the
+ information required by Section 3(a)(1)(A) to the extent
+ reasonably practicable.
+
+ b. ShareAlike.
+
+ In addition to the conditions in Section 3(a), if You Share
+ Adapted Material You produce, the following conditions also apply.
+
+ 1. The Adapter's License You apply must be a Creative Commons
+ license with the same License Elements, this version or
+ later, or a BY-NC-SA Compatible License.
+
+ 2. You must include the text of, or the URI or hyperlink to, the
+ Adapter's License You apply. You may satisfy this condition
+ in any reasonable manner based on the medium, means, and
+ context in which You Share Adapted Material.
+
+ 3. You may not offer or impose any additional or different terms
+ or conditions on, or apply any Effective Technological
+ Measures to, Adapted Material that restrict exercise of the
+ rights granted under the Adapter's License You apply.
+
+
+Section 4 -- Sui Generis Database Rights.
+
+Where the Licensed Rights include Sui Generis Database Rights that
+apply to Your use of the Licensed Material:
+
+ a. for the avoidance of doubt, Section 2(a)(1) grants You the right
+ to extract, reuse, reproduce, and Share all or a substantial
+ portion of the contents of the database for NonCommercial purposes
+ only;
+
+ b. if You include all or a substantial portion of the database
+ contents in a database in which You have Sui Generis Database
+ Rights, then the database in which You have Sui Generis Database
+ Rights (but not its individual contents) is Adapted Material,
+ including for purposes of Section 3(b); and
+
+ c. You must comply with the conditions in Section 3(a) if You Share
+ all or a substantial portion of the contents of the database.
+
+For the avoidance of doubt, this Section 4 supplements and does not
+replace Your obligations under this Public License where the Licensed
+Rights include other Copyright and Similar Rights.
+
+
+Section 5 -- Disclaimer of Warranties and Limitation of Liability.
+
+ a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
+ EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
+ AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
+ IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
+ WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
+ ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
+ KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
+ ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
+
+ b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
+ TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
+ NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
+ INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
+ COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
+ USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
+ DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
+ IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
+
+ c. The disclaimer of warranties and limitation of liability provided
+ above shall be interpreted in a manner that, to the extent
+ possible, most closely approximates an absolute disclaimer and
+ waiver of all liability.
+
+
+Section 6 -- Term and Termination.
+
+ a. This Public License applies for the term of the Copyright and
+ Similar Rights licensed here. However, if You fail to comply with
+ this Public License, then Your rights under this Public License
+ terminate automatically.
+
+ b. Where Your right to use the Licensed Material has terminated under
+ Section 6(a), it reinstates:
+
+ 1. automatically as of the date the violation is cured, provided
+ it is cured within 30 days of Your discovery of the
+ violation; or
+
+ 2. upon express reinstatement by the Licensor.
+
+ For the avoidance of doubt, this Section 6(b) does not affect any
+ right the Licensor may have to seek remedies for Your violations
+ of this Public License.
+
+ c. For the avoidance of doubt, the Licensor may also offer the
+ Licensed Material under separate terms or conditions or stop
+ distributing the Licensed Material at any time; however, doing so
+ will not terminate this Public License.
+
+ d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
+ License.
+
+
+Section 7 -- Other Terms and Conditions.
+
+ a. The Licensor shall not be bound by any additional or different
+ terms or conditions communicated by You unless expressly agreed.
+
+ b. Any arrangements, understandings, or agreements regarding the
+ Licensed Material not stated herein are separate from and
+ independent of the terms and conditions of this Public License.
+
+
+Section 8 -- Interpretation.
+
+ a. For the avoidance of doubt, this Public License does not, and
+ shall not be interpreted to, reduce, limit, restrict, or impose
+ conditions on any use of the Licensed Material that could lawfully
+ be made without permission under this Public License.
+
+ b. To the extent possible, if any provision of this Public License is
+ deemed unenforceable, it shall be automatically reformed to the
+ minimum extent necessary to make it enforceable. If the provision
+ cannot be reformed, it shall be severed from this Public License
+ without affecting the enforceability of the remaining terms and
+ conditions.
+
+ c. No term or condition of this Public License will be waived and no
+ failure to comply consented to unless expressly agreed to by the
+ Licensor.
+
+ d. Nothing in this Public License constitutes or may be interpreted
+ as a limitation upon, or waiver of, any privileges and immunities
+ that apply to the Licensor or You, including from the legal
+ processes of any jurisdiction or authority.
+
+=======================================================================
+
+Creative Commons is not a party to its public licenses.
+Notwithstanding, Creative Commons may elect to apply one of its public
+licenses to material it publishes and in those instances will be
+considered the "Licensor." Except for the limited purpose of indicating
+that material is shared under a Creative Commons public license or as
+otherwise permitted by the Creative Commons policies published at
+creativecommons.org/policies, Creative Commons does not authorize the
+use of the trademark "Creative Commons" or any other trademark or logo
+of Creative Commons without its prior written consent including,
+without limitation, in connection with any unauthorized modifications
+to any of its public licenses or any other arrangements,
+understandings, or agreements concerning use of licensed material. For
+the avoidance of doubt, this paragraph does not form part of the public
+licenses.
+
+Creative Commons may be contacted at creativecommons.org.
+
diff --git a/power_profile/camera_avg/gradle/wrapper/gradle-wrapper.jar b/power_profile/camera_avg/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..8c0fb64a
--- /dev/null
+++ b/power_profile/camera_avg/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/power_profile/camera_avg/gradle/wrapper/gradle-wrapper.properties b/power_profile/camera_avg/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..4da4a580
--- /dev/null
+++ b/power_profile/camera_avg/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Apr 10 15:27:10 PDT 2013
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.4.1-all.zip \ No newline at end of file
diff --git a/power_profile/camera_avg/gradlew b/power_profile/camera_avg/gradlew
new file mode 100755
index 00000000..91a7e269
--- /dev/null
+++ b/power_profile/camera_avg/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/power_profile/camera_avg/gradlew.bat b/power_profile/camera_avg/gradlew.bat
new file mode 100644
index 00000000..aec99730
--- /dev/null
+++ b/power_profile/camera_avg/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/power_profile/camera_avg/screenshots/icon-web.png b/power_profile/camera_avg/screenshots/icon-web.png
new file mode 100644
index 00000000..d9bd4c48
--- /dev/null
+++ b/power_profile/camera_avg/screenshots/icon-web.png
Binary files differ
diff --git a/power_profile/camera_avg/screenshots/main.png b/power_profile/camera_avg/screenshots/main.png
new file mode 100644
index 00000000..47419eb4
--- /dev/null
+++ b/power_profile/camera_avg/screenshots/main.png
Binary files differ
diff --git a/power_profile/camera_avg/settings.gradle b/power_profile/camera_avg/settings.gradle
new file mode 100644
index 00000000..9464a359
--- /dev/null
+++ b/power_profile/camera_avg/settings.gradle
@@ -0,0 +1 @@
+include 'Application'