diff --git a/services/core/java/com/android/server/ActivityTriggerService.java b/services/core/java/com/android/server/ActivityTriggerService.java new file mode 100644 index 0000000000000..323ad096dc5c2 --- /dev/null +++ b/services/core/java/com/android/server/ActivityTriggerService.java @@ -0,0 +1,106 @@ +/* +* Copyright (c) 2019, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package com.android.server; + +import android.content.pm.ApplicationInfo; +import android.util.Slog; +import android.content.Context; +import com.android.server.am.HostingRecord; +import java.lang.Runnable; +import android.os.HandlerThread; +import android.os.Handler; + +public class ActivityTriggerService extends SystemService { + private static String TAG = "ActivityTriggerService"; + public static final int PROC_ADDED_NOTIFICATION = 1; + public static final int PROC_REMOVED_NOTIFICATION = 0; + private EventHandlerThread eventHandler = new EventHandlerThread("EventHandlerThread"); + + public ActivityTriggerService(Context context) { + super(context); + } + + @Override + public void onStart() { + Slog.i(TAG, "Starting ActivityTriggerService"); + eventHandler.start(); + publishLocalService(ActivityTriggerService.class, this); + } + + /*make non-blocking call to add a new event to the handler's queue. + the event handler is the one responsible for running each event.*/ + public void updateRecord(HostingRecord hr, ApplicationInfo info, int pid, int event) { + if(hr != null) { + eventHandler.getHandler().post(new LocalRunnable(info.packageName, info.longVersionCode, info.processName, pid, event)); + } + } + + public class EventHandlerThread extends HandlerThread { + private Handler handler; + public EventHandlerThread(String name) { + super(name); //no priority specified + } + + @Override + protected void onLooperPrepared() { + //attach a handler to the thread + handler = new Handler(); + } + //get the handler that queues and runs Runnables + public Handler getHandler() { + return handler; + } + } + + static class LocalRunnable implements Runnable { + private String packageName; + private long lvCode; + private String procName; + private int pid; + private int event; + + LocalRunnable(String packageName, long lvCode, String procName, int pid, int event) { + this.packageName = packageName; + this.lvCode = lvCode; + this.procName = procName; + this.pid = pid; + this.event = event; + } + @Override + public void run() { + notifyAction_native(packageName, lvCode, procName, pid, event); + } + } + + //Native methods + static native void notifyAction_native(String pkgName, long vCode, String procName, int pid, int event); + +} + diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 02a23fa1e241f..578a14b2cafa3 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -369,6 +369,7 @@ import com.android.server.wm.ActivityTaskManagerService; import com.android.server.wm.WindowManagerService; import com.android.server.wm.WindowProcessController; +import com.android.server.ActivityTriggerService; import dalvik.system.VMRuntime; @@ -758,6 +759,10 @@ void put(ProcessRecord app) { synchronized (this) { mPidMap.put(app.pid, app); } + ActivityTriggerService atService = LocalServices.getService(ActivityTriggerService.class); + if(atService != null) { + atService.updateRecord(app.hostingRecord, app.info, app.pid, ActivityTriggerService.PROC_ADDED_NOTIFICATION); + } mAtmInternal.onProcessMapped(app.pid, app.getWindowProcessController()); } @@ -776,6 +781,10 @@ void remove(ProcessRecord app) { } } if (removed) { + ActivityTriggerService atService = LocalServices.getService(ActivityTriggerService.class); + if(atService != null) { + atService.updateRecord(app.hostingRecord, app.info, app.pid, ActivityTriggerService.PROC_REMOVED_NOTIFICATION); + } mAtmInternal.onProcessUnMapped(app.pid); } } @@ -1555,8 +1564,6 @@ public void binderDied() { static final String SERVICE_RECORD_KEY = "servicerecord"; - static final ActivityTrigger mActivityTrigger = new ActivityTrigger(); - long mLastMemUsageReportTime = 0; // Process in same process Group keep in same cgroup @@ -5240,9 +5247,6 @@ app.compat, getCommonServicesLocked(app.isolated), (int) (SystemClock.elapsedRealtime() - app.startTime), app.hostingRecord.getType(), (app.hostingRecord.getName() != null ? app.hostingRecord.getName() : "")); - - //send start notification to AT with the starting app's info. - mActivityTrigger.activityStartTrigger(app.info, app.pid); return true; } diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp index 621849869590a..75a24aa6eb336 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -52,6 +52,7 @@ cc_library_static { "com_android_server_GraphicsStatsService.cpp", "com_android_server_am_AppCompactor.cpp", "com_android_server_am_LowMemDetector.cpp", + "com_android_server_activityTriggerService.cpp", "onload.cpp", ":lib_networkStatsFactory_native", ], diff --git a/services/core/jni/com_android_server_activityTriggerService.cpp b/services/core/jni/com_android_server_activityTriggerService.cpp new file mode 100644 index 0000000000000..025091f76e38b --- /dev/null +++ b/services/core/jni/com_android_server_activityTriggerService.cpp @@ -0,0 +1,95 @@ +/* +* Copyright (c) 2019, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "jni.h" +#include +#include "android_runtime/AndroidRuntime.h" +#include +#include +#include + +namespace android { + +//structure which has a handle for dynamically loading the trigger handler lib. + +typedef struct dlLibHandler { + void *handle; + void (*set_info)(const char*, const char*, int *); + const char *dlname; +}dlLibhandler; + +//initialize the handler +static dlLibHandler handler = { + NULL, NULL, "libtrigger-handler.so" +}; + +static void trigger_handler_lib_init() { + bool dlError = false; + handler.handle = dlopen(handler.dlname, RTLD_NOW | RTLD_LOCAL); + /*no need to proceed if the lib isn't available*/ + if(handler.handle == NULL) { + ALOGE("Activity trigger handling disabled."); + return; + } + *(void **) (&handler.set_info) = dlsym(handler.handle, "set_info"); + if(handler.set_info == NULL) { + dlError = true; + } + if(dlError) { + handler.set_info = NULL; + if(handler.handle) dlclose(handler.handle); + handler.handle = NULL; + } +} + +static void notifyAction_native (JNIEnv* env, jobject /*jclazz*/,jstring pkgName, jlong vCode, jstring /*procName*/, jint pid_in, jint flag) { + int pid = (int)pid_in; + std::string versionCode = std::to_string((long)vCode) + std::to_string((int)flag); + const char* version = versionCode.c_str(); + + if(pkgName && handler.set_info) { + const char *package = env->GetStringUTFChars(pkgName, NULL); + if(package) { + (*handler.set_info)(package,version,&pid); + env->ReleaseStringUTFChars(pkgName, package); + } + } +} + +static JNINativeMethod method_list[] = { + { "notifyAction_native", "(Ljava/lang/String;JLjava/lang/String;II)V", (void*)notifyAction_native }, +}; + +int register_android_server_ActivityTriggerService(JNIEnv *env) { + //load and link to the handler library + trigger_handler_lib_init(); + return jniRegisterNativeMethods(env, "com/android/server/ActivityTriggerService", + method_list, NELEM(method_list)); +} +}; diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index efffa6ca735b8..439e226a73b33 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -57,6 +57,7 @@ int register_android_server_net_NetworkStatsService(JNIEnv* env); int register_android_server_security_VerityUtils(JNIEnv* env); int register_android_server_am_AppCompactor(JNIEnv* env); int register_android_server_am_LowMemDetector(JNIEnv* env); +int register_android_server_ActivityTriggerService(JNIEnv* env); }; using namespace android; @@ -107,5 +108,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) register_android_server_security_VerityUtils(env); register_android_server_am_AppCompactor(env); register_android_server_am_LowMemDetector(env); + register_android_server_ActivityTriggerService(env); return JNI_VERSION_1_4; } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 950bfbb03c7d4..2aa029ffe1d4b 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -1093,6 +1093,10 @@ private void startOtherServices() { mSystemServiceManager.startService(PinnerService.class); traceEnd(); + traceBeginAndSlog("ActivityTriggerService"); + mSystemServiceManager.startService(ActivityTriggerService.class); + traceEnd(); + traceBeginAndSlog("SignedConfigService"); SignedConfigService.registerUpdateReceiver(mSystemContext); traceEnd();