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 */ 16package com.android.systemui.screenshot; 17 18import android.graphics.Bitmap; 19import android.graphics.BitmapFactory; 20import android.os.Environment; 21import android.os.FileObserver; 22import android.test.ActivityInstrumentationTestCase2; 23import android.test.suitebuilder.annotation.LargeTest; 24import android.util.Log; 25import android.view.KeyEvent; 26 27import java.io.File; 28 29/** 30 * Functional tests for the global screenshot feature. 31 */ 32@LargeTest 33public class ScreenshotTest extends ActivityInstrumentationTestCase2<ScreenshotStubActivity> { 34 35 private static final String LOG_TAG = "ScreenshotTest"; 36 private static final int SCREEN_WAIT_TIME_SEC = 5; 37 38 public ScreenshotTest() { 39 super(ScreenshotStubActivity.class); 40 } 41 42 /** 43 * A simple test for screenshots that launches an Activity, injects the key event combo 44 * to trigger the screenshot, and verifies the screenshot was taken successfully. 45 */ 46 public void testScreenshot() throws Exception { 47 if (true) { 48 // Disable until this works again. 49 return; 50 } 51 Log.d(LOG_TAG, "starting testScreenshot"); 52 // launch the activity. 53 ScreenshotStubActivity activity = getActivity(); 54 assertNotNull(activity); 55 56 File screenshotDir = getScreenshotDir(); 57 NewScreenshotObserver observer = new NewScreenshotObserver( 58 screenshotDir.getAbsolutePath()); 59 observer.startWatching(); 60 takeScreenshot(); 61 // unlikely, but check if a new screenshot file was already created 62 if (observer.getCreatedPath() == null) { 63 // wait for screenshot to be created 64 synchronized(observer) { 65 observer.wait(SCREEN_WAIT_TIME_SEC*1000); 66 } 67 } 68 assertNotNull(String.format("Could not find screenshot after %d seconds", 69 SCREEN_WAIT_TIME_SEC), observer.getCreatedPath()); 70 71 File screenshotFile = new File(screenshotDir, observer.getCreatedPath()); 72 try { 73 assertTrue(String.format("Detected new screenshot %s but its not a file", 74 screenshotFile.getName()), screenshotFile.isFile()); 75 assertTrue(String.format("Detected new screenshot %s but its not an image", 76 screenshotFile.getName()), isValidImage(screenshotFile)); 77 } finally { 78 // delete the file to prevent external storage from filing up 79 screenshotFile.delete(); 80 } 81 } 82 83 private static class NewScreenshotObserver extends FileObserver { 84 private String mAddedPath = null; 85 86 NewScreenshotObserver(String path) { 87 super(path, FileObserver.CREATE); 88 } 89 90 synchronized String getCreatedPath() { 91 return mAddedPath; 92 } 93 94 @Override 95 public void onEvent(int event, String path) { 96 Log.d(LOG_TAG, String.format("Detected new file added %s", path)); 97 synchronized (this) { 98 mAddedPath = path; 99 notify(); 100 } 101 } 102 } 103 104 /** 105 * Inject the key sequence to take a screenshot. 106 */ 107 private void takeScreenshot() { 108 getInstrumentation().sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, 109 KeyEvent.KEYCODE_POWER)); 110 getInstrumentation().sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, 111 KeyEvent.KEYCODE_VOLUME_DOWN)); 112 // the volume down key event will cause the 'volume adjustment' UI to appear in the 113 // foreground, and steal UI focus 114 // unfortunately this means the next key event will get directed to the 115 // 'volume adjustment' UI, instead of this test's activity 116 // for this reason this test must be signed with platform certificate, to grant this test 117 // permission to inject key events to another process 118 getInstrumentation().sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, 119 KeyEvent.KEYCODE_VOLUME_DOWN)); 120 getInstrumentation().sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, 121 KeyEvent.KEYCODE_POWER)); 122 } 123 124 /** 125 * Get the directory where screenshot images are stored. 126 */ 127 private File getScreenshotDir() { 128 // TODO: get this dir location from a constant 129 return new File(Environment.getExternalStorageDirectory(), "Pictures" + File.separator + 130 "Screenshots"); 131 } 132 133 /** 134 * Return true if file is valid image file 135 */ 136 private boolean isValidImage(File screenshotFile) { 137 Bitmap b = BitmapFactory.decodeFile(screenshotFile.getAbsolutePath()); 138 // TODO: do more checks on image 139 return b != null; 140 } 141} 142