1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 package com.android.launcher3.util.rule;
17 
18 import static androidx.test.InstrumentationRegistry.getInstrumentation;
19 
20 import static com.android.launcher3.tapl.TestHelpers.getLauncherInMyProcess;
21 
22 import android.content.ComponentName;
23 import android.content.pm.ActivityInfo;
24 
25 import androidx.annotation.Nullable;
26 import androidx.test.InstrumentationRegistry;
27 import androidx.test.uiautomator.UiDevice;
28 
29 import com.android.systemui.shared.system.PackageManagerWrapper;
30 
31 import org.junit.Assert;
32 import org.junit.rules.TestRule;
33 import org.junit.runner.Description;
34 import org.junit.runners.model.Statement;
35 
36 import java.util.ArrayList;
37 
38 /**
39  * Test rule which executes a shell command at the start of the test.
40  */
41 public class ShellCommandRule implements TestRule {
42 
43     private final String mCmd;
44     private final String mRevertCommand;
45     private final boolean mCheckSuccess;
46     private final Runnable mAdditionalChecks;
47 
ShellCommandRule(String cmd, @Nullable String revertCommand, boolean checkSuccess, Runnable additionalChecks)48     public ShellCommandRule(String cmd, @Nullable String revertCommand, boolean checkSuccess,
49             Runnable additionalChecks) {
50         mCmd = cmd;
51         mRevertCommand = revertCommand;
52         mCheckSuccess = checkSuccess;
53         mAdditionalChecks = additionalChecks;
54     }
55 
ShellCommandRule(String cmd, @Nullable String revertCommand)56     public ShellCommandRule(String cmd, @Nullable String revertCommand) {
57         this(cmd, revertCommand, false, null);
58     }
59 
60     @Override
apply(Statement base, Description description)61     public Statement apply(Statement base, Description description) {
62         return new Statement() {
63             @Override
64             public void evaluate() throws Throwable {
65                 final String result =
66                         UiDevice.getInstance(getInstrumentation()).executeShellCommand(mCmd);
67                 if (mCheckSuccess) {
68                     Assert.assertTrue(
69                             "Failed command: " + mCmd + ", result: " + result,
70                             "Success".equals(result.replaceAll("\\s", "")));
71                 }
72                 if (mAdditionalChecks != null) mAdditionalChecks.run();
73                 try {
74                     base.evaluate();
75                 } finally {
76                     if (mRevertCommand != null) {
77                         final String revertResult = UiDevice.getInstance(
78                                 getInstrumentation()).executeShellCommand(
79                                 mRevertCommand);
80                         if (mCheckSuccess) {
81                             Assert.assertTrue(
82                                     "Failed command: " + mRevertCommand
83                                             + ", result: " + revertResult,
84                                     "Success".equals(result.replaceAll("\\s", "")));
85                         }
86                     }
87                 }
88             }
89         };
90     }
91 
92     /**
93      * Grants the launcher permission to bind widgets.
94      */
95     public static ShellCommandRule grantWidgetBind() {
96         return new ShellCommandRule("appwidget grantbind --package "
97                 + InstrumentationRegistry.getTargetContext().getPackageName(), null);
98     }
99 
100     /**
101      * Sets the target launcher as default launcher.
102      */
103     public static ShellCommandRule setDefaultLauncher() {
104         final ActivityInfo launcher = getLauncherInMyProcess();
105         return new ShellCommandRule(getLauncherCommand(launcher), null, true, () ->
106                 Assert.assertEquals("Setting default launcher failed",
107                         new ComponentName(launcher.packageName, launcher.name)
108                                 .flattenToString(),
109                         PackageManagerWrapper.getInstance().getHomeActivities(new ArrayList<>())
110                                 .flattenToString()));
111     }
112 
113     public static String getLauncherCommand(ActivityInfo launcher) {
114         return "cmd package set-home-activity " +
115                 new ComponentName(launcher.packageName, launcher.name).flattenToString();
116     }
117 
118     /**
119      * Disables heads up notification for the duration of the test
120      */
121     public static ShellCommandRule disableHeadsUpNotification() {
122         return new ShellCommandRule("settings put global heads_up_notifications_enabled 0",
123                 "settings put global heads_up_notifications_enabled 1");
124     }
125 }
126