Home | History | Annotate | Download | only in managedprovisioning
      1 /*
      2  * Copyright (C) 2017 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 
     17 package com.android.cts.verifier.managedprovisioning;
     18 
     19 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
     20 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
     21 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
     22 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
     23 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
     24 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
     25 import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
     26 
     27 import static com.android.cts.verifier.managedprovisioning.Utils.createInteractiveTestItem;
     28 
     29 import android.app.ActivityManager;
     30 import android.app.Notification;
     31 import android.app.NotificationChannel;
     32 import android.app.NotificationManager;
     33 import android.app.admin.DevicePolicyManager;
     34 import android.content.BroadcastReceiver;
     35 import android.content.ComponentName;
     36 import android.content.Context;
     37 import android.content.Intent;
     38 import android.content.IntentFilter;
     39 import android.database.DataSetObserver;
     40 import android.os.AsyncTask;
     41 import android.os.Bundle;
     42 import androidx.localbroadcastmanager.content.LocalBroadcastManager;
     43 import android.util.Log;
     44 import android.widget.Button;
     45 import android.widget.Toast;
     46 
     47 import com.android.cts.verifier.ArrayTestListAdapter;
     48 import com.android.cts.verifier.IntentDrivenTestActivity.ButtonInfo;
     49 import com.android.cts.verifier.PassFailButtons;
     50 import com.android.cts.verifier.R;
     51 import com.android.cts.verifier.TestListAdapter.TestListItem;
     52 import com.android.cts.verifier.TestResult;
     53 
     54 import java.util.concurrent.CountDownLatch;
     55 import java.util.concurrent.TimeUnit;
     56 
     57 /**
     58  * Tests for {@link DevicePolicyManager#setLockTaskFeatures(ComponentName, int)}.
     59  */
     60 public class LockTaskUiTestActivity extends PassFailButtons.TestListActivity {
     61 
     62     private static final String TAG = LockTaskUiTestActivity.class.getSimpleName();
     63 
     64     public static final String EXTRA_TEST_ID =
     65             "com.android.cts.verifier.managedprovisioning.extra.TEST_ID";
     66 
     67     /** Broadcast action sent by {@link DeviceAdminTestReceiver} when LockTask starts. */
     68     static final String ACTION_LOCK_TASK_STARTED =
     69             "com.android.cts.verifier.managedprovisioning.action.LOCK_TASK_STARTED";
     70     /** Broadcast action sent by {@link DeviceAdminTestReceiver} when LockTask stops. */
     71     static final String ACTION_LOCK_TASK_STOPPED =
     72             "com.android.cts.verifier.managedprovisioning.action.LOCK_TASK_STOPPED";
     73 
     74     private static final ComponentName ADMIN_RECEIVER =
     75             DeviceAdminTestReceiver.getReceiverComponentName();
     76     private static final String TEST_PACKAGE_NAME = "com.android.cts.verifier";
     77     private static final String ACTION_STOP_LOCK_TASK =
     78             "com.android.cts.verifier.managedprovisioning.action.STOP_LOCK_TASK";
     79 
     80     private static final String TEST_ID_DEFAULT = "lock-task-ui-default";
     81     private static final String TEST_ID_SYSTEM_INFO = "lock-task-ui-system-info";
     82     private static final String TEST_ID_NOTIFICATIONS = "lock-task-ui-notifications";
     83     private static final String TEST_ID_HOME = "lock-task-ui-home";
     84     private static final String TEST_ID_RECENTS = "lock-task-ui-recents";
     85     private static final String TEST_ID_GLOBAL_ACTIONS = "lock-task-ui-global-actions";
     86     private static final String TEST_ID_KEYGUARD = "lock-task-ui-keyguard";
     87     private static final String TEST_ID_STOP_LOCK_TASK = "lock-task-ui-stop-lock-task";
     88 
     89     private DevicePolicyManager mDpm;
     90     private ActivityManager mAm;
     91     private NotificationManager mNotifyMgr;
     92 
     93     private LockTaskStateChangedReceiver mStateChangedReceiver;
     94     private CountDownLatch mLockTaskStartedLatch;
     95     private CountDownLatch mLockTaskStoppedLatch;
     96 
     97     @Override
     98     protected void onCreate(Bundle savedInstanceState) {
     99         super.onCreate(savedInstanceState);
    100         setContentView(R.layout.device_owner_lock_task_ui);
    101         setPassFailButtonClickListeners();
    102 
    103         mDpm = getSystemService(DevicePolicyManager.class);
    104         mAm = getSystemService(ActivityManager.class);
    105         mNotifyMgr = getSystemService(NotificationManager.class);
    106 
    107         final ArrayTestListAdapter adapter = new ArrayTestListAdapter(this);
    108         addTestsToAdapter(adapter);
    109         adapter.registerDataSetObserver(new DataSetObserver() {
    110             @Override
    111             public void onChanged() {
    112                 updatePassButton();
    113             }
    114         });
    115         setTestListAdapter(adapter);
    116 
    117         Button startLockTaskButton = findViewById(R.id.start_lock_task_button);
    118         startLockTaskButton.setOnClickListener((view) -> startLockTaskMode());
    119 
    120         if (ACTION_STOP_LOCK_TASK.equals(getIntent().getAction())) {
    121             // This means we're started by the "stop LockTask mode" test activity (the last one in
    122             // the list) in order to stop LockTask.
    123             stopLockTaskMode();
    124         }
    125     }
    126 
    127     private void addTestsToAdapter(final ArrayTestListAdapter adapter) {
    128         adapter.add(createSetLockTaskFeaturesTest(
    129                 TEST_ID_DEFAULT,
    130                 LOCK_TASK_FEATURE_NONE,
    131                 R.string.device_owner_lock_task_ui_default_test,
    132                 R.string.device_owner_lock_task_ui_default_test_info));
    133 
    134         adapter.add(createSetLockTaskFeaturesTest(
    135                 TEST_ID_SYSTEM_INFO,
    136                 LOCK_TASK_FEATURE_SYSTEM_INFO,
    137                 R.string.device_owner_lock_task_ui_system_info_test,
    138                 R.string.device_owner_lock_task_ui_system_info_test_info));
    139 
    140         adapter.add(createSetLockTaskFeaturesTest(
    141                 TEST_ID_NOTIFICATIONS,
    142                 LOCK_TASK_FEATURE_HOME | LOCK_TASK_FEATURE_NOTIFICATIONS,
    143                 R.string.device_owner_lock_task_ui_notifications_test,
    144                 R.string.device_owner_lock_task_ui_notifications_test_info));
    145 
    146         adapter.add(createSetLockTaskFeaturesTest(
    147                 TEST_ID_HOME,
    148                 LOCK_TASK_FEATURE_HOME,
    149                 R.string.device_owner_lock_task_ui_home_test,
    150                 R.string.device_owner_lock_task_ui_home_test_info));
    151 
    152         adapter.add(createSetLockTaskFeaturesTest(
    153                 TEST_ID_RECENTS,
    154                 LOCK_TASK_FEATURE_HOME | LOCK_TASK_FEATURE_OVERVIEW,
    155                 R.string.device_owner_lock_task_ui_recents_test,
    156                 R.string.device_owner_lock_task_ui_recents_test_info));
    157 
    158         adapter.add(createSetLockTaskFeaturesTest(
    159                 TEST_ID_GLOBAL_ACTIONS,
    160                 LOCK_TASK_FEATURE_GLOBAL_ACTIONS,
    161                 R.string.device_owner_lock_task_ui_global_actions_test,
    162                 R.string.device_owner_lock_task_ui_global_actions_test_info));
    163 
    164         adapter.add(createSetLockTaskFeaturesTest(
    165                 TEST_ID_KEYGUARD,
    166                 LOCK_TASK_FEATURE_KEYGUARD,
    167                 R.string.device_owner_lock_task_ui_keyguard_test,
    168                 R.string.device_owner_lock_task_ui_keyguard_test_info));
    169 
    170         final Intent stopLockTaskIntent = new Intent(this, LockTaskUiTestActivity.class);
    171         stopLockTaskIntent.setAction(ACTION_STOP_LOCK_TASK);
    172         adapter.add(createInteractiveTestItem(this,
    173                 TEST_ID_STOP_LOCK_TASK,
    174                 R.string.device_owner_lock_task_ui_stop_lock_task_test,
    175                 R.string.device_owner_lock_task_ui_stop_lock_task_test_info,
    176                 new ButtonInfo(
    177                         R.string.device_owner_lock_task_ui_stop_lock_task_test,
    178                         stopLockTaskIntent
    179                 )));
    180     }
    181 
    182     /** Receives LockTask start/stop callbacks forwarded by {@link DeviceAdminTestReceiver}. */
    183     private final class LockTaskStateChangedReceiver extends BroadcastReceiver {
    184         @Override
    185         public void onReceive(Context context, Intent intent) {
    186             String action = intent.getAction();
    187             switch (action) {
    188                 case ACTION_LOCK_TASK_STARTED:
    189                     if (mLockTaskStartedLatch != null) {
    190                         mLockTaskStartedLatch.countDown();
    191                     }
    192                     break;
    193                 case ACTION_LOCK_TASK_STOPPED:
    194                     if (mLockTaskStoppedLatch != null) {
    195                         mLockTaskStoppedLatch.countDown();
    196                     }
    197                     break;
    198             }
    199         }
    200     }
    201 
    202     @Override
    203     protected void onResume() {
    204         super.onResume();
    205         mStateChangedReceiver = new LockTaskStateChangedReceiver();
    206         final IntentFilter filter = new IntentFilter();
    207         filter.addAction(ACTION_LOCK_TASK_STARTED);
    208         filter.addAction(ACTION_LOCK_TASK_STOPPED);
    209         LocalBroadcastManager.getInstance(this).registerReceiver(mStateChangedReceiver, filter);
    210     }
    211 
    212     @Override
    213     protected void onPause() {
    214         if (mStateChangedReceiver != null) {
    215             LocalBroadcastManager.getInstance(this).unregisterReceiver(mStateChangedReceiver);
    216             mStateChangedReceiver = null;
    217         }
    218         super.onPause();
    219     }
    220 
    221     /**
    222      * Starts LockTask mode and waits for callback from {@link DeviceAdminTestReceiver} to confirm
    223      * LockTask has started successfully. If the callback isn't received, the entire test will be
    224      * marked as failed.
    225      *
    226      * @see LockTaskStateChangedReceiver
    227      */
    228     private void startLockTaskMode() {
    229         if (mAm.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_LOCKED) {
    230             return;
    231         }
    232 
    233         mLockTaskStartedLatch = new CountDownLatch(1);
    234         try {
    235             mDpm.setLockTaskPackages(ADMIN_RECEIVER, new String[] {TEST_PACKAGE_NAME});
    236             mDpm.setLockTaskFeatures(ADMIN_RECEIVER, LOCK_TASK_FEATURE_NONE);
    237             startLockTask();
    238 
    239             new CheckLockTaskStateTask() {
    240                 @Override
    241                 protected void onPostExecute(Boolean success) {
    242                     if (success) {
    243                         issueTestNotification();
    244                     } else {
    245                         notifyFailure(getTestId(), "Failed to start LockTask mode");
    246                     }
    247                 }
    248             }.execute(mLockTaskStartedLatch);
    249         } catch (SecurityException e) {
    250             Log.e(TAG, e.getMessage(), e);
    251             Toast.makeText(this, "Failed to run test. Did you set up device owner correctly?",
    252                     Toast.LENGTH_SHORT).show();
    253         }
    254     }
    255 
    256     /**
    257      * Stops LockTask mode and waits for callback from {@link DeviceAdminTestReceiver} to confirm
    258      * LockTask has stopped successfully. If the callback isn't received, the "Stop LockTask mode"
    259      * test case will be marked as failed.
    260      *
    261      * Note that we {@link #finish()} this activity here, since it's started by the "Stop LockTask
    262      * mode" test activity, and shouldn't be exposed to the tester once its job is done.
    263      *
    264      * @see LockTaskStateChangedReceiver
    265      */
    266     private void stopLockTaskMode() {
    267         if (mAm.getLockTaskModeState() == ActivityManager.LOCK_TASK_MODE_NONE) {
    268             finish();
    269             return;
    270         }
    271 
    272         mLockTaskStoppedLatch = new CountDownLatch(1);
    273         try {
    274             stopLockTask();
    275 
    276             new CheckLockTaskStateTask() {
    277                 @Override
    278                 protected void onPostExecute(Boolean success) {
    279                     if (!success) {
    280                         notifyFailure(TEST_ID_STOP_LOCK_TASK, "Failed to stop LockTask mode");
    281                     }
    282                     cancelTestNotification();
    283                     mDpm.setLockTaskFeatures(ADMIN_RECEIVER, LOCK_TASK_FEATURE_NONE);
    284                     mDpm.setLockTaskPackages(ADMIN_RECEIVER, new String[] {});
    285                     LockTaskUiTestActivity.this.finish();
    286                 }
    287             }.execute(mLockTaskStoppedLatch);
    288         } catch (SecurityException e) {
    289             Log.e(TAG, e.getMessage(), e);
    290             Toast.makeText(this, "Failed to finish test. Did you set up device owner correctly?",
    291                     Toast.LENGTH_SHORT).show();
    292         }
    293     }
    294 
    295     private abstract class CheckLockTaskStateTask extends AsyncTask<CountDownLatch, Void, Boolean> {
    296         @Override
    297         protected Boolean doInBackground(CountDownLatch... latches) {
    298             if (latches.length > 0 && latches[0] != null) {
    299                 try {
    300                     return latches[0].await(1, TimeUnit.SECONDS);
    301                 } catch (InterruptedException e) {
    302                     // Fall through
    303                 }
    304             }
    305             return false;
    306         }
    307 
    308         @Override
    309         protected abstract void onPostExecute(Boolean success);
    310     }
    311 
    312     private void notifyFailure(String testId, String message) {
    313         Log.e(TAG, message);
    314         Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    315         TestResult.setFailedResult(this, testId, message);
    316     }
    317 
    318     private void issueTestNotification() {
    319         String channelId = getTestId();
    320         if (mNotifyMgr.getNotificationChannel(channelId) == null) {
    321             NotificationChannel channel = new NotificationChannel(
    322                     channelId, getTestId(), NotificationManager.IMPORTANCE_HIGH);
    323             mNotifyMgr.createNotificationChannel(channel);
    324         }
    325 
    326         Notification note = new Notification.Builder(this, channelId)
    327                 .setContentTitle(getString(R.string.device_owner_lock_task_ui_test))
    328                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
    329                 .setOngoing(true)
    330                 .build();
    331 
    332         mNotifyMgr.notify(0, note);
    333     }
    334 
    335     private void cancelTestNotification() {
    336         mNotifyMgr.cancelAll();
    337     }
    338 
    339     private TestListItem createSetLockTaskFeaturesTest(String testId, int featureFlags,
    340             int titleResId, int detailResId) {
    341         final Intent commandIntent = new Intent(CommandReceiverActivity.ACTION_EXECUTE_COMMAND);
    342         commandIntent.putExtra(CommandReceiverActivity.EXTRA_COMMAND,
    343                 CommandReceiverActivity.COMMAND_SET_LOCK_TASK_FEATURES);
    344         commandIntent.putExtra(CommandReceiverActivity.EXTRA_VALUE, featureFlags);
    345 
    346         return createInteractiveTestItem(this, testId, titleResId, detailResId,
    347                 new ButtonInfo(titleResId, commandIntent));
    348     }
    349 
    350     @Override
    351     public String getTestId() {
    352         return getIntent().getStringExtra(EXTRA_TEST_ID);
    353     }
    354 }
    355