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 
17 package com.android.bedstead.nene.activities;
18 
19 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
20 
21 import android.content.Intent;
22 import android.util.Log;
23 
24 import com.android.bedstead.nene.TestApis;
25 import com.android.bedstead.nene.annotations.Experimental;
26 import com.android.bedstead.nene.packages.ComponentReference;
27 import com.android.bedstead.nene.utils.Poll;
28 
29 /**
30  * A wrapper around a specific Activity instance.
31  */
32 @Experimental
33 public class Activity<E> {
34 
35     private static final String TAG =  "BedsteadActivityWrapper";
36 
37     /*
38      * Note that methods in this class must not rely on the activity existing within the current
39      * process. These APIs must support activities which exist in any process (and they can be
40      * interacted with using the {@link NeneActivity} interface.
41      *
42      * If an API is only suitable for activies in the current process, that API should be added to
43      * {@link LocalActivity}.
44      */
45 
46     private final E mActivityInstance;
47     private final NeneActivity mActivity;
48 
Activity(E activityInstance, NeneActivity activity)49     Activity(E activityInstance, NeneActivity activity) {
50         mActivityInstance = activityInstance;
51         mActivity = activity;
52     }
53 
54     /**
55      * Calls {@link android.app.Activity#startLockTask()} and blocks until the activity has entered
56      * lock task mode.
57      */
58     @Experimental
startLockTask()59     public void startLockTask() {
60         Log.d(TAG, "startLockTask() on " + mActivity);
61         mActivity.startLockTask();
62 
63         // TODO(scottjonathan): What if we're already in lock task mode when we start it here?
64         //  find another thing to poll on
65         Poll.forValue("Lock task mode state", () -> TestApis.activities().getLockTaskModeState())
66                 .toNotBeEqualTo(LOCK_TASK_MODE_NONE)
67                 .errorOnFail()
68                 .await();
69     }
70 
71     /**
72      * Calls {@link android.app.Activity#stopLockTask()} and blocks until the activity has exited
73      * lock task mode.
74      */
75     @Experimental
stopLockTask()76     public void stopLockTask() {
77         Log.d(TAG, "stopLockTask() on " + mActivity);
78         mActivity.stopLockTask();
79 
80         // TODO(scottjonathan): What if we're already in lock task mode when we start it here?
81         //  find another thing to poll
82         Poll.forValue("Lock task mode state", () -> TestApis.activities().getLockTaskModeState())
83                 .toBeEqualTo(LOCK_TASK_MODE_NONE)
84                 .errorOnFail()
85                 .await();
86     }
87 
88     /**
89      * Calls {@link android.app.Activity#startActivity(Intent)} and blocks until the activity has
90      * started.
91      *
92      * <p>If a specific component is specified, this will block until that component is in the
93      * foreground. Otherwise, it will block only until the foreground activity has changed.
94      */
95     @Experimental
startActivity(Intent intent)96     public void startActivity(Intent intent) {
97         Log.d(TAG, "startActivity(): " + intent);
98         if (intent.getComponent() == null) {
99             ComponentReference startActivity = TestApis.activities().foregroundActivity();
100             mActivity.startActivity(intent);
101             Poll.forValue("Foreground activity", () -> TestApis.activities().foregroundActivity())
102                     .toNotBeEqualTo(startActivity)
103                     .errorOnFail()
104                     .await();
105         } else {
106             mActivity.startActivity(intent);
107             ComponentReference component = new ComponentReference(intent.getComponent());
108             Poll.forValue("Foreground activity", () -> TestApis.activities().foregroundActivity())
109                     .toBeEqualTo(component)
110                     .errorOnFail()
111                     .await();
112         }
113     }
114 
115     /**
116      * Gets the original activity to make calls on directly.
117      */
activity()118     public E activity() {
119         return mActivityInstance;
120     }
121 }
122