1 /* 2 * Copyright (C) 2015 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.cts.verifier.screenpinning; 17 18 import android.app.ActivityManager; 19 import android.os.Bundle; 20 import android.util.Log; 21 import android.view.View; 22 import android.view.View.OnClickListener; 23 import android.widget.Button; 24 import android.widget.LinearLayout; 25 import android.widget.TextView; 26 27 import com.android.cts.verifier.PassFailButtons; 28 import com.android.cts.verifier.R; 29 30 public class ScreenPinningTestActivity extends PassFailButtons.Activity { 31 32 private static final String TAG = "ScreenPinningTestActivity"; 33 private static final String KEY_CURRENT_TEST = "keyCurrentTest"; 34 private static final long TASK_MODE_CHECK_DELAY = 200; 35 private static final int MAX_TASK_MODE_CHECK_COUNT = 5; 36 37 private Test[] mTests; 38 private int mTestIndex; 39 40 private ActivityManager mActivityManager; 41 private Button mNextButton; 42 private LinearLayout mInstructions; 43 onCreate(Bundle savedInstanceState)44 protected void onCreate(Bundle savedInstanceState) { 45 super.onCreate(savedInstanceState); 46 setContentView(R.layout.screen_pinning); 47 setPassFailButtonClickListeners(); 48 49 mTests = new Test[] { 50 // Verify not already pinned. 51 mCheckStartedUnpinned, 52 // Enter pinning, verify pinned, try leaving and have the user exit. 53 mCheckStartPinning, 54 mCheckIsPinned, 55 mCheckTryLeave, 56 mCheckUnpin, 57 // Enter pinning, verify pinned, and use APIs to exit. 58 mCheckStartPinning, 59 mCheckIsPinned, 60 mCheckUnpinFromCode, 61 // All done. 62 mDone, 63 }; 64 65 mActivityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); 66 mInstructions = (LinearLayout) findViewById(R.id.instructions_list); 67 68 mNextButton = (Button) findViewById(R.id.next_button); 69 mNextButton.setOnClickListener(new OnClickListener() { 70 @Override 71 public void onClick(View v) { 72 if ((mTestIndex >= 0) && (mTestIndex < mTests.length)) { 73 mTests[mTestIndex].onNextClick(); 74 } 75 } 76 }); 77 78 // Don't allow pass until all tests complete. 79 findViewById(R.id.pass_button).setVisibility(View.GONE); 80 81 // Figure out if we are in a test or starting from the beginning. 82 if (savedInstanceState != null && savedInstanceState.containsKey(KEY_CURRENT_TEST)) { 83 mTestIndex = savedInstanceState.getInt(KEY_CURRENT_TEST); 84 } else { 85 mTestIndex = 0; 86 } 87 mTests[mTestIndex].run(); 88 }; 89 90 @Override onSaveInstanceState(Bundle outState)91 protected void onSaveInstanceState(Bundle outState) { 92 outState.putInt(KEY_CURRENT_TEST, mTestIndex); 93 } 94 95 @Override onBackPressed()96 public void onBackPressed() { 97 // Block back button so we can test screen pinning exit functionality. 98 // Users can still leave by pressing fail (or when done the pass) button. 99 } 100 show(int id)101 private void show(int id) { 102 TextView tv = new TextView(this); 103 tv.setPadding(10, 10, 10, 30); 104 tv.setText(id); 105 mInstructions.removeAllViews(); 106 mInstructions.addView(tv); 107 } 108 succeed()109 private void succeed() { 110 runOnUiThread(new Runnable() { 111 @Override 112 public void run() { 113 mTestIndex++; 114 if (mTestIndex < mTests.length) { 115 mTests[mTestIndex].run(); 116 } 117 } 118 }); 119 } 120 error(int errorId)121 private void error(int errorId) { 122 error(errorId, new Throwable()); 123 } 124 error(final int errorId, final Throwable cause)125 private void error(final int errorId, final Throwable cause) { 126 runOnUiThread(new Runnable() { 127 @Override 128 public void run() { 129 String error = getString(errorId); 130 Log.d(TAG, error, cause); 131 // No more instructions needed. 132 findViewById(R.id.instructions_group).setVisibility(View.GONE); 133 134 ((TextView) findViewById(R.id.error_text)).setText(error); 135 } 136 }); 137 } 138 139 // Verify we don't start in screen pinning. 140 private final Test mCheckStartedUnpinned = new Test(0) { 141 public void run() { 142 if (mActivityManager.isInLockTaskMode()) { 143 error(R.string.error_screen_already_pinned); 144 } else { 145 succeed(); 146 } 147 } 148 }; 149 150 // Start screen pinning by having the user click next then confirm it for us. 151 private final Test mCheckStartPinning = new Test(R.string.screen_pin_instructions) { 152 protected void onNextClick() { 153 startLockTask(); 154 succeed(); 155 } 156 }; 157 158 // Click next and check that we got pinned. 159 // Wait for the user to click next to verify that they got back from the prompt 160 // successfully. 161 private final Test mCheckIsPinned = new Test(R.string.screen_pin_check_pinned) { 162 protected void onNextClick() { 163 if (mActivityManager.isInLockTaskMode()) { 164 succeed(); 165 } else { 166 error(R.string.error_screen_pinning_did_not_start); 167 } 168 } 169 }; 170 171 // Tell user to try to leave. 172 private final Test mCheckTryLeave = new Test(R.string.screen_pin_no_exit) { 173 protected void onNextClick() { 174 if (mActivityManager.isInLockTaskMode()) { 175 succeed(); 176 } else { 177 error(R.string.error_screen_no_longer_pinned); 178 } 179 } 180 }; 181 182 // Verify that the user unpinned and it worked. 183 private final Test mCheckUnpin = new Test(R.string.screen_pin_exit) { 184 protected void onNextClick() { 185 if (!mActivityManager.isInLockTaskMode()) { 186 succeed(); 187 } else { 188 error(R.string.error_screen_pinning_did_not_exit); 189 } 190 } 191 }; 192 193 // Unpin from code and check that it worked. 194 private final Test mCheckUnpinFromCode = new Test(0) { 195 protected void run() { 196 if (!mActivityManager.isInLockTaskMode()) { 197 error(R.string.error_screen_pinning_did_not_start); 198 return; 199 } 200 stopLockTask(); 201 for (int retry = MAX_TASK_MODE_CHECK_COUNT; retry > 0; retry--) { 202 try { 203 Thread.sleep(TASK_MODE_CHECK_DELAY); 204 } catch (InterruptedException e) { 205 } 206 Log.d(TAG, "Check unpin ... " + retry); 207 if (!mActivityManager.isInLockTaskMode()) { 208 succeed(); 209 break; 210 } else if (retry == 1) { 211 error(R.string.error_screen_pinning_couldnt_exit); 212 } 213 } 214 }; 215 }; 216 217 private final Test mDone = new Test(R.string.screen_pinning_done) { 218 @Override 219 protected void run() { 220 super.run(); 221 // On test completion, hide "next" button, and show "pass" button 222 // instead. 223 mNextButton.setVisibility(View.GONE); 224 findViewById(R.id.pass_button).setVisibility(View.VISIBLE); 225 }; 226 }; 227 228 private abstract class Test { 229 private final int mResId; 230 Test(int showId)231 public Test(int showId) { 232 mResId = showId; 233 } 234 run()235 protected void run() { 236 showText(); 237 } 238 showText()239 public void showText() { 240 if (mResId == 0) { 241 return; 242 } 243 show(mResId); 244 } 245 onNextClick()246 protected void onNextClick() { 247 } 248 } 249 250 } 251