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