Loading android/app/jni/com_android_bluetooth_btservice_ActivityAttribution.cpp +0 −131 Original line number Diff line number Diff line Loading @@ -24,138 +24,10 @@ #include "com_android_bluetooth.h" #include "hardware/bt_activity_attribution.h" using bluetooth::activity_attribution::ActivityAttributionCallbacks; using bluetooth::activity_attribution::ActivityAttributionInterface; namespace android { static jmethodID method_onWakeup; static jmethodID method_onActivityLogsReady; static ActivityAttributionInterface* sActivityAttributionInterface = nullptr; static std::shared_timed_mutex interface_mutex; static jobject mCallbacksObj = nullptr; static std::shared_timed_mutex callbacks_mutex; class ActivityAttributionCallbacksImpl : public ActivityAttributionCallbacks { public: ~ActivityAttributionCallbacksImpl() = default; void OnWakeup(const Activity activity, const RawAddress& bd_addr) override { LOG(INFO) << __func__; std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; ScopedLocalRef<jbyteArray> addr( sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); if (!addr.get()) { LOG(ERROR) << "Failed to allocate jbyteArray for bd_addr of wakeup callback"; return; } sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)&bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWakeup, (jint)activity, addr.get()); } void OnActivityLogsReady( const std::vector<BtaaAggregationEntry> logs) override { LOG(INFO) << __func__; std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; jsize logs_size = logs.size() * sizeof(BtaaAggregationEntry); ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), sCallbackEnv->NewByteArray(logs_size)); if (!addr.get()) { LOG(ERROR) << "Failed to allocate jbyteArray for logs from activity " "logging callback"; return; } sCallbackEnv->SetByteArrayRegion(addr.get(), 0, logs_size, (jbyte*)logs.data()); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onActivityLogsReady, addr.get()); } }; static ActivityAttributionCallbacksImpl sActivityAttributionCallbacks; static void classInitNative(JNIEnv* env, jclass clazz) { method_onWakeup = env->GetMethodID(clazz, "onWakeup", "(I[B)V"); method_onActivityLogsReady = env->GetMethodID(clazz, "onActivityLogsReady", "([B)V"); LOG(INFO) << __func__ << ": succeeds"; } static void initNative(JNIEnv* env, jobject object) { std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex); std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex); const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { LOG(ERROR) << "Bluetooth module is not loaded"; return; } if (sActivityAttributionInterface != nullptr) { LOG(INFO) << "Cleaning up ActivityAttribution Interface before initializing..."; sActivityAttributionInterface->Cleanup(); sActivityAttributionInterface = nullptr; } if (mCallbacksObj != nullptr) { LOG(INFO) << "Cleaning up ActivityAttribution callback object"; env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = nullptr; } if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { LOG(ERROR) << "Failed to allocate Global Ref for ActivityAttribution Callbacks"; return; } sActivityAttributionInterface = (ActivityAttributionInterface*)btInf->get_profile_interface( BT_ACTIVITY_ATTRIBUTION_ID); if (sActivityAttributionInterface == nullptr) { LOG(ERROR) << "Failed to get ActivityAttribution Interface"; return; } sActivityAttributionInterface->RegisterCallbacks( &sActivityAttributionCallbacks); } static void cleanupNative(JNIEnv* env, jobject object) { std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex); std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex); const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { LOG(ERROR) << "Bluetooth module is not loaded"; return; } if (sActivityAttributionInterface != nullptr) { sActivityAttributionInterface->Cleanup(); sActivityAttributionInterface = nullptr; } if (mCallbacksObj != nullptr) { env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = nullptr; } } static void notifyActivityAttributionInfoNative(JNIEnv* env, jobject object, jint uid, jstring packageName, Loading Loading @@ -186,9 +58,6 @@ static void notifyActivityAttributionInfoNative(JNIEnv* env, jobject object, } static JNINativeMethod sMethods[] = { {"classInitNative", "()V", (void*)classInitNative}, {"initNative", "()V", (void*)initNative}, {"cleanupNative", "()V", (void*)cleanupNative}, {"notifyActivityAttributionInfoNative", "(ILjava/lang/String;Ljava/lang/String;)V", (void*)notifyActivityAttributionInfoNative}, Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +0 −5 Original line number Diff line number Diff line Loading @@ -716,7 +716,6 @@ public class AdapterService extends Service { mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this); mActivityAttributionService = new ActivityAttributionService(); mActivityAttributionService.start(); setAdapterService(this); Loading Loading @@ -1360,10 +1359,6 @@ public class AdapterService extends Service { mSdpManager = null; } if (mActivityAttributionService != null) { mActivityAttributionService.cleanup(); } if (mNativeAvailable) { debugLog("cleanup() - Cleaning up adapter native"); cleanupNative(); Loading android/app/src/com/android/bluetooth/btservice/activityAttribution/ActivityAttributionNativeInterface.java +1 −41 Original line number Diff line number Diff line Loading @@ -21,26 +21,15 @@ */ package com.android.bluetooth.btservice.activityattribution; import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.util.Arrays; /** ActivityAttribution Native Interface to/from JNI. */ public class ActivityAttributionNativeInterface { private static final boolean DBG = false; private static final String TAG = "ActivityAttributionNativeInterface"; @GuardedBy("INSTANCE_LOCK") private static ActivityAttributionNativeInterface sInstance; private static final Object INSTANCE_LOCK = new Object(); static { classInitNative(); } /** Get singleton instance. */ public static ActivityAttributionNativeInterface getInstance() { synchronized (INSTANCE_LOCK) { Loading @@ -51,40 +40,11 @@ public class ActivityAttributionNativeInterface { } } /** Initializes the native interface. */ public void init() { initNative(); } /** Cleanup the native interface. */ public void cleanup() { cleanupNative(); } /** Notify the UID and package name of the app, and the address of associated active device */ public void notifyActivityAttributionInfo(int uid, String packageName, String deviceAddress) { notifyActivityAttributionInfoNative(uid, packageName, deviceAddress); } // Callbacks from the native stack back into the Java framework. // All callbacks are routed via the Service which will disambiguate which // state machine the message should be routed to. private void onWakeup(int activity, byte[] address) { Log.i(TAG, "onWakeup() BTAA: " + activity); } private void onActivityLogsReady(byte[] logs) { Log.i(TAG, "onActivityLogsReady() BTAA: " + Arrays.toString(logs)); } // Native methods that call into the JNI interface private static native void classInitNative(); private native void initNative(); private native void cleanupNative(); private native void notifyActivityAttributionInfoNative( int uid, String packageName, String deviceAddress); } android/app/src/com/android/bluetooth/btservice/activityAttribution/ActivityAttributionService.java +11 −85 Original line number Diff line number Diff line Loading @@ -16,105 +16,31 @@ package com.android.bluetooth.btservice.activityattribution; import android.util.Log; import static java.util.Objects.requireNonNull; import java.util.Objects; import android.util.Log; /** * Service used for attributes wakeup, wakelock and Bluetooth traffic into per-app and per-device * based activities. */ public class ActivityAttributionService { private boolean mCleaningUp; private static ActivityAttributionService sActivityAttributionService; private static final boolean DBG = false; private static final String TAG = "ActivityAttributionService"; private static final String TAG = ActivityAttributionService.class.getSimpleName(); private final ActivityAttributionNativeInterface mActivityAttributionNativeInterface = Objects.requireNonNull( requireNonNull( ActivityAttributionNativeInterface.getInstance(), "ActivityAttributionNativeInterface " + "cannot be null when ActivityAttributionService starts"); /** Start and initialize the Activity Attribution service. */ public void start() { debugLog("start()"); if (sActivityAttributionService != null) { Log.e(TAG, "start() called twice"); return; } // Mark service as started setActivityAttributionService(this); } /** Cleans up the Activity Attribution service. */ public void cleanup() { debugLog("cleanup"); if (mCleaningUp) { debugLog("already doing cleanup"); return; } mCleaningUp = true; if (sActivityAttributionService == null) { debugLog("cleanup() called before start()"); return; } // Mark service as stopped setActivityAttributionService(null); // Cleanup native interface mActivityAttributionNativeInterface.cleanup(); } /** Get the ActivityAttributionService instance */ public static synchronized ActivityAttributionService getActivityAttributionService() { if (sActivityAttributionService == null) { Log.w(TAG, "getActivityAttributionService(): service is NULL"); return null; } if (!sActivityAttributionService.isAvailable()) { Log.w(TAG, "getActivityAttributionService(): service is not available"); return null; } return sActivityAttributionService; } /** Init JNI */ public void initJni() { debugLog("initJni()"); // Initialize native interface mActivityAttributionNativeInterface.init(); } "ActivityAttributionNativeInterface cannot be null"); /** Notify the UID and package name of the app, and the address of associated active device */ public void notifyActivityAttributionInfo(int uid, String packageName, String deviceAddress) { Log.d(TAG, "notifyActivityAttributionInfo" + " UID=" + uid + " packageName=" + packageName + " deviceAddress=" + deviceAddress); Log.d( TAG, "notifyActivityAttributionInfo()" + (" UID=" + uid) + (" packageName=" + packageName) + (" deviceAddress=" + deviceAddress)); mActivityAttributionNativeInterface.notifyActivityAttributionInfo( uid, packageName, deviceAddress); } private boolean isAvailable() { return !mCleaningUp; } private static synchronized void setActivityAttributionService( ActivityAttributionService instance) { debugLog("setActivityAttributionService(): set to: " + instance); sActivityAttributionService = instance; } private static void debugLog(String msg) { if (DBG) { Log.d(TAG, msg); } } } android/app/tests/unit/src/com/android/bluetooth/btservice/activityAttribution/ActivityAttributionServiceTest.java +0 −15 Original line number Diff line number Diff line Loading @@ -16,12 +16,9 @@ package com.android.bluetooth.btservice.activityattribution; import static com.google.common.truth.Truth.assertThat; import android.os.Binder; import android.os.Process; import org.junit.After; import org.junit.Assume; import org.junit.Before; import org.junit.Test; Loading @@ -30,24 +27,12 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public final class ActivityAttributionServiceTest { private static final String TAG = "ActivityAttributionServiceTest"; private ActivityAttributionService mActivityAttributionService; @Before public void setUp() { Assume.assumeTrue("Ignore test when the user is not primary.", isPrimaryUser()); mActivityAttributionService = new ActivityAttributionService(); mActivityAttributionService.start(); assertThat(mActivityAttributionService).isNotNull(); } @After public void tearDown() { if (!isPrimaryUser()) { return; } mActivityAttributionService.cleanup(); mActivityAttributionService = null; } private boolean isPrimaryUser() { Loading Loading
android/app/jni/com_android_bluetooth_btservice_ActivityAttribution.cpp +0 −131 Original line number Diff line number Diff line Loading @@ -24,138 +24,10 @@ #include "com_android_bluetooth.h" #include "hardware/bt_activity_attribution.h" using bluetooth::activity_attribution::ActivityAttributionCallbacks; using bluetooth::activity_attribution::ActivityAttributionInterface; namespace android { static jmethodID method_onWakeup; static jmethodID method_onActivityLogsReady; static ActivityAttributionInterface* sActivityAttributionInterface = nullptr; static std::shared_timed_mutex interface_mutex; static jobject mCallbacksObj = nullptr; static std::shared_timed_mutex callbacks_mutex; class ActivityAttributionCallbacksImpl : public ActivityAttributionCallbacks { public: ~ActivityAttributionCallbacksImpl() = default; void OnWakeup(const Activity activity, const RawAddress& bd_addr) override { LOG(INFO) << __func__; std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; ScopedLocalRef<jbyteArray> addr( sCallbackEnv.get(), sCallbackEnv->NewByteArray(sizeof(RawAddress))); if (!addr.get()) { LOG(ERROR) << "Failed to allocate jbyteArray for bd_addr of wakeup callback"; return; } sCallbackEnv->SetByteArrayRegion(addr.get(), 0, sizeof(RawAddress), (jbyte*)&bd_addr); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onWakeup, (jint)activity, addr.get()); } void OnActivityLogsReady( const std::vector<BtaaAggregationEntry> logs) override { LOG(INFO) << __func__; std::shared_lock<std::shared_timed_mutex> lock(callbacks_mutex); CallbackEnv sCallbackEnv(__func__); if (!sCallbackEnv.valid() || mCallbacksObj == nullptr) return; jsize logs_size = logs.size() * sizeof(BtaaAggregationEntry); ScopedLocalRef<jbyteArray> addr(sCallbackEnv.get(), sCallbackEnv->NewByteArray(logs_size)); if (!addr.get()) { LOG(ERROR) << "Failed to allocate jbyteArray for logs from activity " "logging callback"; return; } sCallbackEnv->SetByteArrayRegion(addr.get(), 0, logs_size, (jbyte*)logs.data()); sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onActivityLogsReady, addr.get()); } }; static ActivityAttributionCallbacksImpl sActivityAttributionCallbacks; static void classInitNative(JNIEnv* env, jclass clazz) { method_onWakeup = env->GetMethodID(clazz, "onWakeup", "(I[B)V"); method_onActivityLogsReady = env->GetMethodID(clazz, "onActivityLogsReady", "([B)V"); LOG(INFO) << __func__ << ": succeeds"; } static void initNative(JNIEnv* env, jobject object) { std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex); std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex); const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { LOG(ERROR) << "Bluetooth module is not loaded"; return; } if (sActivityAttributionInterface != nullptr) { LOG(INFO) << "Cleaning up ActivityAttribution Interface before initializing..."; sActivityAttributionInterface->Cleanup(); sActivityAttributionInterface = nullptr; } if (mCallbacksObj != nullptr) { LOG(INFO) << "Cleaning up ActivityAttribution callback object"; env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = nullptr; } if ((mCallbacksObj = env->NewGlobalRef(object)) == nullptr) { LOG(ERROR) << "Failed to allocate Global Ref for ActivityAttribution Callbacks"; return; } sActivityAttributionInterface = (ActivityAttributionInterface*)btInf->get_profile_interface( BT_ACTIVITY_ATTRIBUTION_ID); if (sActivityAttributionInterface == nullptr) { LOG(ERROR) << "Failed to get ActivityAttribution Interface"; return; } sActivityAttributionInterface->RegisterCallbacks( &sActivityAttributionCallbacks); } static void cleanupNative(JNIEnv* env, jobject object) { std::unique_lock<std::shared_timed_mutex> interface_lock(interface_mutex); std::unique_lock<std::shared_timed_mutex> callbacks_lock(callbacks_mutex); const bt_interface_t* btInf = getBluetoothInterface(); if (btInf == nullptr) { LOG(ERROR) << "Bluetooth module is not loaded"; return; } if (sActivityAttributionInterface != nullptr) { sActivityAttributionInterface->Cleanup(); sActivityAttributionInterface = nullptr; } if (mCallbacksObj != nullptr) { env->DeleteGlobalRef(mCallbacksObj); mCallbacksObj = nullptr; } } static void notifyActivityAttributionInfoNative(JNIEnv* env, jobject object, jint uid, jstring packageName, Loading Loading @@ -186,9 +58,6 @@ static void notifyActivityAttributionInfoNative(JNIEnv* env, jobject object, } static JNINativeMethod sMethods[] = { {"classInitNative", "()V", (void*)classInitNative}, {"initNative", "()V", (void*)initNative}, {"cleanupNative", "()V", (void*)cleanupNative}, {"notifyActivityAttributionInfoNative", "(ILjava/lang/String;Ljava/lang/String;)V", (void*)notifyActivityAttributionInfoNative}, Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +0 −5 Original line number Diff line number Diff line Loading @@ -716,7 +716,6 @@ public class AdapterService extends Service { mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this); mActivityAttributionService = new ActivityAttributionService(); mActivityAttributionService.start(); setAdapterService(this); Loading Loading @@ -1360,10 +1359,6 @@ public class AdapterService extends Service { mSdpManager = null; } if (mActivityAttributionService != null) { mActivityAttributionService.cleanup(); } if (mNativeAvailable) { debugLog("cleanup() - Cleaning up adapter native"); cleanupNative(); Loading
android/app/src/com/android/bluetooth/btservice/activityAttribution/ActivityAttributionNativeInterface.java +1 −41 Original line number Diff line number Diff line Loading @@ -21,26 +21,15 @@ */ package com.android.bluetooth.btservice.activityattribution; import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.util.Arrays; /** ActivityAttribution Native Interface to/from JNI. */ public class ActivityAttributionNativeInterface { private static final boolean DBG = false; private static final String TAG = "ActivityAttributionNativeInterface"; @GuardedBy("INSTANCE_LOCK") private static ActivityAttributionNativeInterface sInstance; private static final Object INSTANCE_LOCK = new Object(); static { classInitNative(); } /** Get singleton instance. */ public static ActivityAttributionNativeInterface getInstance() { synchronized (INSTANCE_LOCK) { Loading @@ -51,40 +40,11 @@ public class ActivityAttributionNativeInterface { } } /** Initializes the native interface. */ public void init() { initNative(); } /** Cleanup the native interface. */ public void cleanup() { cleanupNative(); } /** Notify the UID and package name of the app, and the address of associated active device */ public void notifyActivityAttributionInfo(int uid, String packageName, String deviceAddress) { notifyActivityAttributionInfoNative(uid, packageName, deviceAddress); } // Callbacks from the native stack back into the Java framework. // All callbacks are routed via the Service which will disambiguate which // state machine the message should be routed to. private void onWakeup(int activity, byte[] address) { Log.i(TAG, "onWakeup() BTAA: " + activity); } private void onActivityLogsReady(byte[] logs) { Log.i(TAG, "onActivityLogsReady() BTAA: " + Arrays.toString(logs)); } // Native methods that call into the JNI interface private static native void classInitNative(); private native void initNative(); private native void cleanupNative(); private native void notifyActivityAttributionInfoNative( int uid, String packageName, String deviceAddress); }
android/app/src/com/android/bluetooth/btservice/activityAttribution/ActivityAttributionService.java +11 −85 Original line number Diff line number Diff line Loading @@ -16,105 +16,31 @@ package com.android.bluetooth.btservice.activityattribution; import android.util.Log; import static java.util.Objects.requireNonNull; import java.util.Objects; import android.util.Log; /** * Service used for attributes wakeup, wakelock and Bluetooth traffic into per-app and per-device * based activities. */ public class ActivityAttributionService { private boolean mCleaningUp; private static ActivityAttributionService sActivityAttributionService; private static final boolean DBG = false; private static final String TAG = "ActivityAttributionService"; private static final String TAG = ActivityAttributionService.class.getSimpleName(); private final ActivityAttributionNativeInterface mActivityAttributionNativeInterface = Objects.requireNonNull( requireNonNull( ActivityAttributionNativeInterface.getInstance(), "ActivityAttributionNativeInterface " + "cannot be null when ActivityAttributionService starts"); /** Start and initialize the Activity Attribution service. */ public void start() { debugLog("start()"); if (sActivityAttributionService != null) { Log.e(TAG, "start() called twice"); return; } // Mark service as started setActivityAttributionService(this); } /** Cleans up the Activity Attribution service. */ public void cleanup() { debugLog("cleanup"); if (mCleaningUp) { debugLog("already doing cleanup"); return; } mCleaningUp = true; if (sActivityAttributionService == null) { debugLog("cleanup() called before start()"); return; } // Mark service as stopped setActivityAttributionService(null); // Cleanup native interface mActivityAttributionNativeInterface.cleanup(); } /** Get the ActivityAttributionService instance */ public static synchronized ActivityAttributionService getActivityAttributionService() { if (sActivityAttributionService == null) { Log.w(TAG, "getActivityAttributionService(): service is NULL"); return null; } if (!sActivityAttributionService.isAvailable()) { Log.w(TAG, "getActivityAttributionService(): service is not available"); return null; } return sActivityAttributionService; } /** Init JNI */ public void initJni() { debugLog("initJni()"); // Initialize native interface mActivityAttributionNativeInterface.init(); } "ActivityAttributionNativeInterface cannot be null"); /** Notify the UID and package name of the app, and the address of associated active device */ public void notifyActivityAttributionInfo(int uid, String packageName, String deviceAddress) { Log.d(TAG, "notifyActivityAttributionInfo" + " UID=" + uid + " packageName=" + packageName + " deviceAddress=" + deviceAddress); Log.d( TAG, "notifyActivityAttributionInfo()" + (" UID=" + uid) + (" packageName=" + packageName) + (" deviceAddress=" + deviceAddress)); mActivityAttributionNativeInterface.notifyActivityAttributionInfo( uid, packageName, deviceAddress); } private boolean isAvailable() { return !mCleaningUp; } private static synchronized void setActivityAttributionService( ActivityAttributionService instance) { debugLog("setActivityAttributionService(): set to: " + instance); sActivityAttributionService = instance; } private static void debugLog(String msg) { if (DBG) { Log.d(TAG, msg); } } }
android/app/tests/unit/src/com/android/bluetooth/btservice/activityAttribution/ActivityAttributionServiceTest.java +0 −15 Original line number Diff line number Diff line Loading @@ -16,12 +16,9 @@ package com.android.bluetooth.btservice.activityattribution; import static com.google.common.truth.Truth.assertThat; import android.os.Binder; import android.os.Process; import org.junit.After; import org.junit.Assume; import org.junit.Before; import org.junit.Test; Loading @@ -30,24 +27,12 @@ import org.junit.runners.JUnit4; @RunWith(JUnit4.class) public final class ActivityAttributionServiceTest { private static final String TAG = "ActivityAttributionServiceTest"; private ActivityAttributionService mActivityAttributionService; @Before public void setUp() { Assume.assumeTrue("Ignore test when the user is not primary.", isPrimaryUser()); mActivityAttributionService = new ActivityAttributionService(); mActivityAttributionService.start(); assertThat(mActivityAttributionService).isNotNull(); } @After public void tearDown() { if (!isPrimaryUser()) { return; } mActivityAttributionService.cleanup(); mActivityAttributionService = null; } private boolean isPrimaryUser() { Loading