1 /* 2 * Copyright (C) 2021 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.devicepolicy; 17 18 import android.content.BroadcastReceiver; 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.IntentFilter; 22 import android.util.Log; 23 24 import com.android.bedstead.dpmwrapper.TestAppHelper; 25 26 import junit.framework.AssertionFailedError; 27 28 import java.util.concurrent.LinkedBlockingQueue; 29 import java.util.concurrent.TimeUnit; 30 31 //TODO(b/174859111): move to automotive-only section 32 /** 33 * Helper class used by test apps to get the safety event received by the device owner's 34 * {@link android.app.admin.DeviceAdminReceiver}. 35 */ 36 public final class OperationSafetyChangedCallback { 37 38 private static final String TAG = OperationSafetyChangedCallback.class.getSimpleName(); 39 40 private static final String ACTION_STATE_CHANGED = "operation_safety_state_changed"; 41 private static final String EXTRA_REASON = "reason"; 42 private static final String EXTRA_IS_SAFE = "is_safe"; 43 44 private static final long TIMEOUT_MS = 50_000; 45 46 private final LinkedBlockingQueue<OperationSafetyChangedEvent> mEvents = 47 new LinkedBlockingQueue<>(); 48 49 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 50 @Override 51 public void onReceive(Context context, Intent intent) { 52 String action = intent.getAction(); 53 if (!ACTION_STATE_CHANGED.equals(action)) { 54 Log.e(TAG, "Invalid action " + action + " on intent " + intent); 55 return; 56 } 57 if (!intent.hasExtra(EXTRA_REASON)) { 58 Log.e(TAG, "No " + EXTRA_REASON + " extra on intent " + intent); 59 return; 60 } 61 if (!intent.hasExtra(EXTRA_IS_SAFE)) { 62 Log.e(TAG, "No " + EXTRA_IS_SAFE + " extra on intent " + intent); 63 return; 64 } 65 OperationSafetyChangedEvent event = new OperationSafetyChangedEvent( 66 intent.getIntExtra(EXTRA_REASON, 42), 67 intent.getBooleanExtra(EXTRA_IS_SAFE, false)); 68 Log.d(TAG, "Received intent with event " + event + " on user " + context.getUserId()); 69 mEvents.offer(event); 70 } 71 }; 72 OperationSafetyChangedCallback()73 private OperationSafetyChangedCallback() {} 74 75 /** 76 * Creates and registers a callback in the given context. 77 */ register(Context context)78 public static OperationSafetyChangedCallback register(Context context) { 79 Log.d(TAG, "Registering " + ACTION_STATE_CHANGED + " on user " + context.getUserId()); 80 OperationSafetyChangedCallback callback = new OperationSafetyChangedCallback(); 81 TestAppHelper.registerTestCaseReceiver(context, callback.mReceiver, 82 new IntentFilter(ACTION_STATE_CHANGED)); 83 return callback; 84 } 85 86 /** 87 * Unregister this callback in the given context. 88 */ unregister(Context context)89 public void unregister(Context context) { 90 Log.d(TAG, "Unregistering " + mReceiver + " on user " + context.getUserId()); 91 TestAppHelper.unregisterTestCaseReceiver(context, mReceiver); 92 } 93 94 /** 95 * Gets the intent for the given event. 96 */ intentFor(OperationSafetyChangedEvent event)97 public static Intent intentFor(OperationSafetyChangedEvent event) { 98 return new Intent(ACTION_STATE_CHANGED) 99 .putExtra(EXTRA_REASON, event.reason) 100 .putExtra(EXTRA_IS_SAFE, event.isSafe); 101 } 102 103 /** 104 * Gets next event or fail. 105 */ getNextEvent()106 public OperationSafetyChangedEvent getNextEvent() { 107 OperationSafetyChangedEvent event = null; 108 try { 109 event = mEvents.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS); 110 } catch (InterruptedException e) { 111 String msg = "interrupted waiting for event"; 112 Log.e(TAG, msg, e); 113 Thread.currentThread().interrupt(); 114 throw new AssertionFailedError(msg); 115 } 116 if (event == null) { 117 String msg = "didn't receive an OperationSafetyChangedEvent in " 118 + TIMEOUT_MS + "ms on " + this; 119 Log.e(TAG, msg); 120 throw new AssertionFailedError(msg); 121 } 122 return event; 123 } 124 125 @Override toString()126 public String toString() { 127 return "OperationSafetyChangedCallback[events=" + mEvents + "]"; 128 } 129 } 130