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

Commit 4b3a7f29 authored by Michael Wachenschwanz's avatar Michael Wachenschwanz Committed by Android (Google) Code Review
Browse files

Merge "Java side setup and access to Binder Proxy Tracking"

parents 9cd92adb 55182464
Loading
Loading
Loading
Loading
+101 −0
Original line number Diff line number Diff line
@@ -16,9 +16,15 @@

package com.android.internal.os;

import android.annotation.NonNull;
import android.os.Handler;
import android.os.IBinder;
import android.os.SystemClock;
import android.util.EventLog;
import android.util.Log;
import android.util.SparseIntArray;

import com.android.internal.util.Preconditions;

import dalvik.system.VMRuntime;

@@ -31,11 +37,14 @@ import java.util.ArrayList;
 * @see IBinder
 */
public class BinderInternal {
    private static final String TAG = "BinderInternal";
    static WeakReference<GcWatcher> sGcWatcher
            = new WeakReference<GcWatcher>(new GcWatcher());
    static ArrayList<Runnable> sGcWatchers = new ArrayList<>();
    static Runnable[] sTmpWatchers = new Runnable[1];
    static long sLastGcTime;
    static final BinderProxyLimitListenerDelegate sBinderProxyLimitListenerDelegate =
            new BinderProxyLimitListenerDelegate();

    static final class GcWatcher {
        @Override
@@ -106,4 +115,96 @@ public class BinderInternal {
    static void forceBinderGc() {
        forceGc("Binder");
    }

    /**
     * Enable/disable Binder Proxy Instance Counting by Uid. While enabled, the set callback will
     * be called if this process holds too many Binder Proxies on behalf of a Uid.
     * @param enabled true to enable counting, false to disable
     */
    public static final native void nSetBinderProxyCountEnabled(boolean enabled);

    /**
     * Get the current number of Binder Proxies held for each uid.
     * @return SparseIntArray mapping uids to the number of Binder Proxies currently held
     */
    public static final native SparseIntArray nGetBinderProxyPerUidCounts();

    /**
     * Get the current number of Binder Proxies held for an individual uid.
     * @param uid Requested uid for Binder Proxy count
     * @return int with the number of Binder proxies held for a uid
     */
    public static final native int nGetBinderProxyCount(int uid);

    /**
     * Set the Binder Proxy watermarks. Default high watermark = 2500. Default low watermark = 2000
     * @param high  The limit at which the BinderProxyListener callback will be called.
     * @param low   The threshold a binder count must drop below before the callback
     *              can be called again. (This is to avoid many repeated calls to the
     *              callback in a brief period of time)
     */
    public static final native void nSetBinderProxyCountWatermarks(int high, int low);

    /**
     * Interface for callback invocation when the Binder Proxy limit is reached. onLimitReached will
     * be called with the uid of the app causing too many Binder Proxies
     */
    public interface BinderProxyLimitListener {
        public void onLimitReached(int uid);
    }

    /**
     * Callback used by native code to trigger a callback in java code. The callback will be
     * triggered when too many binder proxies from a uid hits the allowed limit.
     * @param uid The uid of the bad behaving app sending too many binders
     */
    public static void binderProxyLimitCallbackFromNative(int uid) {
       sBinderProxyLimitListenerDelegate.notifyClient(uid);
    }

    /**
     * Set a callback to be triggered when a uid's Binder Proxy limit is reached for this process.
     * @param listener OnLimitReached of listener will be called in the thread provided by handler
     * @param handler must not be null, callback will be posted through the handler;
     *
     */
    public static void setBinderProxyCountCallback(BinderProxyLimitListener listener,
            @NonNull Handler handler) {
        Preconditions.checkNotNull(handler,
                "Must provide NonNull Handler to setBinderProxyCountCallback when setting "
                        + "BinderProxyLimitListener");
        sBinderProxyLimitListenerDelegate.setListener(listener, handler);
    }

    /**
     * Clear the Binder Proxy callback
     */
    public static void clearBinderProxyCountCallback() {
        sBinderProxyLimitListenerDelegate.setListener(null, null);
    }

    static private class BinderProxyLimitListenerDelegate {
        private BinderProxyLimitListener mBinderProxyLimitListener;
        private Handler mHandler;

        void setListener(BinderProxyLimitListener listener, Handler handler) {
            synchronized (this) {
                mBinderProxyLimitListener = listener;
                mHandler = handler;
            }
        }

        void notifyClient(final int uid) {
            synchronized (this) {
                if (mBinderProxyLimitListener != null) {
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            mBinderProxyLimitListener.onLimitReached(uid);
                        }
                    });
                }
            }
        }
    }
}
+61 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <binder/BpBinder.h>
#include <binder/ProcessState.h>
#include <log/log.h>
#include <utils/Atomic.h>
@@ -80,9 +81,17 @@ static struct binderinternal_offsets_t
    // Class state.
    jclass mClass;
    jmethodID mForceGc;
    jmethodID mProxyLimitCallback;

} gBinderInternalOffsets;

static struct sparseintarray_offsets_t
{
    jclass classObject;
    jmethodID constructor;
    jmethodID put;
} gSparseIntArrayOffsets;

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

static struct error_offsets_t
@@ -973,6 +982,43 @@ static void android_os_BinderInternal_handleGc(JNIEnv* env, jobject clazz)
    android_atomic_and(0, &gNumRefsCreated);
}

static void android_os_BinderInternal_proxyLimitcallback(int uid)
{
    JNIEnv *env = AndroidRuntime::getJNIEnv();
    env->CallStaticVoidMethod(gBinderInternalOffsets.mClass,
                              gBinderInternalOffsets.mProxyLimitCallback,
                              uid);
}

static void android_os_BinderInternal_setBinderProxyCountEnabled(JNIEnv* env, jobject clazz,
                                                                 jboolean enable)
{
    BpBinder::setCountByUidEnabled((bool) enable);
}

static jobject android_os_BinderInternal_getBinderProxyPerUidCounts(JNIEnv* env, jclass clazz)
{
    Vector<uint32_t> uids, counts;
    BpBinder::getCountByUid(uids, counts);
    jobject sparseIntArray = env->NewObject(gSparseIntArrayOffsets.classObject,
                                            gSparseIntArrayOffsets.constructor);
    for (size_t i = 0; i < uids.size(); i++) {
        env->CallVoidMethod(sparseIntArray, gSparseIntArrayOffsets.put,
                            static_cast<jint>(uids[i]), static_cast<jint>(counts[i]));
    }
    return sparseIntArray;
}

static jint android_os_BinderInternal_getBinderProxyCount(JNIEnv* env, jobject clazz, jint uid) {
    return static_cast<jint>(BpBinder::getBinderProxyCount(static_cast<uint32_t>(uid)));
}

static void android_os_BinderInternal_setBinderProxyCountWatermarks(JNIEnv* env, jobject clazz,
                                                                    jint high, jint low)
{
    BpBinder::setBinderProxyCountWatermarks(high, low);
}

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

static const JNINativeMethod gBinderInternalMethods[] = {
@@ -981,7 +1027,11 @@ static const JNINativeMethod gBinderInternalMethods[] = {
    { "joinThreadPool", "()V", (void*)android_os_BinderInternal_joinThreadPool },
    { "disableBackgroundScheduling", "(Z)V", (void*)android_os_BinderInternal_disableBackgroundScheduling },
    { "setMaxThreads", "(I)V", (void*)android_os_BinderInternal_setMaxThreads },
    { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc }
    { "handleGc", "()V", (void*)android_os_BinderInternal_handleGc },
    { "nSetBinderProxyCountEnabled", "(Z)V", (void*)android_os_BinderInternal_setBinderProxyCountEnabled },
    { "nGetBinderProxyPerUidCounts", "()Landroid/util/SparseIntArray;", (void*)android_os_BinderInternal_getBinderProxyPerUidCounts },
    { "nGetBinderProxyCount", "(I)I", (void*)android_os_BinderInternal_getBinderProxyCount },
    { "nSetBinderProxyCountWatermarks", "(II)V", (void*)android_os_BinderInternal_setBinderProxyCountWatermarks}
};

const char* const kBinderInternalPathName = "com/android/internal/os/BinderInternal";
@@ -992,6 +1042,16 @@ static int int_register_android_os_BinderInternal(JNIEnv* env)

    gBinderInternalOffsets.mClass = MakeGlobalRefOrDie(env, clazz);
    gBinderInternalOffsets.mForceGc = GetStaticMethodIDOrDie(env, clazz, "forceBinderGc", "()V");
    gBinderInternalOffsets.mProxyLimitCallback = GetStaticMethodIDOrDie(env, clazz, "binderProxyLimitCallbackFromNative", "(I)V");

    jclass SparseIntArrayClass = FindClassOrDie(env, "android/util/SparseIntArray");
    gSparseIntArrayOffsets.classObject = MakeGlobalRefOrDie(env, SparseIntArrayClass);
    gSparseIntArrayOffsets.constructor = GetMethodIDOrDie(env, gSparseIntArrayOffsets.classObject,
                                                           "<init>", "()V");
    gSparseIntArrayOffsets.put = GetMethodIDOrDie(env, gSparseIntArrayOffsets.classObject, "put",
                                                   "(II)V");

    BpBinder::setLimitCallback(android_os_BinderInternal_proxyLimitcallback);

    return RegisterMethodsOrDie(
        env, kBinderInternalPathName,
+6 −1
Original line number Diff line number Diff line
@@ -19,7 +19,12 @@ LOCAL_SRC_FILES := \
	$(call all-java-files-under, src) \
	$(call all-Iaidl-files-under, src) \
	$(call all-java-files-under, DisabledTestApp/src) \
	$(call all-java-files-under, EnabledTestApp/src)
	$(call all-java-files-under, EnabledTestApp/src) \
	$(call all-java-files-under, BinderProxyCountingTestApp/src) \
	$(call all-java-files-under, BinderProxyCountingTestService/src) \
	$(call all-Iaidl-files-under, aidl)

LOCAL_AIDL_INCLUDES := $(LOCAL_PATH)/aidl

LOCAL_DX_FLAGS := --core-library
LOCAL_JACK_FLAGS := --multi-dex native
+1 −0
Original line number Diff line number Diff line
@@ -86,6 +86,7 @@
    <uses-permission android:name="android.permission.BROADCAST_STICKY" />

    <uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" />
    <uses-permission android:name="android.permission.KILL_UID" />

    <!-- location test permissions -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
+27 −0
Original line number Diff line number Diff line
# Copyright (C) 2017 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.

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := tests

LOCAL_STATIC_JAVA_LIBRARIES := coretests-aidl
LOCAL_SRC_FILES := $(call all-subdir-java-files)

LOCAL_PACKAGE_NAME := BinderProxyCountingTestApp
LOCAL_CERTIFICATE := platform

include $(BUILD_PACKAGE)
Loading