• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Manifest.permission.REAL_GET_TASKS;
20 import static android.os.Build.VERSION_CODES.Q;
21 
22 import android.app.ActivityManager;
23 import android.content.ComponentName;
24 
25 import com.android.bedstead.nene.TestApis;
26 import com.android.bedstead.nene.annotations.Experimental;
27 import com.android.bedstead.nene.exceptions.AdbException;
28 import com.android.bedstead.nene.exceptions.NeneException;
29 import com.android.bedstead.nene.packages.ComponentReference;
30 import com.android.bedstead.nene.permissions.PermissionContext;
31 import com.android.bedstead.nene.utils.ShellCommand;
32 import com.android.bedstead.nene.utils.Versions;
33 
34 import java.util.List;
35 
36 public final class Activities {
37 
38     public static final Activities sInstance = new Activities();
39 
Activities()40     private Activities() {
41     }
42 
43 
44     /**
45      * Wrap the given {@link NeneActivity} subclass to use Nene APIs.
46      */
wrap(Class<E> clazz, E activity)47     public <E extends NeneActivity> Activity<E> wrap(Class<E> clazz, E activity) {
48         return new Activity<>(activity, activity);
49     }
50 
51     /**
52      * Wrap the given {@link android.app.Activity} to use Nene APIs.
53      */
wrap(android.app.Activity activity)54     public LocalActivity wrap(android.app.Activity activity) {
55         return new LocalActivity(activity);
56     }
57 
58     /**
59      * Get the {@link ComponentReference} of the activity currently in the foreground.
60      */
61     @Experimental
foregroundActivity()62     public ComponentReference foregroundActivity() {
63         if (!Versions.meetsMinimumSdkVersionRequirement(Q)) {
64             return foregroundActivityPreQ();
65         }
66         try (PermissionContext p = TestApis.permissions().withPermission(REAL_GET_TASKS)) {
67             ActivityManager activityManager =
68                     TestApis.context().instrumentedContext().getSystemService(
69                             ActivityManager.class);
70             List<ActivityManager.RunningTaskInfo> runningTasks = activityManager.getRunningTasks(1);
71             if (runningTasks.isEmpty()) {
72                 return null;
73             }
74 
75             return new ComponentReference(runningTasks.get(0).topActivity);
76         }
77     }
78 
foregroundActivityPreQ()79     private ComponentReference foregroundActivityPreQ() {
80         try {
81             return ShellCommand.builder("dumpsys activity top")
82                     .executeAndParseOutput((dumpsysOutput) -> {
83                         // The final ACTIVITY is the one on top
84                         String[] activitySplits = dumpsysOutput.split("ACTIVITY ");
85                         String component = activitySplits[activitySplits.length - 1]
86                                 .split(" ", 2)[0];
87                         ComponentName componentName = ComponentName.unflattenFromString(component);
88                         return new ComponentReference(componentName);
89                     });
90         } catch (AdbException | RuntimeException e) {
91             throw new NeneException("Error getting foreground activity pre Q", e);
92         }
93     }
94 
95     /**
96      * Return the current state of task locking. The three possible outcomes
97      * are {@link ActivityManager#LOCK_TASK_MODE_NONE},
98      * {@link ActivityManager#LOCK_TASK_MODE_LOCKED}
99      * and {@link ActivityManager#LOCK_TASK_MODE_PINNED}.
100      */
101     @Experimental
getLockTaskModeState()102     public int getLockTaskModeState() {
103         ActivityManager activityManager =
104                 TestApis.context().instrumentedContext().getSystemService(
105                         ActivityManager.class);
106 
107         return activityManager.getLockTaskModeState();
108     }
109 }
110