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

Commit be639265 authored by Michael Sun's avatar Michael Sun Committed by Gerrit Code Review
Browse files

Merge "btaa: introduce activity attribution Java service"

parents d3cbe096 4b88b5a3
Loading
Loading
Loading
Loading
+76 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2020 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.
 */

/*
 * Defines the native interface that is used by state machine/service to
 * send or receive messages from the native stack. This file is registered
 * for the native methods in the corresponding JNI C++ file.
 */
package com.android.bluetooth.btservice.activityattribution;

import android.util.Log;

import com.android.internal.annotations.GuardedBy;

/** 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) {
            if (sInstance == null) {
                sInstance = new ActivityAttributionNativeInterface();
            }
            return sInstance;
        }
    }

    /** Initializes the native interface. */
    public void init() {
        initNative();
    }

    /** Cleanup the native interface. */
    public void cleanup() {
        cleanupNative();
    }

    // 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);
    }

    // Native methods that call into the JNI interface
    private static native void classInitNative();

    private native void initNative();

    private native void cleanupNative();
}
+113 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2020 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.bluetooth.btservice.activityattribution;

import android.util.Log;

import java.util.Objects;

/**
 * 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";

    ActivityAttributionNativeInterface mActivityAttributionNativeInterface;

    /** Start and initialize the Activity Attribution service. */
    public void start() {
        debugLog("start()");

        if (sActivityAttributionService != null) {
            Log.e(TAG, "start() called twice");
            return;
        }

        mActivityAttributionNativeInterface =
                Objects.requireNonNull(
                        ActivityAttributionNativeInterface.getInstance(),
                        "ActivityAttributionNativeInterface "
                                + "cannot be null when ActivityAttributionService starts");

        // 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();
        mActivityAttributionNativeInterface = null;
    }

    /** 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();
    }

    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);
        }
    }
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -14,6 +14,7 @@ android_test {
    ],
    ],


    static_libs: [
    static_libs: [
        "androidx.test.ext.truth",
        "androidx.test.rules",
        "androidx.test.rules",
        "mockito-target",
        "mockito-target",
        "androidx.test.espresso.intents",
        "androidx.test.espresso.intents",
+58 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright 2020 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.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;
import org.junit.runner.RunWith;
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();
        assertThat(mActivityAttributionService).isNotNull();
    }

    @After
    public void tearDown() {
        if (!isPrimaryUser()) {
            return;
        }
        mActivityAttributionService.cleanup();
        mActivityAttributionService = null;
    }

    private boolean isPrimaryUser() {
        return Binder.getCallingUid() == Process.BLUETOOTH_UID;
    }

    @Test
    public void testSetUpAndTearDown() {}
}