From 67c0daf54589d9bc349171ae31ae969651d107e4 Mon Sep 17 00:00:00 2001 From: Luca Stefani Date: Fri, 3 Apr 2020 16:20:12 +0200 Subject: [PATCH] Remove LineageAudioService Change-Id: I4aea4c62154a0f7d9d6d96e68ddf2bd401458fab --- lineage/jni/Android.bp | 50 ---- lineage/jni/src/onload.cpp | 47 ---- ..._platform_internal_LineageAudioService.cpp | 179 ------------ .../internal/LineageAudioService.java | 160 ----------- lineage/res/AndroidManifest.xml | 8 - lineage/res/res/values/strings.xml | 4 - .../app/LineageContextConstants.java | 8 - .../lineageos/media/AudioSessionInfo.aidl | 19 -- .../lineageos/media/AudioSessionInfo.java | 176 ------------ .../lineageos/media/ILineageAudioService.aidl | 26 -- .../lineageos/media/LineageAudioManager.java | 172 ------------ tests/AndroidManifest.xml | 1 - .../media/unit/LineageAudioManagerTest.java | 260 ------------------ 13 files changed, 1110 deletions(-) delete mode 100644 lineage/jni/Android.bp delete mode 100644 lineage/jni/src/onload.cpp delete mode 100644 lineage/jni/src/org_lineageos_platform_internal_LineageAudioService.cpp delete mode 100644 lineage/lib/main/java/org/lineageos/platform/internal/LineageAudioService.java delete mode 100644 sdk/src/java/lineageos/media/AudioSessionInfo.aidl delete mode 100644 sdk/src/java/lineageos/media/AudioSessionInfo.java delete mode 100644 sdk/src/java/lineageos/media/ILineageAudioService.aidl delete mode 100644 sdk/src/java/lineageos/media/LineageAudioManager.java delete mode 100644 tests/src/org/lineageos/tests/media/unit/LineageAudioManagerTest.java diff --git a/lineage/jni/Android.bp b/lineage/jni/Android.bp deleted file mode 100644 index bf57ee1a..00000000 --- a/lineage/jni/Android.bp +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (C) 2018-2020 The LineageOS 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. -// - -cc_library_shared { - name: "liblineage-sdk_platform_jni", - system_ext_specific: true, - srcs: [ - "src/org_lineageos_platform_internal_LineageAudioService.cpp", - "src/onload.cpp", - ], - - include_dirs: [ - "frameworks/base/core/jni", - "frameworks/av/include", - "hardware/libhardware/include", - ], - - shared_libs: [ - "libandroid_runtime", - "libaudioclient", - "libcutils", - "libhardware", - "liblog", - "libmedia", - "libutils", - ], - - header_libs: [ - "jni_headers", - ], - - cflags: [ - "-Wall", - "-Werror", - "-Wno-unused-parameter", - ], -} diff --git a/lineage/jni/src/onload.cpp b/lineage/jni/src/onload.cpp deleted file mode 100644 index b5903eb0..00000000 --- a/lineage/jni/src/onload.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2016 The CyanogenMod Project - * 2017,2020 The LineageOS 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. - */ - -#include - -#include "jni.h" -#include "utils/Log.h" -#include "utils/misc.h" - -namespace android { - -int register_org_lineageos_platform_internal_LineageAudioService(JNIEnv* env); - -}; - -using namespace android; - -extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) -{ - JNIEnv* env = NULL; - jint result = -1; - - if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { - ALOGE("GetEnv failed!"); - return result; - } - ALOG_ASSERT(env, "Could not retrieve the env!"); - - register_org_lineageos_platform_internal_LineageAudioService(env); - - return JNI_VERSION_1_4; -} - diff --git a/lineage/jni/src/org_lineageos_platform_internal_LineageAudioService.cpp b/lineage/jni/src/org_lineageos_platform_internal_LineageAudioService.cpp deleted file mode 100644 index dff47e2c..00000000 --- a/lineage/jni/src/org_lineageos_platform_internal_LineageAudioService.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* -** -** Copyright 2016, The CyanogenMod Project -** 2017,2020 The LineageOS 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. -*/ - -//#define LOG_NDEBUG 0 - -#define LOG_TAG "LineageAudioService-JNI" - -#include - -#include -#include "core_jni_helpers.h" -#include "android_media_AudioErrors.h" - -#include -/* -#include -*/ - -#include -#include -#include - -// ---------------------------------------------------------------------------- - -namespace android { - -/* -static const char* const kClassPathName = "org/lineageos/platform/internal/LineageAudioService"; - -static jclass gArrayListClass; -static struct { - jmethodID add; - jmethodID toArray; -} gArrayListMethods; - -static struct { - jmethodID postAudioSessionEventFromNative; -} gAudioSessionEventHandlerMethods; - -static jclass gAudioSessionInfoClass; -static jmethodID gAudioSessionInfoCstor; - -static jobject gThiz; - -static Mutex gCallbackLock; - -// ---------------------------------------------------------------------------- - -static void -org_lineageos_platform_internal_LineageAudioService_session_info_callback(int event, - sp& info, bool added) -{ - AutoMutex _l(gCallbackLock); - - JNIEnv *env = AndroidRuntime::getJNIEnv(); - if (env == NULL) { - return; - } - - jobject jSession = env->NewObject(gAudioSessionInfoClass, gAudioSessionInfoCstor, - info->mSessionId, info->mStream, info->mFlags, info->mChannelMask, info->mUid); - - env->CallVoidMethod(gThiz, - gAudioSessionEventHandlerMethods.postAudioSessionEventFromNative, - event, jSession, added); - - env->DeleteLocalRef(jSession); -} - -static void -org_lineageos_platform_internal_LineageAudioService_registerAudioSessionCallback( - JNIEnv *env, jobject thiz, jboolean enabled) -{ - if (gThiz == NULL) { - gThiz = env->NewGlobalRef(thiz); - } - - AudioSystem::setAudioSessionCallback( enabled ? - org_lineageos_platform_internal_LineageAudioService_session_info_callback : NULL); -} - -static jint -org_lineageos_platform_internal_LineageAudioService_listAudioSessions(JNIEnv *env, jobject thiz, - jint streams, jobject jSessions) -{ - ALOGV("listAudioSessions"); - - if (jSessions == NULL) { - ALOGE("listAudioSessions NULL arraylist"); - return (jint)AUDIO_JAVA_BAD_VALUE; - } - if (!env->IsInstanceOf(jSessions, gArrayListClass)) { - ALOGE("listAudioSessions not an arraylist"); - return (jint)AUDIO_JAVA_BAD_VALUE; - } - - status_t status; - Vector< sp> sessions; - - status = AudioSystem::listAudioSessions((audio_stream_type_t)streams, sessions); - if (status != NO_ERROR) { - ALOGE("AudioSystem::listAudioSessions error %d", status); - } else { - ALOGV("AudioSystem::listAudioSessions count=%zu", sessions.size()); - } - - jint jStatus = nativeToJavaStatus(status); - if (jStatus != AUDIO_JAVA_SUCCESS) { - goto exit; - } - - for (size_t i = 0; i < sessions.size(); i++) { - const sp& s = sessions.itemAt(i); - - jobject jSession = env->NewObject(gAudioSessionInfoClass, gAudioSessionInfoCstor, - s->mSessionId, s->mStream, s->mFlags, s->mChannelMask, s->mUid); - - if (jSession == NULL) { - jStatus = (jint)AUDIO_JAVA_ERROR; - goto exit; - } - - env->CallBooleanMethod(jSessions, gArrayListMethods.add, jSession); - env->DeleteLocalRef(jSession); - } - -exit: - return jStatus; -} - - -// ---------------------------------------------------------------------------- - -static JNINativeMethod gMethods[] = { - {"native_listAudioSessions", "(ILjava/util/ArrayList;)I", - (void *)org_lineageos_platform_internal_LineageAudioService_listAudioSessions}, - {"native_registerAudioSessionCallback", "(Z)V", - (void *)org_lineageos_platform_internal_LineageAudioService_registerAudioSessionCallback}, -}; - -*/ - -int register_org_lineageos_platform_internal_LineageAudioService(JNIEnv *env) -{ - return 0; -/* - jclass arrayListClass = FindClassOrDie(env, "java/util/ArrayList"); - gArrayListClass = MakeGlobalRefOrDie(env, arrayListClass); - gArrayListMethods.add = GetMethodIDOrDie(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); - gArrayListMethods.toArray = GetMethodIDOrDie(env, arrayListClass, "toArray", "()[Ljava/lang/Object;"); - - jclass audioSessionInfoClass = FindClassOrDie(env, "lineageos/media/AudioSessionInfo"); - gAudioSessionInfoClass = MakeGlobalRefOrDie(env, audioSessionInfoClass); - gAudioSessionInfoCstor = GetMethodIDOrDie(env, audioSessionInfoClass, "", "(IIIII)V"); - - gAudioSessionEventHandlerMethods.postAudioSessionEventFromNative = - GetMethodIDOrDie(env, env->FindClass(kClassPathName), - "audioSessionCallbackFromNative", "(ILlineageos/media/AudioSessionInfo;Z)V"); - - return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods)); -*/ -} - -} /* namespace android */ diff --git a/lineage/lib/main/java/org/lineageos/platform/internal/LineageAudioService.java b/lineage/lib/main/java/org/lineageos/platform/internal/LineageAudioService.java deleted file mode 100644 index 7a1e2d9c..00000000 --- a/lineage/lib/main/java/org/lineageos/platform/internal/LineageAudioService.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2016 The CyanogenMod 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 org.lineageos.platform.internal; - -import android.content.Context; -import android.content.Intent; -import android.os.Binder; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.UserHandle; -import android.util.Log; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; - -import lineageos.app.LineageContextConstants; -import lineageos.media.AudioSessionInfo; -import lineageos.media.LineageAudioManager; -import lineageos.media.ILineageAudioService; -import lineageos.platform.Manifest; - -public class LineageAudioService extends LineageSystemService { - - private static final String TAG = "LineageAudioService"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); - - private final Context mContext; - - private static final int AUDIO_STATUS_OK = 0; - - //keep in sync with include/media/AudioPolicy.h - private final static int AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE = 10; - - public LineageAudioService(Context context) { - super(context); - - mContext = context; - } - - @Override - public String getFeatureDeclaration() { - return LineageContextConstants.Features.AUDIO; - } - - @Override - public void onStart() { - if (!NativeHelper.isNativeLibraryAvailable()) { - Log.wtf(TAG, "Lineage Audio service started by system server by native library is" + - "unavailable. Service will be unavailable."); - return; - } - publishBinderService(LineageContextConstants.LINEAGE_AUDIO_SERVICE, mBinder); - } - - @Override - public void onBootPhase(int phase) { - if (phase == PHASE_BOOT_COMPLETED) { - if (NativeHelper.isNativeLibraryAvailable()) { - native_registerAudioSessionCallback(true); - } - } - } - - private final IBinder mBinder = new ILineageAudioService.Stub() { - - @Override - public List listAudioSessions(int streamType) throws RemoteException { - final ArrayList sessions = new ArrayList(); - if (!NativeHelper.isNativeLibraryAvailable()) { - // no sessions for u - return sessions; - } - - int status = native_listAudioSessions(streamType, sessions); - if (status != AUDIO_STATUS_OK) { - Log.e(TAG, "Error retrieving audio sessions! status=" + status); - } - - return sessions; - } - - @Override - public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); - - pw.println(); - pw.println("Lineage Audio Service State:"); - try { - List sessions = listAudioSessions(-1); - if (sessions.size() > 0) { - pw.println(" Audio sessions:"); - for (AudioSessionInfo info : sessions) { - pw.println(" " + info.toString()); - } - } else { - pw.println(" No active audio sessions"); - } - } catch (RemoteException e) { - // nothing - } - } - }; - - private void broadcastSessionChanged(boolean added, AudioSessionInfo sessionInfo) { - Intent i = new Intent(LineageAudioManager.ACTION_AUDIO_SESSIONS_CHANGED); - i.putExtra(LineageAudioManager.EXTRA_SESSION_INFO, sessionInfo); - i.putExtra(LineageAudioManager.EXTRA_SESSION_ADDED, added); - - sendBroadcastToAll(i, Manifest.permission.OBSERVE_AUDIO_SESSIONS); - } - - private void sendBroadcastToAll(Intent intent, String receiverPermission) { - intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); - intent.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); - - final long ident = Binder.clearCallingIdentity(); - try { - if (DEBUG) Log.d(TAG, "Sending broadcast: " + intent.toString()); - - mContext.sendBroadcastAsUser(intent, UserHandle.ALL, receiverPermission); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - - /* - * Handles events from JNI - */ - private synchronized void audioSessionCallbackFromNative(int event, - AudioSessionInfo sessionInfo, boolean added) { - - switch (event) { - case AUDIO_OUTPUT_SESSION_EFFECTS_UPDATE: - broadcastSessionChanged(added, sessionInfo); - break; - default: - Log.e(TAG, "Unknown event " + event); - } - } - - private native final void native_registerAudioSessionCallback(boolean enabled); - - private native final int native_listAudioSessions( - int stream, ArrayList sessions); -} diff --git a/lineage/res/AndroidManifest.xml b/lineage/res/AndroidManifest.xml index edd08b54..845e8738 100644 --- a/lineage/res/AndroidManifest.xml +++ b/lineage/res/AndroidManifest.xml @@ -27,7 +27,6 @@ - @@ -64,13 +63,6 @@ android:description="@string/permdesc_writeSecureSettings" android:protectionLevel="signature|privileged|development" /> - - - manage LiveDisplay settings Allows an app to configure advanced display settings. - - observe audio session changes - Allows an app to observe audio streams being created and destroyed. - manage remote settings Allows an app to manage remote settings diff --git a/sdk/src/java/lineageos/app/LineageContextConstants.java b/sdk/src/java/lineageos/app/LineageContextConstants.java index f8061059..9543e44b 100644 --- a/sdk/src/java/lineageos/app/LineageContextConstants.java +++ b/sdk/src/java/lineageos/app/LineageContextConstants.java @@ -70,14 +70,6 @@ public final class LineageContextConstants { */ public static final String LINEAGE_LIVEDISPLAY_SERVICE = "lineagelivedisplay"; - - /** - * Manages enhanced audio functionality - * - * @hide - */ - public static final String LINEAGE_AUDIO_SERVICE = "lineageaudio"; - /** * Use with {@link android.content.Context#getSystemService} to retrieve a * {@link lineageos.trust.TrustInterface} to access the Trust interface. diff --git a/sdk/src/java/lineageos/media/AudioSessionInfo.aidl b/sdk/src/java/lineageos/media/AudioSessionInfo.aidl deleted file mode 100644 index 2ff9b22d..00000000 --- a/sdk/src/java/lineageos/media/AudioSessionInfo.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2016 The CyanogenMod 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 lineageos.media; - -parcelable AudioSessionInfo; diff --git a/sdk/src/java/lineageos/media/AudioSessionInfo.java b/sdk/src/java/lineageos/media/AudioSessionInfo.java deleted file mode 100644 index 8d588d84..00000000 --- a/sdk/src/java/lineageos/media/AudioSessionInfo.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2016 The CyanogenMod 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 lineageos.media; - -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Objects; - -import lineageos.os.Build; -import lineageos.os.Concierge; -import lineageos.os.Concierge.ParcelInfo; - -/** - * AudioSessionInfo represents a single instance of an audio session. - * Audio sessions are created when a new AudioTrack is started, and - * removed when the track is released. Audio session identifiers - * are unique (but may be reused) and are used as a handle by which - * an application may create audio effects on the output stream. - * - * A list of global audio sessions can be obtained by calling - * listAudioSessions() via {@link LineageAudioManager}, or a component can listen - * for the {@link LineageAudioManager#ACTION_AUDIO_SESSIONS_CHANGED} broadcast. - * - * @hide - */ -public final class AudioSessionInfo implements Parcelable { - - /** - * Unique session id - */ - private final int mSessionId; - /** - * Stream type - see audio_stream_type_t - */ - private final int mStream; - /** - * Output flags - see audio_output_flags_t - */ - private final int mFlags; - /** - * Channel mask - see audio_channel_mask_t - */ - private final int mChannelMask; - /** - * UID of the source application - */ - private final int mUid; - - public AudioSessionInfo(int sessionId, int stream, int flags, int channelMask, int uid) { - mSessionId = sessionId; - mStream = stream; - mFlags = flags; - mChannelMask = channelMask; - mUid = uid; - } - - private AudioSessionInfo(Parcel in) { - // Read parcelable version via the Concierge - ParcelInfo parcelInfo = Concierge.receiveParcel(in); - int parcelableVersion = parcelInfo.getParcelVersion(); - - /* -- FIG -- */ - mSessionId = in.readInt(); - mStream = in.readInt(); - mFlags = in.readInt(); - mChannelMask = in.readInt(); - mUid = in.readInt(); - - if (parcelableVersion > Build.LINEAGE_VERSION_CODES.FIG) { - // next-gen mind-altering shit goes here - } - - // Complete parcel info for the concierge - parcelInfo.complete(); - } - - public int getSessionId() { - return mSessionId; - } - - public int getStream() { - return mStream; - } - - public int getFlags() { - return mFlags; - } - - public int getChannelMask() { - return mChannelMask; - } - - public int getUid() { - return mUid; - } - - @Override - public String toString() { - return String.format( - "audioSessionInfo[sessionId=%d, stream=%d, flags=%d, channelMask=%d, uid=%d", - mSessionId, mStream, mFlags, mChannelMask, mUid); - } - - @Override - public int hashCode() { - return Objects.hash(mSessionId, mStream, mFlags, mChannelMask, mUid); - } - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof AudioSessionInfo)) { - return false; - } - - final AudioSessionInfo other = (AudioSessionInfo)obj; - return this == other || - (mSessionId == other.mSessionId && - mStream == other.mStream && - mFlags == other.mFlags && - mChannelMask == other.mChannelMask && - mUid == other.mUid); - } - - /** @hide */ - @Override - public int describeContents() { - return 0; - } - - /** @hide */ - @Override - public void writeToParcel(Parcel dest, int flags) { - // Tell the concierge to prepare the parcel - ParcelInfo parcelInfo = Concierge.prepareParcel(dest); - - /* -- FIG -- */ - dest.writeInt(mSessionId); - dest.writeInt(mStream); - dest.writeInt(mFlags); - dest.writeInt(mChannelMask); - dest.writeInt(mUid); - - parcelInfo.complete(); - } - - /** @hide */ - public static final Creator CREATOR = new Creator() { - - @Override - public AudioSessionInfo createFromParcel(Parcel source) { - return new AudioSessionInfo(source); - } - - @Override - public AudioSessionInfo[] newArray(int size) { - return new AudioSessionInfo[size]; - } - }; -} - - diff --git a/sdk/src/java/lineageos/media/ILineageAudioService.aidl b/sdk/src/java/lineageos/media/ILineageAudioService.aidl deleted file mode 100644 index 71b1d93b..00000000 --- a/sdk/src/java/lineageos/media/ILineageAudioService.aidl +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2016 The CyanogenMod 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 lineageos.media; - -import lineageos.media.AudioSessionInfo; - -/** @hide */ -interface ILineageAudioService { - - List listAudioSessions(int streamType); - -} diff --git a/sdk/src/java/lineageos/media/LineageAudioManager.java b/sdk/src/java/lineageos/media/LineageAudioManager.java deleted file mode 100644 index 5854520d..00000000 --- a/sdk/src/java/lineageos/media/LineageAudioManager.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2016 The CyanogenMod 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 lineageos.media; - -import android.content.Context; -import android.os.IBinder; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.util.Log; - -import java.util.Collections; -import java.util.List; - -import lineageos.app.LineageContextConstants; - -/** - * Manager for extended audio system capabilities provided by - * LineageOS. - * - * Currently, this API provides an application the ability to - * query active global audio sessions, and receive broadcasts - * when new audio sessions are created and destroyed. - * - * Applications wishing to receive audio session information - * should register for the {@link ACTION_AUDIO_SESSIONS_CHANGED} - * broadcast. This broadcast requires an application to hold the - * {@link lineageos.permission.OBSERVE_AUDIO_SESSIONS} - * permission. When receiving the broadcast, {@link EXTRA_SESSION_INFO} - * will hold the {@link AudioSessionInfo} object associated - * with the session. {@link EXTRA_SESSION_ADDED} will hold - * a boolean value, true if the session is added, false if it - * is being removed. - * - * It is important for applications to be cautious about which - * audio streams effects are attached to when using this API as - * it may interfere with their normal operation. An equalizer - * application for example would only want to react to streams - * with the type of {@link android.media.AudioManager.STREAM_MUSIC}. - * - * @see android.media.AudioManager - * - * @hide - */ -public final class LineageAudioManager { - - private static final String TAG = "LineageAudioManager"; - - /** - * Broadcast sent when audio session are added and removed. - */ - public static final String ACTION_AUDIO_SESSIONS_CHANGED = - "lineageos.intent.action.ACTION_AUDIO_SESSIONS_CHANGED"; - - /** - * Extra containing {@link AudioSessionInfo} - */ - public static final String EXTRA_SESSION_INFO = "session_info"; - - /** - * Boolean extra, true if session is being added. - */ - public static final String EXTRA_SESSION_ADDED = "added"; - - private Context mContext; - - private static LineageAudioManager sInstance; - private static ILineageAudioService sService; - - /** - * @hide to prevent subclassing from outside of the framework - */ - private LineageAudioManager(Context context) { - Context appContext = context.getApplicationContext(); - if (appContext != null) { - mContext = appContext; - } else { - mContext = context; - - } - sService = getService(); - - if (!context.getPackageManager().hasSystemFeature( - LineageContextConstants.Features.AUDIO) || !checkService()) { - Log.wtf(TAG, "Unable to get LineageAudioService. The service either" + - " crashed, was not started, or the interface has been called to early in" + - " SystemServer init"); - } - } - - /** - * Get or create an instance of the {@link lineageos.media.LineageAudioManager} - * @param context - * @return {@link LineageAudioManager} - */ - public synchronized static LineageAudioManager getInstance(Context context) { - if (sInstance == null) { - sInstance = new LineageAudioManager(context); - } - return sInstance; - } - - /** @hide */ - public static ILineageAudioService getService() { - if (sService != null) { - return sService; - } - IBinder b = ServiceManager.getService(LineageContextConstants.LINEAGE_AUDIO_SERVICE); - if (b != null) { - sService = ILineageAudioService.Stub.asInterface(b); - return sService; - } - return null; - } - - /** - * @return true if service is valid - */ - private boolean checkService() { - if (sService == null) { - Log.w(TAG, "not connected to LineageAudioService"); - return false; - } - return true; - } - - /** - * List audio sessions for the given stream type defined in - * {@link android.media.AudioManager}, for example, - * {@link android.media.AudioManager#STREAM_MUSIC}. - * - * @param streamType from {@link android.media.AudioManager} - * @return list of {@link AudioSessionInfo}, or empty list if none found - * @see android.media.AudioManager - */ - public List listAudioSessions(int streamType) { - if (checkService()) { - try { - final List sessions = sService.listAudioSessions(streamType); - if (sessions != null) { - return Collections.unmodifiableList(sessions); - } - } catch (RemoteException e) { - Log.e(TAG, "Failed to list audio sessions!", e); - } - } - return Collections.emptyList(); - } - - /** - * List all audio sessions. - * - * @return list of {@link AudioSessionInfo}, or empty list if none found - * @see android.media.AudioManager - */ - public List listAudioSessions() { - return listAudioSessions(-1); - } -} diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml index 9a2672f1..cdecca48 100644 --- a/tests/AndroidManifest.xml +++ b/tests/AndroidManifest.xml @@ -26,7 +26,6 @@ - sessions = new ArrayList(); - - ExecutorService sexecutioner = Executors.newFixedThreadPool(5); - for (int i = 0; i < SESSIONS; i++) { - sexecutioner.submit(new Runnable() { - @Override - public void run() { - AudioTrack track = createTestTrack(); - synchronized (sessions) { - sessions.add(track.getAudioSessionId()); - } - track.play(); - track.release(); - } - }); - if ((i % 2) == 0) { - Thread.sleep(100); - } - } - - receiver.waitForSessions(); - sexecutioner.shutdown(); - - assertEquals(SESSIONS, sessions.size()); - assertEquals(SESSIONS, receiver.getNumAdded()); - assertEquals(SESSIONS, receiver.getNumRemoved()); - - for (AudioSessionInfo info : receiver.getSessions()) { - assertTrue(sessions.contains(info.getSessionId())); - } - } - - private static class AudioSessionReceiver extends BroadcastReceiver { - - private int mAdded = 0; - private int mRemoved = 0; - - private final CountDownLatch mLatch; - - private List mSessions = new ArrayList(); - - public AudioSessionReceiver(int count) { - mLatch = new CountDownLatch(count); - } - - @Override - public void onReceive(Context context, Intent intent) { - assertNotNull(intent); - - boolean added = intent.getBooleanExtra(LineageAudioManager.EXTRA_SESSION_ADDED, false); - - AudioSessionInfo info = intent.getParcelableExtra(LineageAudioManager.EXTRA_SESSION_INFO); - Log.d(TAG, "onReceive: " + info); - - assertNotNull(info); - - synchronized (mSessions) { - if (added) { - mAdded++; - mSessions.add(info); - } else { - mRemoved++; - } - } - - mLatch.countDown(); - } - - public int getNumAdded() { - return mAdded; - } - - public int getNumRemoved() { - return mRemoved; - } - - public List getSessions() { - return mSessions; - } - - public void waitForSessions() throws InterruptedException { - mLatch.await(60, TimeUnit.SECONDS); - } - }; - - private AudioSessionInfo findAudioSessionInfo(int sessionId) { - List infos = mLineageAudioManager.listAudioSessions(AudioManager.STREAM_MUSIC); - for (AudioSessionInfo info : infos) { - if (info.getSessionId() == sessionId) { - return info; - } - } - return null; - } - - private AudioTrack createTestTrack() { - int bytes = 2 * 44100 / 1000; - AudioTrack track = new AudioTrack(AudioManager.STREAM_MUSIC, 44100, - AudioFormat.CHANNEL_OUT_STEREO, - AudioFormat.ENCODING_PCM_16BIT, - bytes, - AudioTrack.STATE_INITIALIZED); - return track; - } -}