diff options
author | Chong Zhang <chz@google.com> | 2020-12-04 17:15:45 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-12-04 17:15:45 +0000 |
commit | c4be44372d4059d41656c4b5207bead1bf4ec273 (patch) | |
tree | 20c2e2490a81ddbb7c69678f12518d42b5488e4f /native | |
parent | cb95b8375bcdf7ce3ef02177f2dd3bc1bff9a195 (diff) | |
parent | e6bcd1bbb1331549cab40011d422f3b6fccbe90d (diff) |
Merge "Add AActivityManager UidImportance test"
Diffstat (limited to 'native')
6 files changed, 382 insertions, 0 deletions
diff --git a/native/android/tests/activitymanager/UidImportanceHelperApps/Android.bp b/native/android/tests/activitymanager/UidImportanceHelperApps/Android.bp new file mode 100644 index 000000000000..1a51218616d2 --- /dev/null +++ b/native/android/tests/activitymanager/UidImportanceHelperApps/Android.bp @@ -0,0 +1,11 @@ +android_test_helper_app { + name: "UidImportanceHelperApp", + manifest: "HelperAppManifest.xml", + static_libs: ["androidx.test.rules"], + sdk_version: "test_current", + srcs: ["src/**/*.java"], + test_suites: [ + "general-tests", + ], +} + diff --git a/native/android/tests/activitymanager/UidImportanceHelperApps/HelperAppManifest.xml b/native/android/tests/activitymanager/UidImportanceHelperApps/HelperAppManifest.xml new file mode 100644 index 000000000000..3583b33756e9 --- /dev/null +++ b/native/android/tests/activitymanager/UidImportanceHelperApps/HelperAppManifest.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.tests.UidImportanceHelper" + android:versionCode="1" + android:versionName="1.0" > + + <application android:label="UidImportanceHelper"> + <activity android:name="com.android.tests.UidImportanceHelper.MainActivity" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT"/> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> + diff --git a/native/android/tests/activitymanager/UidImportanceHelperApps/src/com/android/tests/UidImportanceHelper/MainActivity.java b/native/android/tests/activitymanager/UidImportanceHelperApps/src/com/android/tests/UidImportanceHelper/MainActivity.java new file mode 100644 index 000000000000..db0f2b5ed967 --- /dev/null +++ b/native/android/tests/activitymanager/UidImportanceHelperApps/src/com/android/tests/UidImportanceHelper/MainActivity.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.tests.UidImportanceHelper; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +/** + * This is an empty activity for testing the UID policy of media transcoding service. + */ +public class MainActivity extends Activity { + private static final String TAG = "MainActivity"; + + // Called at the start of the full lifetime. + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Initialize Activity and inflate the UI. + } + + // Called after onCreate has finished, use to restore UI state + @Override + public void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + // Restore UI state from the savedInstanceState. + // This bundle has also been passed to onCreate. + // Will only be called if the Activity has been + // killed by the system since it was last visible. + } + + // Called before subsequent visible lifetimes + // for an activity process. + @Override + public void onRestart() { + super.onRestart(); + // Load changes knowing that the Activity has already + // been visible within this process. + } + + // Called at the start of the visible lifetime. + @Override + public void onStart() { + super.onStart(); + // Apply any required UI change now that the Activity is visible. + } + + // Called at the start of the active lifetime. + @Override + public void onResume() { + super.onResume(); + // Resume any paused UI updates, threads, or processes required + // by the Activity but suspended when it was inactive. + } + + // Called to save UI state changes at the + // end of the active lifecycle. + @Override + public void onSaveInstanceState(Bundle savedInstanceState) { + // Save UI state changes to the savedInstanceState. + // This bundle will be passed to onCreate and + // onRestoreInstanceState if the process is + // killed and restarted by the run time. + super.onSaveInstanceState(savedInstanceState); + } + + // Called at the end of the active lifetime. + @Override + public void onPause() { + // Suspend UI updates, threads, or CPU intensive processes + // that don't need to be updated when the Activity isn't + // the active foreground Activity. + super.onPause(); + } + + // Called at the end of the visible lifetime. + @Override + public void onStop() { + // Suspend remaining UI updates, threads, or processing + // that aren't required when the Activity isn't visible. + // Persist all edits or state changes + // as after this call the process is likely to be killed. + super.onStop(); + } + + // Sometimes called at the end of the full lifetime. + @Override + public void onDestroy() { + // Clean up any resources including ending threads, + // closing database connections etc. + super.onDestroy(); + } +} diff --git a/native/android/tests/activitymanager/nativeTests/Android.bp b/native/android/tests/activitymanager/nativeTests/Android.bp new file mode 100644 index 000000000000..d4b5015ad8f3 --- /dev/null +++ b/native/android/tests/activitymanager/nativeTests/Android.bp @@ -0,0 +1,39 @@ +cc_test { + name: "ActivityManagerNativeTestCases", + + multilib: { + lib32: { + suffix: "32", + }, + lib64: { + suffix: "64", + }, + }, + + srcs: ["src/ActivityManagerNativeTest.cpp"], + + shared_libs: [ + "liblog", + "libutils", + "libandroid", + "libbinder", + ], + + static_libs: [ + "libbase", + "libgtest", + ], + stl: "c++_shared", + + test_suites: [ + "general-tests", + ], + + cflags: [ + "-Werror", + "-Wall", + ], + required: [ + "UidImportanceHelperApp", + ], +} diff --git a/native/android/tests/activitymanager/nativeTests/AndroidTest.xml b/native/android/tests/activitymanager/nativeTests/AndroidTest.xml new file mode 100644 index 000000000000..bf6287ad4883 --- /dev/null +++ b/native/android/tests/activitymanager/nativeTests/AndroidTest.xml @@ -0,0 +1,53 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2020 The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<configuration description="Config for ActivityManager native test cases"> + <option name="test-suite-tag" value="apct" /> + <option name="test-suite-tag" value="apct-native" /> + <option name="config-descriptor:metadata" key="component" value="framework" /> + <option name="config-descriptor:metadata" key="parameter" value="instant_app" /> + <option name="config-descriptor:metadata" key="parameter" value="multi_abi" /> + <option name="config-descriptor:metadata" key="parameter" value="secondary_user" /> + + <!-- Force root to allow registering UidImportanceListener from native test --> + <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"> + <option name="force-root" value="true" /> + </target_preparer> + <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> + <option name="run-command" value="input keyevent KEYCODE_WAKEUP" /> + <option name="run-command" value="wm dismiss-keyguard" /> + </target_preparer> + <!-- Install the helper apk --> + <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller"> + <option name="cleanup-apks" value="true" /> + <option name="test-file-name" value="UidImportanceHelperApp.apk" /> + </target_preparer> + + <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher"> + <option name="cleanup" value="true" /> + <option name="push" value="ActivityManagerNativeTestCases->/data/local/tmp/ActivityManagerNativeTestCases" /> + <option name="append-bitness" value="true" /> + </target_preparer> + + <test class="com.android.tradefed.testtype.GTest" > + <option name="native-test-device-path" value="/data/local/tmp" /> + <option name="module-name" value="ActivityManagerNativeTestCases" /> + <option name="runtime-hint" value="1m" /> + </test> + + <!-- Controller that will skip the module if a native bridge situation is detected --> + <!-- For example: module wants to run arm and device is x86 --> + <object type="module_controller" class="com.android.tradefed.testtype.suite.module.NativeBridgeModuleController" /> +</configuration> diff --git a/native/android/tests/activitymanager/nativeTests/src/ActivityManagerNativeTest.cpp b/native/android/tests/activitymanager/nativeTests/src/ActivityManagerNativeTest.cpp new file mode 100644 index 000000000000..75ba0ffb229a --- /dev/null +++ b/native/android/tests/activitymanager/nativeTests/src/ActivityManagerNativeTest.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "ActivityManagerNativeTest" + +#include <android-base/logging.h> +#include <android/activity_manager.h> +#include <binder/PermissionController.h> +#include <binder/ProcessState.h> +#include <gtest/gtest.h> + +constexpr const char* kTestPackage = "com.android.tests.UidImportanceHelper"; +constexpr const char* kTestActivity = "com.android.tests.UidImportanceHelper.MainActivity"; +constexpr int64_t kEventTimeoutUs = 500000; + +//----------------------------------------------------------------- +class ActivityManagerNativeTest : public ::testing::Test { +protected: + ActivityManagerNativeTest() : mUidObserver(nullptr), mTestAppUid(-1), mLastUidImportance(-1) {} + + virtual ~ActivityManagerNativeTest() {} + + /* Test setup*/ + virtual void SetUp() { android::ProcessState::self()->startThreadPool(); } + + /* Test tear down */ + virtual void TearDown() {} + + bool waitForImportance(int32_t val, int64_t timeoutUs) { + std::unique_lock lock(mLock); + + if (mLastUidImportance != val && timeoutUs > 0) { + mCondition.wait_for(lock, std::chrono::microseconds(timeoutUs)); + } + + return mLastUidImportance == val; + } + + void onUidImportanceChanged(uid_t uid, int32_t uidImportance) { + LOG(ERROR) << "OnUidImportance: uid " << uid << ", importance " << uidImportance; + std::unique_lock lock(mLock); + + if (uid == mTestAppUid) { + mLastUidImportance = uidImportance; + mCondition.notify_one(); + } + } + + static void OnUidImportance(uid_t uid, int32_t uidImportance, void* cookie) { + ActivityManagerNativeTest* owner = reinterpret_cast<ActivityManagerNativeTest*>(cookie); + owner->onUidImportanceChanged(uid, uidImportance); + } + + AActivityManager_UidImportanceListener* mUidObserver; + uid_t mTestAppUid; + std::mutex mLock; + std::condition_variable mCondition; + int32_t mLastUidImportance; +}; + +static bool getUidForPackage(const char* packageName, /*inout*/ uid_t& uid) { + android::PermissionController pc; + uid = pc.getPackageUid(android::String16(packageName), 0); + if (uid <= 0) { + ALOGE("Unknown package: '%s'", packageName); + return false; + } + return true; +} + +struct ShellHelper { + static bool RunCmd(const std::string& cmdStr) { + int ret = system(cmdStr.c_str()); + if (ret != 0) { + LOG(ERROR) << "Failed to run cmd: " << cmdStr << ", exitcode " << ret; + return false; + } + return true; + } + + static bool Start(const char* packageName, const char* activityName) { + return RunCmd("am start -W " + std::string(packageName) + "/" + std::string(activityName) + + " &> /dev/null"); + } + + static bool Stop(const char* packageName) { + return RunCmd("am force-stop " + std::string(packageName)); + } +}; + +//------------------------------------------------------------------------------------------------- +TEST_F(ActivityManagerNativeTest, testUidImportance) { + pid_t selfPid = ::getpid(); + uid_t selfUid = ::getuid(); + + uid_t testAppUid; + EXPECT_TRUE(getUidForPackage(kTestPackage, testAppUid)); + LOG(INFO) << "testUidImportance: uidselfUid" << selfUid << ", selfPid " << selfPid + << ", testAppUid " << testAppUid; + mTestAppUid = testAppUid; + + // Expect the initial UidImportance to be GONE. + EXPECT_FALSE(AActivityManager_isUidActive(testAppUid)); + EXPECT_EQ(AActivityManager_getUidImportance(testAppUid), AACTIVITYMANAGER_IMPORTANCE_GONE); + + mUidObserver = AActivityManager_addUidImportanceListener(&OnUidImportance, + AACTIVITYMANAGER_IMPORTANCE_FOREGROUND, + (void*)this); + EXPECT_TRUE(mUidObserver != nullptr); + + // Start the test activity, and expect to receive UidImportance change to FOREGROUND. + EXPECT_TRUE(ShellHelper::Start(kTestPackage, kTestActivity)); + EXPECT_TRUE(waitForImportance(AACTIVITYMANAGER_IMPORTANCE_FOREGROUND, kEventTimeoutUs)); + EXPECT_TRUE(AActivityManager_isUidActive(testAppUid)); + EXPECT_EQ(AActivityManager_getUidImportance(testAppUid), + AACTIVITYMANAGER_IMPORTANCE_FOREGROUND); + + // Stop the test activity, and expect to receive UidImportance change to GONE. + EXPECT_TRUE(ShellHelper::Stop(kTestPackage)); + EXPECT_TRUE(waitForImportance(AACTIVITYMANAGER_IMPORTANCE_GONE, kEventTimeoutUs)); + EXPECT_FALSE(AActivityManager_isUidActive(testAppUid)); + EXPECT_EQ(AActivityManager_getUidImportance(testAppUid), AACTIVITYMANAGER_IMPORTANCE_GONE); + + AActivityManager_removeUidImportanceListener(mUidObserver); + mUidObserver = nullptr; +} |