| /* | |
| * Copyright (C) 2019 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.startop.test; | |
| import android.app.Activity; | |
| import android.app.ActivityManager; | |
| import android.app.AppOpsManager; | |
| import android.app.PendingIntent; | |
| import android.content.ComponentName; | |
| import android.content.Context; | |
| import android.content.Intent; | |
| import android.content.pm.ApplicationInfo; | |
| import android.content.pm.PackageManager; | |
| import android.content.pm.PackageManager.NameNotFoundException; | |
| import android.net.ConnectivityManager; | |
| import android.os.AsyncTask; | |
| import android.os.PowerManager; | |
| import android.os.Process; | |
| import android.os.UserManager; | |
| /** | |
| * An interface for running benchmarks and collecting results. Used so we can have both an | |
| * interactive runner and a non-interactive runner. | |
| */ | |
| interface BenchmarkRunner { | |
| void addBenchmark(CharSequence name, Runnable thunk); | |
| } | |
| interface ResultListener { | |
| /** | |
| * Called when a benchmark result is ready | |
| * | |
| * @param mean The average iteration time in nanoseconds | |
| * @param stdev The standard deviation of iteration times in nanoseconds | |
| */ | |
| void onResult(double mean, double stdev); | |
| } | |
| class SystemServerBenchmarks { | |
| // Time limit to run benchmarks in seconds | |
| public static final int TIME_LIMIT = 5; | |
| static void initializeBenchmarks(Activity parent, BenchmarkRunner benchmarks) { | |
| final String packageName = parent.getPackageName(); | |
| PackageManager pm = parent.getPackageManager(); | |
| benchmarks.addBenchmark("getInstalledApplications", () -> { | |
| pm.getInstalledApplications(PackageManager.MATCH_SYSTEM_ONLY); | |
| }); | |
| benchmarks.addBenchmark("getInstalledPackages", () -> { | |
| pm.getInstalledPackages(PackageManager.GET_ACTIVITIES); | |
| }); | |
| benchmarks.addBenchmark("getPackageInfo", () -> { | |
| try { | |
| pm.getPackageInfo(packageName, 0); | |
| } catch (NameNotFoundException e) { | |
| throw new RuntimeException(e); | |
| } | |
| }); | |
| benchmarks.addBenchmark("getApplicationInfo", () -> { | |
| try { | |
| pm.getApplicationInfo(packageName, 0); | |
| } catch (NameNotFoundException e) { | |
| throw new RuntimeException(e); | |
| } | |
| }); | |
| try { | |
| ApplicationInfo app = pm.getApplicationInfo(packageName, 0); | |
| benchmarks.addBenchmark("getResourcesForApplication", () -> { | |
| try { | |
| pm.getResourcesForApplication(app); | |
| } catch (NameNotFoundException e) { | |
| throw new RuntimeException(e); | |
| } | |
| }); | |
| benchmarks.addBenchmark("getPackagesForUid", () -> { | |
| pm.getPackagesForUid(app.uid); | |
| }); | |
| } catch (NameNotFoundException e) { | |
| throw new RuntimeException(e); | |
| } | |
| ComponentName component = new ComponentName(parent, parent.getClass()); | |
| benchmarks.addBenchmark("getActivityInfo", () -> { | |
| try { | |
| pm.getActivityInfo(component, PackageManager.GET_META_DATA); | |
| } catch (NameNotFoundException e) { | |
| throw new RuntimeException(e); | |
| } | |
| }); | |
| benchmarks.addBenchmark("getLaunchIntentForPackage", () -> { | |
| pm.getLaunchIntentForPackage(packageName); | |
| }); | |
| benchmarks.addBenchmark("getPackageUid", () -> { | |
| try { | |
| pm.getPackageUid(packageName, 0); | |
| } catch (NameNotFoundException e) { | |
| throw new RuntimeException(e); | |
| } | |
| }); | |
| benchmarks.addBenchmark("checkPermission", () -> { | |
| // Check for the first permission I could find. | |
| pm.checkPermission("android.permission.SEND_SMS", packageName); | |
| }); | |
| benchmarks.addBenchmark("checkSignatures", () -> { | |
| // Compare with settings, since settings is on both AOSP and Master builds | |
| pm.checkSignatures("com.android.settings", packageName); | |
| }); | |
| Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED); | |
| benchmarks.addBenchmark("queryBroadcastReceivers", () -> { | |
| pm.queryBroadcastReceivers(intent, 0); | |
| }); | |
| benchmarks.addBenchmark("hasSystemFeature", () -> { | |
| pm.hasSystemFeature(PackageManager.FEATURE_CAMERA); | |
| }); | |
| benchmarks.addBenchmark("resolveService", () -> { | |
| pm.resolveService(intent, 0); | |
| }); | |
| ActivityManager am = (ActivityManager) parent.getSystemService(Context.ACTIVITY_SERVICE); | |
| benchmarks.addBenchmark("getRunningAppProcesses", () -> { | |
| am.getRunningAppProcesses(); | |
| }); | |
| // We use PendingIntent.getCreatorPackage, since | |
| // getPackageIntentForSender is not public to us, but getCreatorPackage | |
| // is just a thin wrapper around it. | |
| PendingIntent pi = PendingIntent.getActivity(parent, 0, new Intent(), 0); | |
| benchmarks.addBenchmark("getPackageIntentForSender", () -> { | |
| pi.getCreatorPackage(); | |
| }); | |
| PowerManager pwr = (PowerManager) parent.getSystemService(Context.POWER_SERVICE); | |
| PowerManager.WakeLock wl = pwr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "benchmark tag"); | |
| benchmarks.addBenchmark("WakeLock Acquire/Release", () -> { | |
| wl.acquire(); | |
| wl.release(); | |
| }); | |
| AppOpsManager appOps = (AppOpsManager) parent.getSystemService(Context.APP_OPS_SERVICE); | |
| int uid = Process.myUid(); | |
| benchmarks.addBenchmark("AppOpsService.checkOperation", () -> { | |
| appOps.checkOp(AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, uid, packageName); | |
| }); | |
| benchmarks.addBenchmark("AppOpsService.checkPackage", () -> { | |
| appOps.checkPackage(uid, packageName); | |
| }); | |
| benchmarks.addBenchmark("AppOpsService.noteOperation", () -> { | |
| appOps.noteOp(AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, uid, packageName); | |
| }); | |
| benchmarks.addBenchmark("AppOpsService.noteProxyOperation", () -> { | |
| appOps.noteProxyOp(AppOpsManager.OPSTR_READ_EXTERNAL_STORAGE, packageName); | |
| }); | |
| UserManager userManager = (UserManager) parent.getSystemService(Context.USER_SERVICE); | |
| benchmarks.addBenchmark("isUserUnlocked", () -> { | |
| userManager.isUserUnlocked(); | |
| }); | |
| benchmarks.addBenchmark("getIntentSender", () -> { | |
| pi.getIntentSender(); | |
| }); | |
| ConnectivityManager cm = (ConnectivityManager) parent | |
| .getSystemService(Context.CONNECTIVITY_SERVICE); | |
| benchmarks.addBenchmark("getActiveNetworkInfo", () -> { | |
| cm.getActiveNetworkInfo(); | |
| }); | |
| } | |
| /** | |
| * A helper method for benchark runners to actually run the benchmark and gather stats | |
| * | |
| * @param thunk The code whose performance we want to measure | |
| * @param reporter What to do with the results | |
| */ | |
| static void runBenchmarkInBackground(Runnable thunk, ResultListener reporter) { | |
| new AsyncTask() { | |
| double resultMean = 0; | |
| double resultStdev = 0; | |
| @Override | |
| protected Object doInBackground(Object... _args) { | |
| long startTime = System.nanoTime(); | |
| int count = 0; | |
| // Run benchmark | |
| while (true) { | |
| long elapsed = -System.nanoTime(); | |
| thunk.run(); | |
| elapsed += System.nanoTime(); | |
| count++; | |
| double elapsedVariance = (double) elapsed - resultMean; | |
| resultMean += elapsedVariance / count; | |
| resultStdev += elapsedVariance * ((double) elapsed - resultMean); | |
| if (System.nanoTime() - startTime > TIME_LIMIT * 1e9) { | |
| break; | |
| } | |
| } | |
| resultStdev = Math.sqrt(resultStdev / (count - 1)); | |
| return null; | |
| } | |
| @Override | |
| protected void onPostExecute(Object _result) { | |
| reporter.onResult(resultMean, resultStdev); | |
| } | |
| }.execute(new Object()); | |
| } | |
| } |