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