1 /*
2 * Copyright (C) 2020 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 #define LOG_TAG "ActivityManagerNativeTest"
18
19 #include <android-base/logging.h>
20 #include <android/activity_manager.h>
21 #include <binder/PermissionController.h>
22 #include <binder/ProcessState.h>
23 #include <gtest/gtest.h>
24
25 constexpr const char* kTestPackage = "com.android.tests.UidImportanceHelper";
26 constexpr const char* kTestActivity = "com.android.tests.UidImportanceHelper.MainActivity";
27 constexpr int64_t kEventTimeoutUs = 500000;
28
29 //-----------------------------------------------------------------
30 class ActivityManagerNativeTest : public ::testing::Test {
31 protected:
ActivityManagerNativeTest()32 ActivityManagerNativeTest() : mUidObserver(nullptr), mTestAppUid(-1), mLastUidImportance(-1) {}
33
~ActivityManagerNativeTest()34 virtual ~ActivityManagerNativeTest() {}
35
36 /* Test setup*/
SetUp()37 virtual void SetUp() { android::ProcessState::self()->startThreadPool(); }
38
39 /* Test tear down */
TearDown()40 virtual void TearDown() {}
41
waitForImportance(int32_t val,int64_t timeoutUs)42 bool waitForImportance(int32_t val, int64_t timeoutUs) {
43 std::unique_lock lock(mLock);
44
45 if (mLastUidImportance != val && timeoutUs > 0) {
46 mCondition.wait_for(lock, std::chrono::microseconds(timeoutUs));
47 }
48
49 return mLastUidImportance == val;
50 }
51
onUidImportanceChanged(uid_t uid,int32_t uidImportance)52 void onUidImportanceChanged(uid_t uid, int32_t uidImportance) {
53 LOG(ERROR) << "OnUidImportance: uid " << uid << ", importance " << uidImportance;
54 std::unique_lock lock(mLock);
55
56 if (uid == mTestAppUid) {
57 mLastUidImportance = uidImportance;
58 mCondition.notify_one();
59 }
60 }
61
OnUidImportance(uid_t uid,int32_t uidImportance,void * cookie)62 static void OnUidImportance(uid_t uid, int32_t uidImportance, void* cookie) {
63 ActivityManagerNativeTest* owner = reinterpret_cast<ActivityManagerNativeTest*>(cookie);
64 owner->onUidImportanceChanged(uid, uidImportance);
65 }
66
67 AActivityManager_UidImportanceListener* mUidObserver;
68 uid_t mTestAppUid;
69 std::mutex mLock;
70 std::condition_variable mCondition;
71 int32_t mLastUidImportance;
72 };
73
getUidForPackage(const char * packageName,uid_t & uid)74 static bool getUidForPackage(const char* packageName, /*inout*/ uid_t& uid) {
75 android::PermissionController pc;
76 uid = pc.getPackageUid(android::String16(packageName), 0);
77 if (uid <= 0) {
78 ALOGE("Unknown package: '%s'", packageName);
79 return false;
80 }
81 return true;
82 }
83
84 struct ShellHelper {
RunCmdShellHelper85 static bool RunCmd(const std::string& cmdStr) {
86 int ret = system(cmdStr.c_str());
87 if (ret != 0) {
88 LOG(ERROR) << "Failed to run cmd: " << cmdStr << ", exitcode " << ret;
89 return false;
90 }
91 return true;
92 }
93
StartShellHelper94 static bool Start(const char* packageName, const char* activityName) {
95 return RunCmd("am start -W " + std::string(packageName) + "/" + std::string(activityName) +
96 " &> /dev/null");
97 }
98
StopShellHelper99 static bool Stop(const char* packageName) {
100 return RunCmd("am force-stop " + std::string(packageName));
101 }
102 };
103
104 //-------------------------------------------------------------------------------------------------
TEST_F(ActivityManagerNativeTest,testUidImportance)105 TEST_F(ActivityManagerNativeTest, testUidImportance) {
106 pid_t selfPid = ::getpid();
107 uid_t selfUid = ::getuid();
108
109 uid_t testAppUid;
110 EXPECT_TRUE(getUidForPackage(kTestPackage, testAppUid));
111 LOG(INFO) << "testUidImportance: uidselfUid" << selfUid << ", selfPid " << selfPid
112 << ", testAppUid " << testAppUid;
113 mTestAppUid = testAppUid;
114
115 // Expect the initial UidImportance to be GONE.
116 EXPECT_FALSE(AActivityManager_isUidActive(testAppUid));
117 EXPECT_EQ(AActivityManager_getUidImportance(testAppUid), AACTIVITYMANAGER_IMPORTANCE_GONE);
118
119 mUidObserver = AActivityManager_addUidImportanceListener(&OnUidImportance,
120 AACTIVITYMANAGER_IMPORTANCE_FOREGROUND,
121 (void*)this);
122 EXPECT_TRUE(mUidObserver != nullptr);
123
124 // Start the test activity, and expect to receive UidImportance change to FOREGROUND.
125 EXPECT_TRUE(ShellHelper::Start(kTestPackage, kTestActivity));
126 EXPECT_TRUE(waitForImportance(AACTIVITYMANAGER_IMPORTANCE_FOREGROUND, kEventTimeoutUs));
127 EXPECT_TRUE(AActivityManager_isUidActive(testAppUid));
128 EXPECT_EQ(AActivityManager_getUidImportance(testAppUid),
129 AACTIVITYMANAGER_IMPORTANCE_FOREGROUND);
130
131 // Stop the test activity, and expect to receive UidImportance change to GONE.
132 EXPECT_TRUE(ShellHelper::Stop(kTestPackage));
133 EXPECT_TRUE(waitForImportance(AACTIVITYMANAGER_IMPORTANCE_GONE, kEventTimeoutUs));
134 EXPECT_FALSE(AActivityManager_isUidActive(testAppUid));
135 EXPECT_EQ(AActivityManager_getUidImportance(testAppUid), AACTIVITYMANAGER_IMPORTANCE_GONE);
136
137 AActivityManager_removeUidImportanceListener(mUidObserver);
138 mUidObserver = nullptr;
139 }
140