Home | History | Annotate | Download | only in analyzer
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.cts.verifier.camera.analyzer;
     18 
     19 import android.app.PendingIntent;
     20 import android.content.BroadcastReceiver;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentFilter;
     24 import android.graphics.Bitmap;
     25 import android.graphics.BitmapFactory;
     26 import android.graphics.ImageFormat;
     27 import android.hardware.Camera;
     28 import android.hardware.usb.UsbAccessory;
     29 import android.hardware.usb.UsbManager;
     30 import android.os.ParcelFileDescriptor;
     31 import android.util.Log;
     32 import android.view.SurfaceView;
     33 import android.widget.ImageView;
     34 import android.widget.Toast;
     35 
     36 import java.io.FileDescriptor;
     37 import java.io.FileInputStream;
     38 import java.io.FileOutputStream;
     39 import java.io.IOException;
     40 import java.util.ArrayList;
     41 import java.util.List;
     42 
     43 /**
     44  * Implements a test to verify whether the Auto Exposure Lock functions as
     45  * described in the API.
     46  *
     47  * The test consists three sub-categories. The first set of tests focus on
     48  * testing whether the auto exposure lock works in various situations.
     49  * For all tests in this set, the lock is set during the period when the camera
     50  * preview is open. In this way the lock locks exposure according to the
     51  * lighting at the moment of setting the lock. The second set of tests focus on
     52  * testing whether the auto exposure lock works as expected after turning the
     53  * preview off and on. The lock is set during the period when the camera
     54  * preview is turned off. The lock is expected to lock an exposure level
     55  * identical to the one before the preview is turned off. One special case in
     56  * this category is to set lock before the preview is turned on for the first
     57  * time.
     58  */
     59 public class AutoLockTest extends CameraTests {
     60 
     61     private static final String TAG = "AutoLockTest";
     62     /** USB permission to connect to ADK. */
     63     private static final String ACTION_USB_PERMISSION = "com.android.cts.verifier.USB_PERMISSION";
     64     /** Defines a long sleep period.*/
     65     private static final int SHORT_SLEEP = 2000;
     66     /** Defines a short sleep period. */
     67     private static final int LONG_SLEEP = 4000;
     68 
     69     /** Test results in text format. */
     70     private String mDebugText = new String();
     71     /** Detailed report. */
     72     private String mResultText = new String();
     73     /** Thread lock of the camera callbacks. */
     74     private final Object mProcessingImage = new Object();
     75     /** Memory address of the native test handler. */
     76     private long mTestHandler;
     77     /** Array storing the reference test results. */
     78     private ArrayList<Boolean> mReferenceCompareResults;
     79     /** Array storing the reference test scenario logs. */
     80     private ArrayList<String> mReferenceLogs;
     81     /** Number of tests so far. */
     82     private int mTestCount;
     83 
     84     /** Usb Manager of the USB connections. */
     85     private UsbManager mUsbManager;
     86     /** Intent for getting the permission to access the ADK. */
     87     private PendingIntent mPermissionIntent;
     88     /** Boolean to represent whether a permission is gained. */
     89     private boolean mPermissionRequestPending;
     90     /** USB accessory pointing to the ADK. */
     91     private UsbAccessory mAccessory;
     92     /** File descriptor of the USB communication port. */
     93     private ParcelFileDescriptor mFileDescriptor;
     94     /** Output stream to write commands for ADK to. */
     95     private FileOutputStream mOutputStream;
     96 
     97     /** Pointer to the CameraAnalyzerActivity activity. */
     98     private CameraAnalyzerActivity mActivity;
     99     /** Boolean to tell whether the accessory is opened. */
    100     private boolean mSetupReady;
    101     /** Thread lock for setting up the usb. */
    102     private final Object mUsbSetup = new Object();
    103     /** Boolean to indicate whether there is an ADK attached. */
    104     private boolean mUsingUsb = false;
    105     /** Test results.*/
    106     private int[] mTestResults;
    107     /** Number of tests. */
    108     private int mNumTests;
    109     /** Singleton test instance.*/
    110     private static AutoLockTest singletonTest = null;
    111 
    112     /**
    113      * Receives the notice of whether the connection to ADK is granted or
    114      * denied.
    115      */
    116     private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
    117         @Override
    118         public void onReceive(Context context, Intent intent) {
    119             String action = intent.getAction();
    120             Log.v(TAG, String.format("Received USB broadcast with action %s ", action));
    121 
    122             if (ACTION_USB_PERMISSION.equals(action)) {
    123                 synchronized (this) {
    124                     UsbAccessory accessory =
    125                         (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
    126 
    127                     if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
    128                         // Grants the permission to connect to the ADK.
    129                         Log.v(TAG, "Open accessory 3");
    130                         openAccessory(accessory);
    131                         // Overwrites the old camera instsance with the one currently opened
    132                         // by the CameraAnalyzerActivity instance, since the permission
    133                         // dialogue pauses the CameraAnalyzerActivity and forces the camera to
    134                         // be released and reopened when the dialogue disappears.
    135                         mTestCamera = mActivity.getCameraInstance();
    136                     } else {
    137                         // Denies the permission to connect to the ADK.
    138                         Log.d(TAG, "permission denied for accessory " + accessory);
    139                     }
    140                     // Marks that the permission request has been processed.
    141                     mPermissionRequestPending = false;
    142                 }
    143             } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
    144                 // Invokes when the USB is detached.
    145                 // Closes the accessory if it has not been closed.
    146                 Log.v(TAG, "Usb device detached");
    147                 mUsingUsb = false;
    148                 UsbAccessory accessory =
    149                     (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
    150                 if (accessory != null && accessory.equals(mAccessory)) {
    151                     closeAccessory();
    152                 }
    153             }
    154         }
    155     };
    156 
    157     /**
    158      * Opens the ADK from USB and attaches the output stream with it.
    159      *
    160      * Notifies the tread lock that the USB setup is ready.
    161      */
    162     private void openAccessory(UsbAccessory accessory) {
    163         Log.d(TAG, "openAccessory: " + accessory);
    164         mFileDescriptor = mUsbManager.openAccessory(accessory);
    165 
    166         if (mFileDescriptor != null) {
    167             mAccessory = accessory;
    168             FileDescriptor fd = mFileDescriptor.getFileDescriptor();
    169             mOutputStream = new FileOutputStream(fd);
    170             Log.d(TAG, "accessory opened");
    171         } else {
    172             Log.d(TAG, "accessory open fail");
    173         }
    174 
    175         // Unlocks the thread lock of waiting for the USB to be ready.
    176         synchronized (mUsbSetup) {
    177             mSetupReady = true;
    178             Log.v(TAG, "Setup ready");
    179             mUsbSetup.notifyAll();
    180         }
    181     }
    182 
    183     /**
    184      * Closes the ADK and detaches the output stream from it.
    185      */
    186     private void closeAccessory() {
    187         try {
    188             if (mFileDescriptor != null) {
    189                 mFileDescriptor.close();
    190             }
    191         } catch (IOException e) {
    192         } finally {
    193             mFileDescriptor = null;
    194             mAccessory = null;
    195         }
    196     }
    197 
    198     /**
    199      * Constructs the AutoLockTest class, which can execute a series of tests
    200      * to verify whether the device's Auto Exposure Lock is working properly.
    201      *
    202      * The test uses the LED lights on an ADK device as light source to change
    203      * the lighting condition of the environment. The usb connection to the
    204      * ADK board is established in the constructor.
    205      *
    206      * @param hostActivity pointer to the <code>CameraAnalyzerActivity</code>
    207      * that instructs the Auto Lock Test
    208      * @param mCamera pointer to the current camera instance
    209      */
    210     private AutoLockTest(){
    211         super();
    212     }
    213 
    214     public static synchronized AutoLockTest getSingletonTest() {
    215         if (singletonTest == null) {
    216             Log.v(TAG, "Creating a new AutoLockTest instance");
    217             singletonTest = new AutoLockTest();
    218             singletonTest.initializeTest();
    219         }
    220         return singletonTest;
    221     }
    222 
    223     private void initializeTest() {
    224         // Creates a native test handler with a 120x160 pixel debug output
    225         mTestHandler = createAutoLockTest();
    226         mReferenceCompareResults = new ArrayList<Boolean>();
    227         mReferenceLogs = new ArrayList<String>();
    228         mNumTests = 4;
    229         mTestResults = new int[mNumTests];
    230         for (int i = 0; i < mNumTests; ++i) {
    231             mTestResults[i] = CameraTests.CAMERA_TEST_NOT_RUN;
    232         }
    233     }
    234 
    235     public void updateCamera() {}
    236 
    237     public void setActivity(CameraAnalyzerActivity hostActivity){
    238         if (mUsingUsb) {
    239             closeConnection();
    240         }
    241 
    242         mActivity = hostActivity;
    243 
    244         mSetupReady = false;
    245 
    246         Log.v(TAG, "Start to test ADK connection");
    247         // Starts to establish the connection to the ADK board.
    248         mUsbManager = (UsbManager) mActivity.getSystemService(Context.USB_SERVICE);
    249         mPermissionIntent = PendingIntent.getBroadcast(mActivity, 0,
    250                                                        new Intent(ACTION_USB_PERMISSION), 0);
    251         IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
    252         filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
    253         filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
    254         mActivity.registerReceiver(mUsbReceiver, filter);
    255 
    256         if (mActivity.getLastNonConfigurationInstance() != null) {
    257             mAccessory = (UsbAccessory) mActivity.getLastNonConfigurationInstance();
    258             Log.v(TAG, "Open acceossory 1");
    259             openAccessory(mAccessory);
    260         }
    261 
    262         // Skips the permission listener if the user already grants the ADK
    263         // permission previously in the app.
    264         UsbAccessory[] accessories = mUsbManager.getAccessoryList();
    265         UsbAccessory accessory = (accessories == null ? null : accessories[0]);
    266         if (accessory != null) {
    267             if (mUsbManager.hasPermission(accessory)) {
    268                 Log.v(TAG, "Open accessory 2");
    269                 openAccessory(accessory);
    270             } else {
    271                 synchronized (mUsbReceiver) {
    272                     if (!mPermissionRequestPending) {
    273                         mUsbManager.requestPermission(accessory, mPermissionIntent);
    274                         mPermissionRequestPending = true;
    275                     }
    276                 }
    277             }
    278             mUsingUsb = true;
    279         } else {
    280             Log.d(TAG, "accessory is null");
    281             mUsingUsb = false;
    282         }
    283 
    284     }
    285 
    286     /**
    287      * Closes the accessories and unregister the USB listener at the end of
    288      * tests.
    289      */
    290     public void closeConnection() {
    291         closeAccessory();
    292         mActivity.unregisterReceiver(mUsbReceiver);
    293     }
    294 
    295     protected void finalize ()  {
    296         if (mUsingUsb) {
    297             closeConnection();
    298         }
    299     }
    300 
    301     /**
    302      * Runs the Auto Lock tests. A total of 19 tests have been coded and
    303      * included. Developers can freely comment out tests not interested. In
    304      * the release version, all tests will be executed.
    305      */
    306     @Override
    307     public synchronized void run(int index){
    308         if (index == 0) {
    309             for (int i = 1; i < mNumTests; ++i) {
    310                 run(i);
    311             }
    312             return;
    313         }
    314 
    315         Log.v(TAG, "AutoLockTest thread started!");
    316 
    317         if (mUsingUsb && (!mSetupReady)) {
    318             // USB connection is not set up. Locks thread and wait.
    319             Log.v(TAG, "Setup not ready, waiting");
    320             synchronized (mUsbSetup) {
    321                 try{
    322                     Log.v(TAG, "Start waiting for Image");
    323                     mUsbSetup.wait();
    324                 } catch (InterruptedException e) {
    325                     Log.v(TAG, "Callback wait fails!");
    326                 }
    327             }
    328         }
    329 
    330         // Restarts the camera intance and attach the preview to the corrent
    331         // UI elements.
    332         restartCamera();
    333         startPreview();
    334 
    335         mTestCount = 0;
    336         switch (index) {
    337             case 1:
    338                 Log.v(TAG, "SP -> TP1 -> SP -> +1 -> Lock -> -1 -> TP2");
    339                 test0();
    340                 Log.v(TAG, "SP -> TP1 -> SP -> Lock -> +1 -> TP2 -> -1");
    341                 test1();
    342                 Log.v(TAG, "SP -> Lock -> +1 -> TP1 -> SP -> -1 -> Lock -> TP2");
    343                 test2();
    344                 Log.v(TAG, "SP -> Lock -> +1 -> TP1 -> SP -> Lock -> -1 -> TP2");
    345                 test3();
    346                 break;
    347             case 2:
    348                 Log.v(TAG, "SP -> +1 -> TP1 -> -1 -> Lock -> SP -> TP2");
    349                 test4();
    350                 Log.v(TAG, "SP -> +1 -> TP1 -> Lock -> SP -> -1 -> TP2");
    351                 test5();
    352                 Log.v(TAG, "SP -> TP1 -> +1 -> Lock -> SP -> -1 -> TP2");
    353                 test6();
    354                 Log.v(TAG, "SP -> TP1 -> +1 -> Lock -> SP -> TP2");
    355                 test7();
    356                 Log.v(TAG, "SP -> TP1 -> Lock -> SP -> +1 -> TP2");
    357                 test8();
    358                 Log.v(TAG, "SP -> +1 -> Lock -> -1 -> TP1 -> Lock -> SP -> TP2");
    359                 test9();
    360                 Log.v(TAG, "SP -> +1 -> Lock -> TP1 -> -1 -> Lock -> SP -> TP2");
    361                 test10();
    362                 Log.v(TAG, "SP -> Lock -> TP1 -> +1 -> Lock -> SP -> -1 -> TP2");
    363                 test11();
    364                 break;
    365             case 3:
    366                 Log.v(TAG, "Restart -> Lock -> SP -> TP1 -> Restart -> Lock -> SP -> +1 -> TP2");
    367                 test12();
    368                 Log.v(TAG, "Restart -> Lock -> SP -> +1 -> TP1 -> -1 -> Lock -> SP -> TP2");
    369                 test13();
    370                 Log.v(TAG, "Restart -> Lock -> SP -> +1 -> TP1 -> Lock -> SP -> -1 -> TP2");
    371                 test14();
    372                 Log.v(TAG, "Restart -> Lock -> SP -> TP1 -> +1 -> Lock -> SP -> -1 -> TP2");
    373                 test15();
    374                 Log.v(TAG, "Restart -> Lock -> SP -> TP1 -> +1 -> Lock -> SP -> TP2");
    375                 test16();
    376                 Log.v(TAG, "Restart -> Lock -> SP -> TP1 -> Lock -> SP -> +1 -> TP2");
    377                 test17();
    378                 Log.v(TAG, "Restart -> Lock -> SP -> TP1 -> Lock -> SP -> TP2");
    379                 test18();
    380                 break;
    381             default:
    382                 break;
    383         }
    384 
    385         releaseLock();
    386 
    387         Log.v(TAG, "Ready to process data");
    388         boolean[] testCompareResults = new boolean[2 * mTestCount];
    389 
    390         // Processes the data stored in the native test handler instance.
    391         // Stores the test results into a boolean array.
    392         processAutoLockTest(mTestHandler, testCompareResults);
    393 
    394         // Prepares the test result text output with the booelan result array.
    395         prepareDebugText(testCompareResults, index);
    396         mReferenceCompareResults.clear();
    397         mReferenceLogs.clear();
    398     }
    399 
    400     /**
    401      * Compares two images taken under the same lighting, Image 1 without AE
    402      * lock and Image 2 with AE locked under a bright light. Image 1 is
    403      * expected to be brighter than Image 2.
    404      * Tests whether AE lock works compared to no AE lock.
    405      */
    406     private void test0() {
    407         releaseLock();
    408         takePicture();
    409         startPreview();
    410         turnOnLight();
    411         setLock();
    412         turnOffLight();
    413         takePicture();
    414         startPreview();
    415         releaseLock();
    416         mReferenceCompareResults.add(true);
    417         mReferenceCompareResults.add(false);
    418         mReferenceLogs.add("Same lighting condition with one different lock");
    419         ++mTestCount;
    420     }
    421 
    422     /**
    423      * Compares two images taken under different lighting, Image 1 without AE
    424      * lock and Image 2 with with AE locked under the same light Image 1 is
    425      * taken. Image 2 is taken under a bright light. Image 1 is expected to be
    426      * darker than Image 2.
    427      * Tests whether AE lock works compared to no AE lock.
    428      */
    429     private void test1() {
    430         releaseLock();
    431         takePicture();
    432         startPreview();
    433         setLock();
    434         turnOnLight();
    435         takePicture();
    436         turnOffLight();
    437         startPreview();
    438         releaseLock();
    439         mReferenceCompareResults.add(false);
    440         mReferenceCompareResults.add(false);
    441         mReferenceLogs.add("One same lock with different lighting");
    442         ++mTestCount;
    443     }
    444 
    445     /**
    446      * Compares two images taken under different light, both with AE locked
    447      * under the same lighting. Image 1 is taken under a brighter light.
    448      * Image 1 is expected to be brighter than Image 2.
    449      * Tests whether AE locks the exposure to the same level in the same
    450      * lighting condition after preview restarts.
    451      */
    452      private void test2() {
    453         releaseLock();
    454         setLock();
    455         turnOnLight();
    456         takePicture();
    457         startPreview();
    458         turnOffLight();
    459         setLock();
    460         takePicture();
    461         startPreview();
    462         releaseLock();
    463         mReferenceCompareResults.add(true);
    464         mReferenceCompareResults.add(false);
    465         mReferenceLogs.add("Same locking locations with different lighting");
    466         ++mTestCount;
    467     }
    468 
    469     /**
    470      * Compares two images taken under different light, Image 1 with AE locked
    471      * under normal light and Image 2 with AE locked under a bright light.
    472      * Image 1 is taken under a bright light and Image 2 is taken in the normal
    473      * lighting. Image 1 is expected to be brighter than Image 2.
    474      * Tests whether AE lock can adjust to change of lighting conditions.
    475      */
    476     private void test3() {
    477         releaseLock();
    478         setLock();
    479         turnOnLight();
    480         takePicture();
    481         startPreview();
    482         setLock();
    483         turnOffLight();
    484         takePicture();
    485         startPreview();
    486         releaseLock();
    487         mReferenceCompareResults.add(true);
    488         mReferenceCompareResults.add(false);
    489         mReferenceLogs.add("Different locking locations with different lighting");
    490         ++mTestCount;
    491     }
    492 
    493     /**
    494      * Compares two images taken under different lighting, Image 1 without
    495      * AE lock and Image 2 with AE lock set before camera preview resumes.
    496      * Image 1 is taken under a bright light and the light is turned off before
    497      * camera preview starts again. Image 1 is expected to be brighter than
    498      * Image 2.
    499      * Tests whether setting AE lock between camera preview stops and restarts
    500      * can retain the exposure level of the previous AE-unlocked photo.
    501      */
    502     private void test4() {
    503         releaseLock();
    504         turnOnLight();
    505         takePicture();
    506         turnOffLight();
    507         setLock();
    508         startPreview();
    509         takePicture();
    510         startPreview();
    511         releaseLock();
    512         mReferenceCompareResults.add(true);
    513         mReferenceCompareResults.add(false);
    514         mReferenceLogs.add("Lock after takePicture and light change, before preview");
    515         ++mTestCount;
    516     }
    517 
    518     /**
    519      * Compares two images taken under different lighting, Image 1 without
    520      * AE lock and Image 2 with AE lock set before camera preview resumes.
    521      * Image 1 is taken under a bright light and the light is turned off after
    522      * preview restars but before Image 2 is taken. Image 1 is expected to be
    523      * brighter than Image 2.
    524      * Tests whether setting AE lock between camera preview stops and restarts
    525      * can retain the exposure level of the previous AE-unlocked photo.
    526      */
    527     private void test5() {
    528         releaseLock();
    529         turnOnLight();
    530         takePicture();
    531         setLock();
    532         startPreview();
    533         turnOffLight();
    534         takePicture();
    535         startPreview();
    536         releaseLock();
    537         mReferenceCompareResults.add(true);
    538         mReferenceCompareResults.add(false);
    539         mReferenceLogs.add("Lock between takePicture and light change, w/o light change");
    540         ++mTestCount;
    541     }
    542 
    543     private void test6() {
    544         releaseLock();
    545         takePicture();
    546         turnOnLight();
    547         setLock();
    548         startPreview();
    549         turnOffLight();
    550         takePicture();
    551         startPreview();
    552         releaseLock();
    553         mReferenceCompareResults.add(false);
    554         mReferenceCompareResults.add(true);
    555         mReferenceLogs.add("Lock after takePicture and light change, before preview.");
    556         ++mTestCount;
    557     }
    558 
    559     private void test7() {
    560         releaseLock();
    561         takePicture();
    562         turnOnLight();
    563         setLock();
    564         startPreview();
    565         takePicture();
    566         startPreview();
    567         releaseLock();
    568         turnOffLight();
    569         mReferenceCompareResults.add(false);
    570         mReferenceCompareResults.add(false);
    571         mReferenceLogs.add("Lock after takePicture and light change, before preview.");
    572         ++mTestCount;
    573     }
    574 
    575     private void test8() {
    576         releaseLock();
    577         takePicture();
    578         setLock();
    579         startPreview();
    580         turnOnLight();
    581         takePicture();
    582         startPreview();
    583         releaseLock();
    584         turnOffLight();
    585         mReferenceCompareResults.add(false);
    586         mReferenceCompareResults.add(false);
    587         mReferenceLogs.add("Lock after takePicture and before startPreview.");
    588         ++mTestCount;
    589     }
    590 
    591     private void test9() {
    592         releaseLock();
    593         turnOnLight();
    594         setLock();
    595         turnOffLight();
    596         takePicture();
    597         setLock();
    598         startPreview();
    599         takePicture();
    600         releaseLock();
    601         startPreview();
    602         mReferenceCompareResults.add(false);
    603         mReferenceCompareResults.add(true);
    604         mReferenceLogs.add("Lock after first lock with changing light");
    605         ++mTestCount;
    606     }
    607 
    608     private void test10() {
    609         releaseLock();
    610         turnOnLight();
    611         setLock();
    612         takePicture();
    613         turnOffLight();
    614         setLock();
    615         startPreview();
    616         takePicture();
    617         releaseLock();
    618         startPreview();
    619         mReferenceCompareResults.add(true);
    620         mReferenceCompareResults.add(false);
    621         mReferenceLogs.add("Lock after first lock with changing light");
    622         ++mTestCount;
    623     }
    624 
    625     private void test11() {
    626         releaseLock();
    627         setLock();
    628         takePicture();
    629         turnOnLight();
    630         setLock();
    631         startPreview();
    632         turnOffLight();
    633         takePicture();
    634         releaseLock();
    635         startPreview();
    636         mReferenceCompareResults.add(false);
    637         mReferenceCompareResults.add(true);
    638         mReferenceLogs.add("Lock after first lock with changing light");
    639         ++mTestCount;
    640     }
    641 
    642     private void test12() {
    643         //"Restart -> Lock -> SP -> TP1 -> Restart -> Lock -> SP -> +1 -> TP2"
    644         restartCamera();
    645         setLock();
    646         startPreview();
    647         takePicture();
    648         releaseLock();
    649         restartCamera();
    650         setLock();
    651         startPreview();
    652         turnOnLight();
    653         takePicture();
    654         releaseLock();
    655         turnOffLight();
    656         startPreview();
    657         //mTestCamera.release();
    658         mReferenceCompareResults.add(false);
    659         mReferenceCompareResults.add(false);
    660         mReferenceLogs.add("Lock before first preview");
    661         ++mTestCount;
    662     }
    663 
    664     private void test13() {
    665         //"Restart -> Lock -> SP -> +1 -> TP1 -> -1 -> Lock -> SP -> TP2"
    666         restartCamera();
    667         setLock();
    668         startPreview();
    669         turnOnLight();
    670         takePicture();
    671         turnOffLight();
    672         setLock();
    673         startPreview();
    674         takePicture();
    675         releaseLock();
    676         startPreview();
    677         mReferenceCompareResults.add(true);
    678         mReferenceCompareResults.add(false);
    679         mReferenceLogs.add("Lock after first lock with changing light");
    680         ++mTestCount;
    681     }
    682 
    683     private void test14() {
    684         //"Restart -> Lock -> SP -> +1 -> TP1 -> Lock -> SP -> -1 -> TP2"
    685         restartCamera();
    686         setLock();
    687         startPreview();
    688         turnOnLight();
    689         takePicture();
    690         setLock();
    691         startPreview();
    692         turnOffLight();
    693         takePicture();
    694         releaseLock();
    695         startPreview();
    696         mReferenceCompareResults.add(true);
    697         mReferenceCompareResults.add(false);
    698         mReferenceLogs.add("Lock after first lock with changing light");
    699         ++mTestCount;
    700     }
    701 
    702     private void test15() {
    703         //"Restart -> Lock -> SP -> TP1 -> +1 -> Lock -> SP -> -1 -> TP2"
    704          restartCamera();
    705         setLock();
    706         startPreview();
    707         takePicture();
    708         turnOnLight();
    709         setLock();
    710         startPreview();
    711         turnOffLight();
    712         takePicture();
    713         releaseLock();
    714         startPreview();
    715         mReferenceCompareResults.add(false);
    716         mReferenceCompareResults.add(true);
    717         mReferenceLogs.add("Lock after first lock with changing light");
    718         ++mTestCount;
    719     }
    720 
    721     private void test16() {
    722         //"Restart -> Lock -> SP -> TP1 -> +1 -> Lock -> SP -> TP2"
    723         restartCamera();
    724         setLock();
    725         startPreview();
    726         takePicture();
    727         turnOnLight();
    728         setLock();
    729         startPreview();
    730         takePicture();
    731         turnOffLight();
    732         releaseLock();
    733         startPreview();
    734         mReferenceCompareResults.add(false);
    735         mReferenceCompareResults.add(false);
    736         mReferenceLogs.add("Lock after first lock with changing light");
    737         ++mTestCount;
    738     }
    739 
    740     private void test17() {
    741         //"Restart -> Lock -> SP -> TP1 -> Lock -> SP -> +1 -> TP2"
    742         restartCamera();
    743         setLock();
    744         startPreview();
    745         takePicture();
    746         setLock();
    747         startPreview();
    748         turnOnLight();
    749         takePicture();
    750         turnOffLight();
    751         releaseLock();
    752         startPreview();
    753         mReferenceCompareResults.add(false);
    754         mReferenceCompareResults.add(false);
    755         mReferenceLogs.add("Lock after first lock with changing light");
    756         ++mTestCount;
    757     }
    758 
    759     private void test18() {
    760         //"Restart -> Lock -> SP -> TP1 -> Lock -> SP -> TP2"
    761         restartCamera();
    762         setLock();
    763         startPreview();
    764         takePicture();
    765         setLock();
    766         startPreview();
    767         takePicture();
    768         releaseLock();
    769         startPreview();
    770         mReferenceCompareResults.add(false);
    771         mReferenceCompareResults.add(true);
    772         mReferenceLogs.add("Lock after first lock with changing light");
    773         ++mTestCount;
    774     }
    775 
    776     /**
    777      * Restarts the camera by releasing the current instance and get a new
    778      * instance. Also connects this new camera instance's preview to the proper
    779      * UI surfaceview.
    780      */
    781     private void restartCamera() {
    782         Log.v(TAG, "Restarting Camera");
    783 
    784         mTestCamera.release();
    785         Log.v(TAG, "Camera released");
    786 
    787         try {
    788             mTestCamera = Camera.open(mActivity.getCameraIdx());
    789         } catch (RuntimeException e) {
    790             throw new RuntimeException("Failed to open the camera", e);
    791         }
    792 
    793         Camera.Parameters params = mTestCamera.getParameters();
    794         params.setPictureFormat(ImageFormat.JPEG);
    795         params.setPictureSize(640, 480);
    796         mTestCamera.setParameters(params);
    797 
    798         try {
    799             mTestCamera.setPreviewDisplay(super.getCameraView().getHolder());
    800         } catch (IOException e) {
    801             throw new RuntimeException("Unable to connect camera to display: " + e);
    802         }
    803     }
    804 
    805     /**
    806      * Starts Camera preview with a delay of 2 seconds to let it adjust to
    807      * the lighting condition.
    808      */
    809     private void startPreview() {
    810         mTestCamera.startPreview();
    811         try{
    812             Log.v(TAG, "Waiting");
    813             Thread.sleep(2000);
    814             Log.v(TAG, "END Waiting");
    815         } catch (InterruptedException e){}
    816     }
    817 
    818     /**
    819      * Sends command to ADK to turn on all the LED lights to white.
    820      * Waits for 4 seconds for the camera to adjust to the new lighting.
    821      */
    822     private void turnOnLight() {
    823         Log.v(TAG, "Turn on light");
    824         if (mUsingUsb) {
    825             byte[] buffer = new byte[3];
    826 
    827             buffer[0] = (byte) 3;
    828             buffer[1] = (byte) 0;
    829             buffer[2] = (byte) 1;
    830             if (mOutputStream != null && buffer[1] != -1) {
    831                 try {
    832                     mOutputStream.write(buffer);
    833                 } catch (IOException e) {
    834                     Log.e(TAG, "write failed", e);
    835                 }
    836             }
    837         } else {
    838             mActivity.runOnUiThread(new Runnable() {
    839                 public void run() {
    840                     Toast.makeText(mActivity.getApplicationContext(), "Turn on light!", 4).show();
    841 
    842                 }
    843             });
    844         }
    845 
    846         try{
    847             Log.v(TAG, "Waiting, Please Turn on light");
    848             Thread.sleep(LONG_SLEEP);
    849             Log.v(TAG, "END Waiting");
    850         } catch (InterruptedException e){}
    851     }
    852 
    853     /**
    854      * Sends command to ADK to turn off all LED lights.
    855      * Waits for 4 seconds for the camera to adjust to the new lighting.
    856      */
    857     private void turnOffLight() {
    858         Log.v(TAG, "Turn off light");
    859         if (mUsingUsb) {
    860             byte[] buffer = new byte[3];
    861 
    862             buffer[0] = (byte) 3;
    863             buffer[1] = (byte) 0;
    864             buffer[2] = (byte) 0;
    865             if (mOutputStream != null && buffer[1] != -1) {
    866                 try {
    867                     mOutputStream.write(buffer);
    868                 } catch (IOException e) {
    869                     Log.e(TAG, "write failed", e);
    870                 }
    871             }
    872         } else {
    873             mActivity.runOnUiThread(new Runnable() {
    874                 public void run() {
    875                     Toast.makeText(mActivity.getApplicationContext(), "Turn off light!", 4).show();
    876 
    877                 }
    878             });
    879         }
    880 
    881         try{
    882             Log.v(TAG, "Waiting, Please Turn off light");
    883             Thread.sleep(LONG_SLEEP);
    884             Log.v(TAG, "END Waiting");
    885         } catch (InterruptedException e){}
    886     }
    887 
    888     /**
    889      * Sets the Auto Exposure Lock.
    890      * Waits for 2 seonds for the lock to function.
    891      */
    892     private void setLock() {
    893         Camera.Parameters params = mTestCamera.getParameters();
    894 
    895         params.setAutoExposureLock(true);
    896         params.setAutoWhiteBalanceLock(true);
    897         mTestCamera.setParameters(params);
    898         try{
    899             Log.v(TAG, "Waiting to set lock");
    900             Thread.sleep(2000);
    901             Log.v(TAG, "END Waiting");
    902         } catch (InterruptedException e){}
    903     }
    904 
    905     /**
    906      * Releases the Auto Exposure Lock.
    907      * Waits for 4 seconds afterwards for the Auto Exposure to be adjusted
    908      * to the lighting condition.
    909      */
    910     private void releaseLock() {
    911         Camera.Parameters params = mTestCamera.getParameters();
    912 
    913         params.setAutoExposureLock(false);
    914         params.setAutoWhiteBalanceLock(false);
    915         mTestCamera.setParameters(params);
    916         try{
    917             Log.v(TAG, "Waiting to release lock");
    918             Thread.sleep(LONG_SLEEP);
    919             Log.v(TAG, "END Waiting");
    920         } catch (InterruptedException e){}
    921 
    922     }
    923 
    924     /**
    925      * Takes a picture and locks thread until the picture callback finishes.
    926      */
    927     private void takePicture(){
    928         mTestCamera.takePicture(null, null, null, mTestJpegListener);
    929 
    930         synchronized (mProcessingImage) {
    931             try{
    932                 Log.v(TAG, "Start waiting for Image");
    933               //  System.gc();
    934                 mProcessingImage.wait();
    935             } catch (InterruptedException e){
    936                  Log.v(TAG, "Callback wait fails!");
    937             }
    938         }
    939     }
    940 
    941     /**
    942      * Prepare for the result to be shown in the UI. The result for each single
    943      * test is shown in green if it matches the reference result. It is shown
    944      * in red otherwise.
    945      */
    946     private void prepareDebugText(boolean[] testCompareResults, int index) {
    947         boolean groupTestPassed = true;
    948          for (int i = 0; i < mTestCount; ++i) {
    949               String testLog;
    950               boolean testPassed = true;
    951               testLog = mReferenceLogs.get(i);
    952               mDebugText += (testLog + "<br/>");
    953 
    954               if (testCompareResults[i * 2] == mReferenceCompareResults.get(i * 2)) {
    955                   mDebugText += String.format(
    956                       "Picture 1 brighter than Picture 2 is %b \n",
    957                       testCompareResults[i * 2]);
    958               } else {
    959                   mDebugText += String.format(
    960                       "Picture 1 brighter than Picture 2 is %b \n",
    961                       testCompareResults[i * 2]);
    962                   testPassed = false;
    963               }
    964 
    965               if (testCompareResults[i * 2 + 1] == mReferenceCompareResults.get(i * 2 + 1)) {
    966                   mDebugText += String.format(
    967                       "Picture 1 is equivalent to Picture 2 is %b \n",
    968                       testCompareResults[i * 2 + 1]);
    969               } else {
    970                   mDebugText += String.format(
    971                       "Picture 1 is equivalent to Picture 2 is %b \n",
    972                       testCompareResults[i * 2 + 1]);
    973                   testPassed = false;
    974               }
    975 
    976               if (testPassed) {
    977                   mDebugText += "Test passed! \n";
    978               } else {
    979                   mDebugText += "Test failed! \n";
    980                   groupTestPassed = false;
    981               }
    982          }
    983         if (groupTestPassed) {
    984             mTestResults[index] = CameraTests.CAMERA_TEST_SUCCESS;
    985         } else {
    986             mTestResults[index] = CameraTests.CAMERA_TEST_FAILURE;
    987         }
    988     }
    989 
    990     /**
    991      * Clears the debug text so that new test results can be added.
    992      */
    993     public void clearDebugText() {
    994         mDebugText = "";
    995     }
    996 
    997     @Override
    998     public String getDebugText() {
    999         return mDebugText;
   1000     }
   1001 
   1002     @Override
   1003     public String getResultText() {
   1004         return mDebugText;
   1005     }
   1006 
   1007     @Override
   1008     public String getTestName() {
   1009         return "Auto Exposure Lock test: \n";
   1010     }
   1011 
   1012     @Override
   1013     public String getTestName(int index) {
   1014         switch (index) {
   1015             case 0:
   1016                 return "Run all tests";
   1017             case 1:
   1018                 return "Compulsory tests";
   1019             case 2:
   1020                 return "Recommended tests (preview behavior)";
   1021             case 3:
   1022                 return "Optional tests (default lock)";
   1023             default:
   1024                 return "";
   1025         }
   1026     }
   1027 
   1028     @Override
   1029     public int getResult(int index) {
   1030         return mTestResults[index];
   1031     }
   1032 
   1033     @Override
   1034     public int getNumTests() {
   1035         return mNumTests;
   1036     }
   1037 
   1038     private Camera.PictureCallback mTestJpegListener = new Camera.PictureCallback() {
   1039         public void onPictureTaken(byte[] data, Camera mCamera) {
   1040             Log.v(TAG, "Shutter pressed down!");
   1041             Bitmap inputImage;
   1042 
   1043             // Decodes the camera input data into Bitmap.
   1044             // Constructs a native image class with the image.
   1045             inputImage = BitmapFactory.decodeByteArray(data, 0, data.length);
   1046             long bufferAddress = findNative(inputImage);
   1047             Log.v(TAG, "findNative method finishes");
   1048 
   1049             // Cleans up memory taken by the Bitmap.
   1050             data = null;
   1051             inputImage.recycle();
   1052             inputImage = null;
   1053             System.gc();
   1054 
   1055             // Passes data from the native image class to the native
   1056             // test handler.
   1057             createAutoLockClass(bufferAddress, mTestHandler,
   1058                                 getCheckerCenter(), getCheckerRadius());
   1059 
   1060             // Unlocks the thread lock.
   1061             synchronized (mProcessingImage) {
   1062                 mProcessingImage.notifyAll();
   1063             }
   1064         }
   1065     };
   1066 
   1067     private native long createAutoLockTest();
   1068 
   1069     private native void createAutoLockClass(long bufferAddress, long handlerAddress,
   1070                                             long checkerCenterAddress,
   1071                                             long checkerRadiusAddress);
   1072 
   1073     private native void processAutoLockTest(long handlerAddress, boolean[] testCompareResults);
   1074 
   1075     static {
   1076         System.loadLibrary("cameraanalyzer");
   1077     }
   1078 }
   1079