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 android.cts.statsdatom.apphibernation;
18 
19 import com.android.tradefed.util.RunUtil;
20 import static com.google.common.truth.Truth.assertThat;
21 
22 import android.cts.statsdatom.lib.AtomTestUtils;
23 import android.cts.statsdatom.lib.ConfigUtils;
24 import android.cts.statsdatom.lib.DeviceUtils;
25 import android.cts.statsdatom.lib.ReportUtils;
26 
27 import com.android.os.AtomsProto;
28 import com.android.os.StatsLog;
29 import com.android.tradefed.build.IBuildInfo;
30 import com.android.tradefed.testtype.DeviceTestCase;
31 import com.android.tradefed.testtype.IBuildReceiver;
32 
33 import java.util.List;
34 
35 public class AppHibernationStatsTest extends DeviceTestCase implements IBuildReceiver {
36     private static final String CMD_APP_HIBERNATION_SET_STATE =
37             "cmd app_hibernation set-state %s %s %s";
38     private static final String CMD_ENABLE_APP_HIBERNATION =
39             "device_config put app_hibernation app_hibernation_enabled true";
40     private static final String GLOBAL_OPTION = "--global";
41     private IBuildInfo mCtsBuild;
42 
43     @Override
setUp()44     protected void setUp() throws Exception {
45         super.setUp();
46         assertThat(mCtsBuild).isNotNull();
47         ConfigUtils.removeConfig(getDevice());
48         ReportUtils.clearReports(getDevice());
49         DeviceUtils.installStatsdTestApp(getDevice(), mCtsBuild);
50         getDevice().executeShellCommand(CMD_ENABLE_APP_HIBERNATION);
51         RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG);
52     }
53 
54     @Override
tearDown()55     protected void tearDown() throws Exception {
56         ConfigUtils.removeConfig(getDevice());
57         ReportUtils.clearReports(getDevice());
58         DeviceUtils.uninstallStatsdTestApp(getDevice());
59         super.tearDown();
60     }
61 
62     @Override
setBuild(IBuildInfo buildInfo)63     public void setBuild(IBuildInfo buildInfo) {
64         mCtsBuild = buildInfo;
65     }
66 
testUserLevelAppHibernationStateChanged_fromNotHibernatingToHibernating()67     public void testUserLevelAppHibernationStateChanged_fromNotHibernatingToHibernating()
68             throws Exception {
69         getDevice().executeShellCommand(
70                 getHibernationCommand(DeviceUtils.STATSD_ATOM_TEST_PKG,
71                         /* isGlobal */ false, /* isHibernating */ false));
72         ConfigUtils.uploadConfigForPushedAtomWithUid(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
73                 AtomsProto.Atom.USER_LEVEL_HIBERNATION_STATE_CHANGED_FIELD_NUMBER,
74                 /*uidInAttributionChain=*/false);
75 
76         getDevice().executeShellCommand(
77                 getHibernationCommand(DeviceUtils.STATSD_ATOM_TEST_PKG,
78                         /* isGlobal */ false, /* isHibernating */ true));
79 
80         // Sorted list of events in order in which they occurred.
81         final List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
82         assertThat(data.size()).isAtLeast(1);
83         assertUserLevelHibernationStateChangedEvent(data, /* isHibernating */ true,
84                 getDevice().getCurrentUser());
85     }
86 
testUserLevelAppHibernationStateChanged_fromHibernatingToNotHibernating()87     public void testUserLevelAppHibernationStateChanged_fromHibernatingToNotHibernating()
88             throws Exception {
89         getDevice().executeShellCommand(
90                 getHibernationCommand(DeviceUtils.STATSD_ATOM_TEST_PKG,
91                         /* isGlobal */ false, /* isHibernating */ true));
92         ConfigUtils.uploadConfigForPushedAtomWithUid(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
93                 AtomsProto.Atom.USER_LEVEL_HIBERNATION_STATE_CHANGED_FIELD_NUMBER,
94                 /*uidInAttributionChain=*/false);
95 
96         getDevice().executeShellCommand(
97                 getHibernationCommand(DeviceUtils.STATSD_ATOM_TEST_PKG,
98                         /* isGlobal */ false, /* isHibernating */ false));
99 
100         // Sorted list of events in order in which they occurred.
101         final List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
102         assertThat(data.size()).isAtLeast(1);
103         assertUserLevelHibernationStateChangedEvent(data, /* isHibernating */ false,
104                 getDevice().getCurrentUser());
105     }
106 
testUserLevelHibernatedApps()107     public void testUserLevelHibernatedApps() throws Exception {
108         ConfigUtils.uploadConfigForPulledAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
109                 AtomsProto.Atom.USER_LEVEL_HIBERNATED_APPS_FIELD_NUMBER);
110         getDevice().executeShellCommand(
111                 getHibernationCommand(DeviceUtils.STATSD_ATOM_TEST_PKG,
112                         /* isGlobal */ false, /* isHibernating */ true));
113 
114         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice());
115         RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG);
116 
117         final List<AtomsProto.Atom> atoms = ReportUtils.getGaugeMetricAtoms(getDevice());
118         final int userId = getDevice().getCurrentUser();
119         for (AtomsProto.Atom atom : atoms) {
120             AtomsProto.UserLevelHibernatedApps apps = atom.getUserLevelHibernatedApps();
121             if (apps.getUserId() == userId) {
122                 assertThat(apps.getHibernatedAppCount()).isAtLeast(1);
123                 return;
124             }
125         }
126         fail(String.format("Did not find a matching atom for user %d", userId));
127     }
128 
testGlobalHibernatedApps()129     public void testGlobalHibernatedApps() throws Exception {
130         ConfigUtils.uploadConfigForPulledAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
131                 AtomsProto.Atom.GLOBAL_HIBERNATED_APPS_FIELD_NUMBER);
132         getDevice().executeShellCommand(
133                 getHibernationCommand(DeviceUtils.STATSD_ATOM_TEST_PKG,
134                         /* isGlobal */ true, /* isHibernating */ true));
135 
136         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice());
137         RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG);
138 
139         final List<AtomsProto.Atom> atoms = ReportUtils.getGaugeMetricAtoms(getDevice());
140         assertThat(atoms.size()).isEqualTo(1);
141         AtomsProto.GlobalHibernatedApps apps = atoms.get(0).getGlobalHibernatedApps();
142         assertThat(apps.getHibernatedAppCount()).isAtLeast(1);
143     }
144 
assertUserLevelHibernationStateChangedEvent( List<StatsLog.EventMetricData> data, boolean isHibernating, int currentUser)145     private static void assertUserLevelHibernationStateChangedEvent(
146             List<StatsLog.EventMetricData> data, boolean isHibernating, int currentUser) {
147         for (StatsLog.EventMetricData d : data) {
148             AtomsProto.UserLevelHibernationStateChanged atom =
149                     d.getAtom().getUserLevelHibernationStateChanged();
150             if (atom.getPackageName().equals(DeviceUtils.STATSD_ATOM_TEST_PKG)) {
151                 assertThat(atom.getUserId()).isEqualTo(currentUser);
152                 assertThat(atom.getIsHibernating()).isEqualTo(isHibernating);
153                 return;
154             }
155         }
156         fail(String.format("Did not find a matching event for package %s",
157                 DeviceUtils.STATSD_ATOM_TEST_PKG));
158     }
159 
getHibernationCommand( String packageName, boolean isGlobal, boolean isHibernating)160     private static String getHibernationCommand(
161             String packageName, boolean isGlobal, boolean isHibernating) {
162         return String.format(CMD_APP_HIBERNATION_SET_STATE,
163                 (isGlobal ? GLOBAL_OPTION : ""), packageName, isHibernating);
164     }
165 }
166