1/* 2 * Copyright (C) 2012 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 17package com.android.keyguard.test; 18 19import com.android.internal.policy.IKeyguardShowCallback; 20import com.android.internal.policy.IKeyguardExitCallback; 21import com.android.internal.policy.IKeyguardService; 22 23import android.app.Activity; 24import android.app.AlertDialog; 25import android.app.admin.DevicePolicyManager; 26import android.content.ComponentName; 27import android.content.Context; 28import android.content.Intent; 29import android.content.ServiceConnection; 30import android.os.Bundle; 31import android.os.Handler; 32import android.os.IBinder; 33import android.os.RemoteException; 34import android.os.SystemClock; 35import android.provider.Settings; 36import android.util.Log; 37import android.view.Menu; 38import android.view.MenuInflater; 39import android.view.MenuItem; 40import android.view.View; 41import android.view.View.OnClickListener; 42import android.view.WindowManagerPolicy; 43 44import com.android.internal.widget.LockPatternUtils; 45import com.android.internal.widget.LockPatternView.Cell; 46 47import java.util.List; 48 49public class KeyguardTestActivity extends Activity implements OnClickListener { 50 private static final String KEYGUARD_PACKAGE = "com.android.keyguard"; 51 private static final String KEYGUARD_CLASS = "com.android.keyguard.KeyguardService"; 52 private static final String TAG = "LockScreenTestActivity"; 53 private static final int MODE_NONE = 0; 54 private static final int MODE_PIN = 1; 55 private static final int MODE_PASSWORD = 2; 56 private static final int MODE_PATTERN = 3; 57 private static final int MODE_SIM_PIN = 4; 58 private static final int MODE_SIM_PUK = 5; 59 private static final String SECURITY_MODE = "security_mode"; 60 Handler mHandler = new Handler(); 61 62 IKeyguardService mService = null; 63 64 KeyguardShowCallback mKeyguardShowCallback = new KeyguardShowCallback(); 65 KeyguardExitCallback mKeyguardExitCallback = new KeyguardExitCallback(); 66 67 RemoteServiceConnection mConnection; 68 private boolean mSentSystemReady; 69 70 class KeyguardShowCallback extends IKeyguardShowCallback.Stub { 71 72 @Override 73 public void onShown(IBinder windowToken) throws RemoteException { 74 Log.v(TAG, "Keyguard is shown, windowToken = " + windowToken); 75 } 76 } 77 78 class KeyguardExitCallback extends IKeyguardExitCallback.Stub { 79 80 @Override 81 public void onKeyguardExitResult(final boolean success) throws RemoteException { 82 mHandler.post(new Runnable() { 83 @Override 84 public void run() { 85 new AlertDialog.Builder(KeyguardTestActivity.this) 86 .setMessage("Result: " + success) 87 .setPositiveButton("OK", null) 88 .show(); 89 } 90 }); 91 } 92 }; 93 94 private class RemoteServiceConnection implements ServiceConnection { 95 public void onServiceConnected(ComponentName className, IBinder service) { 96 Log.v(TAG, "onServiceConnected()"); 97 mService = IKeyguardService.Stub.asInterface(service); 98 try { 99 mService.asBinder().linkToDeath(new IBinder.DeathRecipient() { 100 @Override 101 public void binderDied() { 102 new AlertDialog.Builder(KeyguardTestActivity.this) 103 .setMessage("Oops! Keygued died") 104 .setPositiveButton("OK", null) 105 .show(); 106 } 107 }, 0); 108 } catch (RemoteException e) { 109 Log.w(TAG, "Couldn't linkToDeath"); 110 e.printStackTrace(); 111 } 112// try { 113// mService.onSystemReady(); 114// } catch (RemoteException e) { 115// Log.v(TAG, "Remote service died trying to call onSystemReady"); 116// e.printStackTrace(); 117// } 118 } 119 120 public void onServiceDisconnected(ComponentName className) { 121 Log.v(TAG, "onServiceDisconnected()"); 122 mService = null; 123 } 124 }; 125 126 private void bindService() { 127 if (mConnection == null) { 128 mConnection = new RemoteServiceConnection(); 129 Intent intent = new Intent(); 130 intent.setClassName(KEYGUARD_PACKAGE, KEYGUARD_CLASS); 131 Log.v(TAG, "BINDING SERVICE: " + KEYGUARD_CLASS); 132 if (!bindService(intent, mConnection, Context.BIND_AUTO_CREATE)) { 133 Log.v(TAG, "FAILED TO BIND TO KEYGUARD!"); 134 } 135 } else { 136 Log.v(TAG, "Service already bound"); 137 } 138 } 139 140 @Override 141 protected void onCreate(Bundle savedInstanceState) { 142 super.onCreate(savedInstanceState); 143 setContentView(R.layout.keyguard_test_activity); 144 final int[] buttons = { 145 R.id.on_screen_turned_off, R.id.on_screen_turned_on, 146 R.id.do_keyguard, R.id.verify_unlock 147 }; 148 for (int i = 0; i < buttons.length; i++) { 149 findViewById(buttons[i]).setOnClickListener(this); 150 } 151 Log.v(TAG, "Binding service..."); 152 bindService(); 153 } 154 155 @Override 156 protected void onSaveInstanceState(Bundle outState) { 157 super.onSaveInstanceState(outState); 158 outState.putInt(SECURITY_MODE, mSecurityMode); 159 } 160 161 @Override 162 protected void onRestoreInstanceState(Bundle savedInstanceState) { 163 super.onRestoreInstanceState(savedInstanceState); 164 setMode(savedInstanceState.getInt(SECURITY_MODE)); 165 } 166 167// TODO: Find a secure way to inject mock into keyguard... 168// @Override 169// public boolean onCreateOptionsMenu(Menu menu) { 170// MenuInflater inflater = getMenuInflater(); 171// inflater.inflate(R.menu.optionmenu, menu); 172// return true; 173// } 174 175 private void setMode(int mode) { 176 mTestSimPin = false; 177 mTestSimPuk = false; 178 mLockPasswordEnabled = false; 179 mLockPatternEnabled = false; 180 switch(mode) { 181 case MODE_NONE: 182 mSecurityModeMock = DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; 183 break; 184 case MODE_PIN: 185 mSecurityModeMock = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; 186 mLockPasswordEnabled = true; 187 break; 188 case MODE_PASSWORD: 189 mSecurityModeMock = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC; 190 mLockPasswordEnabled = true; 191 break; 192 case MODE_PATTERN: 193 mSecurityModeMock = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 194 mLockPatternEnabled = true; 195 break; 196 case MODE_SIM_PIN: 197 mTestSimPin = true; 198 break; 199 case MODE_SIM_PUK: 200 mTestSimPuk = true; 201 break; 202 } 203 mSecurityMode = mode; 204 } 205 206 @Override 207 public boolean onOptionsItemSelected(MenuItem item) { 208 // Handle item selection 209 switch (item.getItemId()) { 210 case R.id.none_menu_item: 211 setMode(MODE_NONE); 212 break; 213 case R.id.pin_menu_item: 214 setMode(MODE_PIN); 215 break; 216 case R.id.password_menu_item: 217 setMode(MODE_PASSWORD); 218 break; 219 case R.id.pattern_menu_item: 220 setMode(MODE_PATTERN); 221 break; 222 case R.id.sim_pin_menu_item: 223 setMode(MODE_SIM_PIN); 224 break; 225 case R.id.sim_puk_menu_item: 226 setMode(MODE_SIM_PUK); 227 break; 228 case R.id.add_widget_item: 229 startWidgetPicker(); 230 break; 231 default: 232 return super.onOptionsItemSelected(item); 233 } 234 try { 235 mService.doKeyguardTimeout(null); 236 } catch (RemoteException e) { 237 Log.e(TAG, "Remote service died"); 238 e.printStackTrace(); 239 } 240 return true; 241 } 242 243 private void startWidgetPicker() { 244 startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS)); 245 } 246 247 @Override 248 public void onClick(View v) { 249 try { 250 switch (v.getId()) { 251 case R.id.on_screen_turned_on: 252 mService.onScreenTurnedOn(mKeyguardShowCallback); 253 break; 254 case R.id.on_screen_turned_off: 255 mService.onScreenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER); 256 break; 257 case R.id.do_keyguard: 258 if (!mSentSystemReady) { 259 mSentSystemReady = true; 260 mService.onSystemReady(); 261 } 262 mService.doKeyguardTimeout(null); 263 break; 264 case R.id.verify_unlock: 265 mService.doKeyguardTimeout(null); 266 // Wait for keyguard to lock and then try this... 267 mHandler.postDelayed(new Runnable() { 268 @Override 269 public void run() { 270 try { 271 mService.verifyUnlock(mKeyguardExitCallback); 272 } catch (RemoteException e) { 273 Log.e(TAG, "Failed verifyUnlock()", e); 274 } 275 } 276 }, 5000); 277 break; 278 } 279 } catch (RemoteException e) { 280 Log.e(TAG, "onClick(): Failed due to remote exeption", e); 281 } 282 } 283 284 @Override 285 protected void onPause() { 286 super.onPause(); 287 try { 288 if (mService != null) { 289 mService.setHidden(true); 290 } 291 } catch (RemoteException e) { 292 Log.e(TAG, "Remote service died"); 293 e.printStackTrace(); 294 } 295 } 296 297 protected void onResume() { 298 super.onResume(); 299 try { 300 if (mService != null) { 301 mService.setHidden(false); 302 } 303 } catch (RemoteException e) { 304 Log.e(TAG, "Remote service died"); 305 e.printStackTrace(); 306 } 307 } 308 309 public int mSecurityModeMock; 310 private boolean mTestSimPin; 311 private boolean mTestSimPuk; 312 private boolean mLockPasswordEnabled; 313 public boolean mLockPatternEnabled; 314 private int mSecurityMode; 315 316 class LockPatternUtilsMock extends LockPatternUtils { 317 private long mDeadline; 318 public LockPatternUtilsMock(Context context) { 319 super(context); 320 } 321 322 @Override 323 public boolean checkPattern(List<Cell> pattern) { 324 return pattern.size() > 4; 325 } 326 327 @Override 328 public boolean checkPassword(String password) { 329 return password.length() > 4; 330 } 331 @Override 332 public long setLockoutAttemptDeadline() { 333 final long deadline = SystemClock.elapsedRealtime() + FAILED_ATTEMPT_TIMEOUT_MS; 334 mDeadline = deadline; 335 return deadline; 336 } 337 @Override 338 public boolean isLockScreenDisabled() { 339 return false; 340 } 341 @Override 342 public long getLockoutAttemptDeadline() { 343 return mDeadline; 344 } 345 @Override 346 public void reportFailedPasswordAttempt() { 347 // Ignored 348 } 349 @Override 350 public void reportSuccessfulPasswordAttempt() { 351 // Ignored 352 } 353 @Override 354 public boolean isLockPatternEnabled() { 355 return mLockPatternEnabled; 356 } 357 358 @Override 359 public boolean isLockPasswordEnabled() { 360 return mLockPasswordEnabled; 361 } 362 363 @Override 364 public int getKeyguardStoredPasswordQuality() { 365 return mSecurityModeMock; 366 } 367 368 public boolean isSecure() { 369 return mLockPatternEnabled || mLockPasswordEnabled || mTestSimPin || mTestSimPuk; 370 } 371 372 } 373} 374