Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d9ec135 authored by Tapas Kumar Kundu's avatar Tapas Kumar Kundu Committed by Linux Build Service Account
Browse files

ActivityTrigger: New class to invoke when activity starts/resumes

This changes is combination of following commits:
1) Author: David Ng <dave@codeaurora.org>
   Proprietary client library needs to know activity name. Example:app
   trigger
   Change-Id: I3078ef90d0b1846cdbbf9eaefd68544263936040
2) Author: Rajulu Ponnada <rajulu@codeaurora.org>
   Change activity trigger api to include activity flags which can be
   changed if required in vendor specific library.
   Change-Id: Icfaab21fd4c5a6290f226a338870b9031d32b498
3) Author: Rajulu Ponnada <rajulu@codeaurora.org>
   support for opening/loading multiple dynamic libraries when apps'
   activity start/resume invoked
   Change-Id: Icf42e426870ee634920c2288e4075699c472d3a6
4) Author: Xin Qi <xqi@codeaurora.org>
   GetStringUTFChars() does not release memory untill
   ReleaseStringUTFChars() is called and causes memory leak. This
   change uses ReleaseStringUTFChars() to release unused buffer.
   Change-Id: If7f27ea35f5a1d1dd7c98fbe5f92729ab9ba0257

Change-Id: I089f1669e5711efcabbf1985d80b48c6e92893c6
parent c4cb19bb
Loading
Loading
Loading
Loading
+74 −0
Original line number Diff line number Diff line
/* Copyright (c) 2015, 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.internal.app;

import android.content.ComponentName;
import android.content.Intent;
import android.util.Log;

public class ActivityTrigger
{
    private static final String TAG = "ActivityTrigger";

    /** &hide */
    public ActivityTrigger() {
        //Log.d(TAG, "ActivityTrigger initialized");
    }

    /** &hide */
    protected void finalize() {
        native_at_deinit();
    }

    /** &hide */
    public int activityStartTrigger(Intent intent, int flags) {
        ComponentName cn = intent.getComponent();
        String activity = null;

        if (cn != null)
            activity = cn.flattenToString();
        flags = native_at_startActivity(activity, flags);
        return flags;
    }

    /** &hide */
    public void activityResumeTrigger(Intent intent) {
        ComponentName cn = intent.getComponent();
        String activity = null;

        if (cn != null)
            activity = cn.flattenToString();
        native_at_resumeActivity(activity);
    }

    private native int native_at_startActivity(String activity, int flags);
    private native void native_at_resumeActivity(String activity);
    private native void native_at_deinit();
}
+2 −1
Original line number Diff line number Diff line
@@ -177,7 +177,8 @@ LOCAL_SRC_FILES:= \
    com_android_internal_os_PathClassLoaderFactory.cpp \
    com_android_internal_os_Zygote.cpp \
    com_android_internal_util_VirtualRefBasePtr.cpp \
    com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp
    com_android_internal_view_animation_NativeInterpolatorFactoryHelper.cpp \
    com_android_internal_app_ActivityTrigger.cpp

LOCAL_C_INCLUDES += \
    $(JNI_H_INCLUDE) \
+2 −1
Original line number Diff line number Diff line
@@ -203,6 +203,7 @@ extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env);
extern int register_com_android_internal_os_PathClassLoaderFactory(JNIEnv* env);
extern int register_com_android_internal_os_Zygote(JNIEnv *env);
extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);
extern int register_com_android_internal_app_ActivityTrigger(JNIEnv *env);

static AndroidRuntime* gCurRuntime = NULL;

@@ -1408,7 +1409,7 @@ static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_animation_PropertyValuesHolder),
    REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
    REG_JNI(register_com_android_internal_net_NetworkStatsFactory),

    REG_JNI(register_com_android_internal_app_ActivityTrigger),
};

/*
+208 −0
Original line number Diff line number Diff line
/* Copyright (c) 2015, 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.
 *
 */

#define LOG_TAG "ActTriggerJNI"

#include "jni.h"
#include "JNIHelp.h"
#include <android_runtime/AndroidRuntime.h>

#include <dlfcn.h>
#include <limits.h>
#include <string.h>

#include <cutils/properties.h>
#include <utils/Log.h>

#define LIBRARY_PATH_PREFIX "/vendor/lib/"

namespace android
{

// ----------------------------------------------------------------------------
/*
 * Stuct containing handle to dynamically loaded lib as well as function
 * pointers to key interfaces.
 */
typedef struct dlLibHandler {
    void *dlhandle;
    void (*startActivity)(const char *, int *);
    void (*resumeActivity)(const char *);
    void (*init)(void);
    void (*deinit)(void);
    const char *dlname;
}dlLibHandler;

/*
 * Array of dlhandlers
 * library -both handlers for Start and Resume events.
 */
static dlLibHandler mDlLibHandlers[] = {
    {NULL, NULL, NULL, NULL, NULL,
     "ro.vendor.at_library"},
    {NULL, NULL, NULL, NULL, NULL,
     "ro.vendor.gt_library"},
};

// ----------------------------------------------------------------------------

static void
com_android_internal_app_ActivityTrigger_native_at_init()
{
    const char *rc;
    char buf[PROPERTY_VALUE_MAX];
    bool errored = false;
    size_t numlibs = 0;

    numlibs = sizeof (mDlLibHandlers) / sizeof (*mDlLibHandlers);

    for(size_t i = 0; i < numlibs; i++) {
        errored = false;

        /* Retrieve name of vendor library */
        if (property_get(mDlLibHandlers[i].dlname, buf, NULL) <= 0) {
            continue;
        }

        /* Sanity check - ensure */
        buf[PROPERTY_VALUE_MAX-1] = '\0';
        if (strstr(buf, "/") != NULL) {
            continue;
        }

        mDlLibHandlers[i].dlhandle = dlopen(buf, RTLD_NOW | RTLD_LOCAL);
        if (mDlLibHandlers[i].dlhandle == NULL) {
            continue;
        }

        dlerror();

        *(void **) (&mDlLibHandlers[i].startActivity) = dlsym(mDlLibHandlers[i].dlhandle, "activity_trigger_start");
        if ((rc = dlerror()) != NULL) {
            errored = true;
        }

        if (!errored) {
            *(void **) (&mDlLibHandlers[i].resumeActivity) = dlsym(mDlLibHandlers[i].dlhandle, "activity_trigger_resume");
            if ((rc = dlerror()) != NULL) {
                errored = true;
            }
        }
        if (!errored) {
            *(void **) (&mDlLibHandlers[i].init) = dlsym(mDlLibHandlers[i].dlhandle, "activity_trigger_init");
            if ((rc = dlerror()) != NULL) {
                errored = true;
            }
        }

        if (errored) {
            mDlLibHandlers[i].startActivity  = NULL;
            mDlLibHandlers[i].resumeActivity = NULL;
            if (mDlLibHandlers[i].dlhandle) {
                dlclose(mDlLibHandlers[i].dlhandle);
                mDlLibHandlers[i].dlhandle = NULL;
            }
        } else {
            (*mDlLibHandlers[i].init)();
        }
    }
}

static void
com_android_internal_app_ActivityTrigger_native_at_deinit(JNIEnv *env, jobject clazz)
{
    size_t numlibs = sizeof (mDlLibHandlers) / sizeof (*mDlLibHandlers);

    for(size_t i = 0; i < numlibs; i++) {
        if (mDlLibHandlers[i].dlhandle) {
            mDlLibHandlers[i].startActivity  = NULL;
            mDlLibHandlers[i].resumeActivity = NULL;

            *(void **) (&mDlLibHandlers[i].deinit) = dlsym(mDlLibHandlers[i].dlhandle, "activity_trigger_deinit");
            if (mDlLibHandlers[i].deinit) {
                (*mDlLibHandlers[i].deinit)();
            }

            dlclose(mDlLibHandlers[i].dlhandle);
            mDlLibHandlers[i].dlhandle = NULL;
        }
    }
}

static jint
com_android_internal_app_ActivityTrigger_native_at_startActivity(JNIEnv *env, jobject clazz, jstring activity, jint flags)
{
    int activiyFlags = flags;
    size_t numlibs = sizeof (mDlLibHandlers) / sizeof (*mDlLibHandlers);
    for(size_t i = 0; i < numlibs; i++){
        if(mDlLibHandlers[i].startActivity && activity) {
            const char *actStr = env->GetStringUTFChars(activity, NULL);
            if (actStr) {
                (*mDlLibHandlers[i].startActivity)(actStr, &activiyFlags);
                env->ReleaseStringUTFChars(activity, actStr);
            }
        }
    }
    return activiyFlags;
}

static void
com_android_internal_app_ActivityTrigger_native_at_resumeActivity(JNIEnv *env, jobject clazz, jstring activity)
{
    size_t numlibs = sizeof (mDlLibHandlers) / sizeof (*mDlLibHandlers);

    for(size_t i = 0; i < numlibs; i++){
        if(mDlLibHandlers[i].resumeActivity && activity) {
            const char *actStr = env->GetStringUTFChars(activity, NULL);
            if (actStr) {
                (*mDlLibHandlers[i].resumeActivity)(actStr);
                env->ReleaseStringUTFChars(activity, actStr);
            }
        }
    }
}

// ----------------------------------------------------------------------------

static JNINativeMethod gMethods[] = {
    {"native_at_startActivity",  "(Ljava/lang/String;I)I", (void *)com_android_internal_app_ActivityTrigger_native_at_startActivity},
    {"native_at_resumeActivity", "(Ljava/lang/String;)V", (void *)com_android_internal_app_ActivityTrigger_native_at_resumeActivity},
    {"native_at_deinit",         "()V",                   (void *)com_android_internal_app_ActivityTrigger_native_at_deinit},
};


int register_com_android_internal_app_ActivityTrigger(JNIEnv *env)
{
    com_android_internal_app_ActivityTrigger_native_at_init();

    return AndroidRuntime::registerNativeMethods(env,
            "com/android/internal/app/ActivityTrigger", gMethods, NELEM(gMethods));
}

}   // namespace android
+9 −1
Original line number Diff line number Diff line
@@ -119,6 +119,8 @@ import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.view.Display;
import com.android.internal.app.ActivityTrigger;


import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.ReferrerIntent;
@@ -354,6 +356,8 @@ final class ActivityStack {

    final Handler mHandler;

    static final ActivityTrigger mActivityTrigger = new ActivityTrigger();

    final class ActivityStackHandler extends Handler {

        ActivityStackHandler(Looper looper) {
@@ -2233,7 +2237,10 @@ final class ActivityStack {

        if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next);

        // If we are currently pausing an activity, then don't do anything until that is done.
        mActivityTrigger.activityResumeTrigger(next.intent);

        // If we are currently pausing an activity, then don't do anything
        // until that is done.
        if (!mStackSupervisor.allPausedActivitiesComplete()) {
            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
                    "resumeTopActivityLocked: Skip resume: some activity pausing.");
@@ -2699,6 +2706,7 @@ final class ActivityStack {
        task.setFrontOfTask();

        r.putInHistory();
        r.info.flags = mActivityTrigger.activityStartTrigger(r.intent, r.info.flags);
        if (!isHomeStack() || numActivities() > 0) {
            // We want to show the starting preview window if we are
            // switching to a new task, or the next activity's process is