13c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi/* 23c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * Copyright (C) 2016 The Android Open Source Project 33c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * 43c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License"); 53c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * you may not use this file except in compliance with the License. 63c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * You may obtain a copy of the License at 73c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * 83c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * http://www.apache.org/licenses/LICENSE-2.0 93c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * 103c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * Unless required by applicable law or agreed to in writing, software 113c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS, 123c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * See the License for the specific language governing permissions and 143c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * limitations under the License. 153c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi */ 163c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 173c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivipackage android.media; 183c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 193c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Triviimport android.annotation.NonNull; 20035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hungimport android.annotation.Nullable; 213c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Triviimport android.app.ActivityThread; 223c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Triviimport android.app.AppOpsManager; 233c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Triviimport android.content.Context; 24035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hungimport android.media.VolumeShaper; 25292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Triviimport android.os.Binder; 263c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Triviimport android.os.IBinder; 27292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Triviimport android.os.Parcel; 28292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Triviimport android.os.Parcelable; 293c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Triviimport android.os.Process; 303c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Triviimport android.os.RemoteException; 313c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Triviimport android.os.ServiceManager; 323c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Triviimport android.util.Log; 333c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 3476e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Triviimport com.android.internal.annotations.GuardedBy; 353c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Triviimport com.android.internal.app.IAppOpsCallback; 363c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Triviimport com.android.internal.app.IAppOpsService; 373c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 38292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Triviimport java.lang.IllegalArgumentException; 39cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Triviimport java.lang.ref.WeakReference; 40292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Triviimport java.util.Objects; 41292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 423c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi/** 433c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * Class to encapsulate a number of common player operations: 443c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * - AppOps for OP_PLAY_AUDIO 453c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * - more to come (routing, transport control) 463c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * @hide 473c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi */ 483c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivipublic abstract class PlayerBase { 493c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 50aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi private static final String TAG = "PlayerBase"; 518e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi /** Debug app ops */ 52aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi private static final boolean DEBUG_APP_OPS = false; 53b8748c65b8ccc645eeec95e8922058238e72cc9dJean-Michel Trivi private static final boolean DEBUG = DEBUG_APP_OPS || false; 54b8748c65b8ccc645eeec95e8922058238e72cc9dJean-Michel Trivi private static IAudioService sService; //lazy initialization, use getService() 558e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi 563c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi // parameters of the player that affect AppOps 573c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi protected AudioAttributes mAttributes; 583c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi protected float mLeftVolume = 1.0f; 593c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi protected float mRightVolume = 1.0f; 603c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi protected float mAuxEffectSendLevel = 0.0f; 613c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 6276e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi // NEVER call into AudioService (see getService()) with mLock held: PlayerBase can run in 6376e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi // the same process as AudioService, which can synchronously call back into this class, 6476e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi // causing deadlocks between the two 6576e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi private final Object mLock = new Object(); 6676e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi 673c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi // for AppOps 6876e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi private @Nullable IAppOpsService mAppOps; 699dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi private IAppOpsCallback mAppOpsCallback; 7076e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi @GuardedBy("mLock") 7176e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi private boolean mHasAppOpsPlayAudio = true; 723c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 73292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi private final int mImplType; 74292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi // uniquely identifies the Player Interface throughout the system (P I Id) 7576e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi private int mPlayerIId = AudioPlaybackConfiguration.PLAYER_PIID_UNASSIGNED; 76292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 7776e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi @GuardedBy("mLock") 7876e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi private int mState; 7976e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi @GuardedBy("mLock") 8076e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi private int mStartDelayMs = 0; 8176e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi @GuardedBy("mLock") 8276e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi private float mPanMultiplierL = 1.0f; 8376e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi @GuardedBy("mLock") 8476e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi private float mPanMultiplierR = 1.0f; 85292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 863c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi /** 873c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * Constructor. Must be given audio attributes, as they are required for AppOps. 883c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * @param attr non-null audio attributes 89292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi * @param class non-null class of the implementation of this abstract class 903c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi */ 91292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi PlayerBase(@NonNull AudioAttributes attr, int implType) { 923c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi if (attr == null) { 933c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi throw new IllegalArgumentException("Illegal null AudioAttributes"); 943c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 953c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi mAttributes = attr; 96292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi mImplType = implType; 97e9630038872065874c66c8f120555cf09d1ee060Jean-Michel Trivi mState = AudioPlaybackConfiguration.PLAYER_STATE_IDLE; 989dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi }; 999dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi 1009dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi /** 1019dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi * Call from derived class when instantiation / initialization is successful 1029dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi */ 1039dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi protected void baseRegisterPlayer() { 10444a8f53f94808fdc5ac35a249d21ff2ba23e9419Jean-Michel Trivi int newPiid = AudioPlaybackConfiguration.PLAYER_PIID_INVALID; 1053c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi IBinder b = ServiceManager.getService(Context.APP_OPS_SERVICE); 1063c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi mAppOps = IAppOpsService.Stub.asInterface(b); 1073c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi // initialize mHasAppOpsPlayAudio 108aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi updateAppOpsPlayAudio(); 1093c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi // register a callback to monitor whether the OP_PLAY_AUDIO is still allowed 110aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi mAppOpsCallback = new IAppOpsCallbackWrapper(this); 1113c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi try { 1123c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi mAppOps.startWatchingMode(AppOpsManager.OP_PLAY_AUDIO, 1133c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi ActivityThread.currentPackageName(), mAppOpsCallback); 1143c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } catch (RemoteException e) { 115b8748c65b8ccc645eeec95e8922058238e72cc9dJean-Michel Trivi Log.e(TAG, "Error registering appOps callback", e); 1163c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi mHasAppOpsPlayAudio = false; 1173c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 118292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi try { 119cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi newPiid = getService().trackPlayer( 120cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi new PlayerIdCard(mImplType, mAttributes, new IPlayerWrapper(this))); 121292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } catch (RemoteException e) { 122292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi Log.e(TAG, "Error talking to audio service, player will not be tracked", e); 123292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 12444a8f53f94808fdc5ac35a249d21ff2ba23e9419Jean-Michel Trivi mPlayerIId = newPiid; 1253c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 1263c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 1273c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi /** 1283c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * To be called whenever the audio attributes of the player change 1293c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * @param attr non-null audio attributes 1303c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi */ 1313c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi void baseUpdateAudioAttributes(@NonNull AudioAttributes attr) { 1323c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi if (attr == null) { 1333c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi throw new IllegalArgumentException("Illegal null AudioAttributes"); 1343c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 135292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi try { 136292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi getService().playerAttributes(mPlayerIId, attr); 137292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } catch (RemoteException e) { 138292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi Log.e(TAG, "Error talking to audio service, STARTED state will not be tracked", e); 139292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 14099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi synchronized (mLock) { 141e5a351cb9213b59026efd602011a4d9e99c85649Eric Laurent boolean attributesChanged = (mAttributes != attr); 1423c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi mAttributes = attr; 143e5a351cb9213b59026efd602011a4d9e99c85649Eric Laurent updateAppOpsPlayAudio_sync(attributesChanged); 1443c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 1453c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 1463c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 14776e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi private void updateState(int state) { 14876e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi final int piid; 14976e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi synchronized (mLock) { 15076e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi mState = state; 15176e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi piid = mPlayerIId; 15276e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi } 153292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi try { 15476e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi getService().playerEvent(piid, state); 155292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } catch (RemoteException e) { 15676e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi Log.e(TAG, "Error talking to audio service, " 15776e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi + AudioPlaybackConfiguration.toLogFriendlyPlayerState(state) 15876e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi + " state will not be tracked for piid=" + piid, e); 159292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 16076e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi } 16176e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi 16276e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi void baseStart() { 16376e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi if (DEBUG) { Log.v(TAG, "baseStart() piid=" + mPlayerIId); } 16476e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi updateState(AudioPlaybackConfiguration.PLAYER_STATE_STARTED); 16599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi synchronized (mLock) { 1663c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi if (isRestricted_sync()) { 1678e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi playerSetVolume(true/*muting*/,0, 0); 1683c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 1693c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 1703c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 1713c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 17299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi void baseSetStartDelayMs(int delayMs) { 17399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi synchronized(mLock) { 17499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi mStartDelayMs = Math.max(delayMs, 0); 17599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 17699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 17799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi 17899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi protected int getStartDelayMs() { 17999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi synchronized(mLock) { 18099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi return mStartDelayMs; 18199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 18299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 18399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi 184292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi void basePause() { 185292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi if (DEBUG) { Log.v(TAG, "basePause() piid=" + mPlayerIId); } 18676e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi updateState(AudioPlaybackConfiguration.PLAYER_STATE_PAUSED); 187292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 188292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 189292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi void baseStop() { 190292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi if (DEBUG) { Log.v(TAG, "baseStop() piid=" + mPlayerIId); } 19176e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi updateState(AudioPlaybackConfiguration.PLAYER_STATE_STOPPED); 192292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 193292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 19499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi void baseSetPan(float pan) { 19599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi final float p = Math.min(Math.max(-1.0f, pan), 1.0f); 19699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi synchronized (mLock) { 19799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi if (p >= 0.0f) { 19899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi mPanMultiplierL = 1.0f - p; 19999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi mPanMultiplierR = 1.0f; 20099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } else { 20199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi mPanMultiplierL = 1.0f; 20299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi mPanMultiplierR = 1.0f + p; 20399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 20499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 20599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi baseSetVolume(mLeftVolume, mRightVolume); 20699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 20799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi 2083c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi void baseSetVolume(float leftVolume, float rightVolume) { 209e5a351cb9213b59026efd602011a4d9e99c85649Eric Laurent final boolean isRestricted; 21099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi synchronized (mLock) { 2113c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi mLeftVolume = leftVolume; 2123c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi mRightVolume = rightVolume; 213e5a351cb9213b59026efd602011a4d9e99c85649Eric Laurent isRestricted = isRestricted_sync(); 2143c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 215e5a351cb9213b59026efd602011a4d9e99c85649Eric Laurent playerSetVolume(isRestricted/*muting*/, 21699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi leftVolume * mPanMultiplierL, rightVolume * mPanMultiplierR); 2173c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 2183c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 2193c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi int baseSetAuxEffectSendLevel(float level) { 22099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi synchronized (mLock) { 2213c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi mAuxEffectSendLevel = level; 2223c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi if (isRestricted_sync()) { 2233c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi return AudioSystem.SUCCESS; 2243c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 2253c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 2268e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi return playerSetAuxEffectSendLevel(false/*muting*/, level); 2273c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 2283c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 2293c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi /** 2303c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * To be called from a subclass release or finalize method. 2313c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * Releases AppOps related resources. 2323c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi */ 2333c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi void baseRelease() { 234e9630038872065874c66c8f120555cf09d1ee060Jean-Michel Trivi if (DEBUG) { Log.v(TAG, "baseRelease() piid=" + mPlayerIId + " state=" + mState); } 23576e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi boolean releasePlayer = false; 23676e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi synchronized (mLock) { 23776e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi if (mState != AudioPlaybackConfiguration.PLAYER_STATE_RELEASED) { 23876e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi releasePlayer = true; 23976e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi mState = AudioPlaybackConfiguration.PLAYER_STATE_RELEASED; 24076e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi } 24176e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi } 242292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi try { 24376e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi if (releasePlayer) { 24476e124bcd3ee2e5ba98dcbdb99965a4c133fe7e4Jean-Michel Trivi getService().releasePlayer(mPlayerIId); 245292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 246292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } catch (RemoteException e) { 247292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi Log.e(TAG, "Error talking to audio service, the player will still be tracked", e); 248292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 2493c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi try { 2500fbcb86389623e57689fcc3956ef94084ab9ceabJean-Michel Trivi if (mAppOps != null) { 2510fbcb86389623e57689fcc3956ef94084ab9ceabJean-Michel Trivi mAppOps.stopWatchingMode(mAppOpsCallback); 2520fbcb86389623e57689fcc3956ef94084ab9ceabJean-Michel Trivi } 253a00f86009eb84a96a2086d3e3e065bd812cdcee3Jean-Michel Trivi } catch (Exception e) { 2543c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi // nothing to do here, the object is supposed to be released anyway 2553c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 2563c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 2573c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 258aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi private void updateAppOpsPlayAudio() { 259aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi synchronized (mLock) { 260e5a351cb9213b59026efd602011a4d9e99c85649Eric Laurent updateAppOpsPlayAudio_sync(false); 261aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi } 262aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi } 263aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi 2643c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi /** 2653c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * To be called whenever a condition that might affect audibility of this player is updated. 26699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi * Must be called synchronized on mLock. 2673c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi */ 268e5a351cb9213b59026efd602011a4d9e99c85649Eric Laurent void updateAppOpsPlayAudio_sync(boolean attributesChanged) { 2693c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi boolean oldHasAppOpsPlayAudio = mHasAppOpsPlayAudio; 2703c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi try { 2710fbcb86389623e57689fcc3956ef94084ab9ceabJean-Michel Trivi int mode = AppOpsManager.MODE_IGNORED; 2720fbcb86389623e57689fcc3956ef94084ab9ceabJean-Michel Trivi if (mAppOps != null) { 2730fbcb86389623e57689fcc3956ef94084ab9ceabJean-Michel Trivi mode = mAppOps.checkAudioOperation(AppOpsManager.OP_PLAY_AUDIO, 2743c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi mAttributes.getUsage(), 2753c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi Process.myUid(), ActivityThread.currentPackageName()); 2760fbcb86389623e57689fcc3956ef94084ab9ceabJean-Michel Trivi } 2773c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi mHasAppOpsPlayAudio = (mode == AppOpsManager.MODE_ALLOWED); 2783c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } catch (RemoteException e) { 2793c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi mHasAppOpsPlayAudio = false; 2803c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 2813c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 2823c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi // AppsOps alters a player's volume; when the restriction changes, reflect it on the actual 2833c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi // volume used by the player 2843c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi try { 285e5a351cb9213b59026efd602011a4d9e99c85649Eric Laurent if (oldHasAppOpsPlayAudio != mHasAppOpsPlayAudio || 286e5a351cb9213b59026efd602011a4d9e99c85649Eric Laurent attributesChanged) { 2873120059d5bdc52fb5ef2c90d9662562e92cd4df9Jean-Michel Trivi getService().playerHasOpPlayAudio(mPlayerIId, mHasAppOpsPlayAudio); 288e5a351cb9213b59026efd602011a4d9e99c85649Eric Laurent if (!isRestricted_sync()) { 2898e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi if (DEBUG_APP_OPS) { 2908e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi Log.v(TAG, "updateAppOpsPlayAudio: unmuting player, vol=" + mLeftVolume 2918e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi + "/" + mRightVolume); 2928e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi } 29399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi playerSetVolume(false/*muting*/, 29499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi mLeftVolume * mPanMultiplierL, mRightVolume * mPanMultiplierR); 2958e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi playerSetAuxEffectSendLevel(false/*muting*/, mAuxEffectSendLevel); 2963c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } else { 2978e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi if (DEBUG_APP_OPS) { 2988e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi Log.v(TAG, "updateAppOpsPlayAudio: muting player"); 2998e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi } 3008e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi playerSetVolume(true/*muting*/, 0.0f, 0.0f); 3018e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi playerSetAuxEffectSendLevel(true/*muting*/, 0.0f); 3023c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 3033c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 3043c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } catch (Exception e) { 3053c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi // failing silently, player might not be in right state 3063c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 3073c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 3083c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 3093c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi /** 3103c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * To be called by the subclass whenever an operation is potentially restricted. 3113c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * As the media player-common behavior are incorporated into this class, the subclass's need 3123c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * to call this method should be removed, and this method could become private. 3133c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * FIXME can this method be private so subclasses don't have to worry about when to check 3143c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * the restrictions. 3153c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi * @return 3163c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi */ 3173c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi boolean isRestricted_sync() { 3181293c060c81de1124887ddc05603eb3f98b50cbaJean-Michel Trivi // check app ops 3191293c060c81de1124887ddc05603eb3f98b50cbaJean-Michel Trivi if (mHasAppOpsPlayAudio) { 3201293c060c81de1124887ddc05603eb3f98b50cbaJean-Michel Trivi return false; 3211293c060c81de1124887ddc05603eb3f98b50cbaJean-Michel Trivi } 3221293c060c81de1124887ddc05603eb3f98b50cbaJean-Michel Trivi // check bypass flag 3233c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi if ((mAttributes.getAllFlags() & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY) != 0) { 3243c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi return false; 3253c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 3268e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi // check force audibility flag and camera restriction 3278e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi if (((mAttributes.getAllFlags() & AudioAttributes.FLAG_AUDIBILITY_ENFORCED) != 0) 3288e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi && (mAttributes.getUsage() == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)) { 3298e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi boolean cameraSoundForced = false; 3308e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi try { 3318e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi cameraSoundForced = getService().isCameraSoundForced(); 3328e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi } catch (RemoteException e) { 3338e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi Log.e(TAG, "Cannot access AudioService in isRestricted_sync()"); 3348e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi } catch (NullPointerException e) { 3358e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi Log.e(TAG, "Null AudioService in isRestricted_sync()"); 3368e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi } 3378e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi if (cameraSoundForced) { 3388e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi return false; 3398e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi } 3408e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi } 3411293c060c81de1124887ddc05603eb3f98b50cbaJean-Michel Trivi return true; 3423c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi } 3433c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi 3448e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi private static IAudioService getService() 3458e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi { 3468e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi if (sService != null) { 3478e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi return sService; 3488e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi } 3498e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE); 3508e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi sService = IAudioService.Stub.asInterface(b); 3518e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi return sService; 3528e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi } 3538e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi 35499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi /** 35599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi * @hide 35699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi * @param delayMs 35799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi */ 35899489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi public void setStartDelayMs(int delayMs) { 35999489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi baseSetStartDelayMs(delayMs); 36099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 36199489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi 362292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi //===================================================================== 3633c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi // Abstract methods a subclass needs to implement 3648e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi /** 3658e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi * Abstract method for the subclass behavior's for volume and muting commands 3668e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi * @param muting if true, the player is to be muted, and the volume values can be ignored 3678e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi * @param leftVolume the left volume to use if muting is false 3688e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi * @param rightVolume the right volume to use if muting is false 3698e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi */ 3708e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi abstract void playerSetVolume(boolean muting, float leftVolume, float rightVolume); 371035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung 372035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung /** 373035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * Abstract method to apply a {@link VolumeShaper.Configuration} 374035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * and a {@link VolumeShaper.Operation} to the Player. 375035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * This should be overridden by the Player to call into the native 376035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * VolumeShaper implementation. Multiple {@code VolumeShapers} may be 377035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * concurrently active for a given Player, each accessible by the 378035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * {@code VolumeShaper} id. 379035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * 380035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * The {@code VolumeShaper} implementation caches the id returned 381035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * when applying a fully specified configuration 382035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * from {VolumeShaper.Configuration.Builder} to track later 383035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * operation changes requested on it. 384035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * 385035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * @param configuration a {@code VolumeShaper.Configuration} object 386035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * created by {@link VolumeShaper.Configuration.Builder} or 387035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * an created from a {@code VolumeShaper} id 388035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * by the {@link VolumeShaper.Configuration} constructor. 389035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * @param operation a {@code VolumeShaper.Operation}. 390035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * @return a negative error status or a 391035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * non-negative {@code VolumeShaper} id on success. 392035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung */ 393035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung /* package */ abstract int playerApplyVolumeShaper( 394035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung @NonNull VolumeShaper.Configuration configuration, 395035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung @NonNull VolumeShaper.Operation operation); 396035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung 397035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung /** 398035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * Abstract method to get the current VolumeShaper state. 399035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * @param id the {@code VolumeShaper} id returned from 400035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * sending a fully specified {@code VolumeShaper.Configuration} 401035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * through {@link #playerApplyVolumeShaper} 402035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * @return a {@code VolumeShaper.State} object or null if 403035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung * there is no {@code VolumeShaper} for the id. 404035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung */ 405035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung /* package */ abstract @Nullable VolumeShaper.State playerGetVolumeShaperState(int id); 406035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung 4078e48c6939bd81dcbc596f0a4b11bfaea73aed00bJean-Michel Trivi abstract int playerSetAuxEffectSendLevel(boolean muting, float level); 4089dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi abstract void playerStart(); 4099dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi abstract void playerPause(); 4109dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi abstract void playerStop(); 4112f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi 4122f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi //===================================================================== 413aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi private static class IAppOpsCallbackWrapper extends IAppOpsCallback.Stub { 414aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi private final WeakReference<PlayerBase> mWeakPB; 415aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi 416aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi public IAppOpsCallbackWrapper(PlayerBase pb) { 417aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi mWeakPB = new WeakReference<PlayerBase>(pb); 418aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi } 419aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi 420aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi @Override 421aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi public void opChanged(int op, int uid, String packageName) { 422aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi if (op == AppOpsManager.OP_PLAY_AUDIO) { 423aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi if (DEBUG_APP_OPS) { Log.v(TAG, "opChanged: op=PLAY_AUDIO pack=" + packageName); } 424aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi final PlayerBase pb = mWeakPB.get(); 425aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi if (pb != null) { 426aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi pb.updateAppOpsPlayAudio(); 427aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi } 428aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi } 429aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi } 430aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi } 431aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi 432aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi //===================================================================== 4339dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi /** 434cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi * Wrapper around an implementation of IPlayer for all subclasses of PlayerBase 435cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi * that doesn't keep a strong reference on PlayerBase 4369dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi */ 437cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi private static class IPlayerWrapper extends IPlayer.Stub { 438cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi private final WeakReference<PlayerBase> mWeakPB; 439cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi 440cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi public IPlayerWrapper(PlayerBase pb) { 441cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi mWeakPB = new WeakReference<PlayerBase>(pb); 442cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi } 443cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi 444292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi @Override 4459dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi public void start() { 446cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi final PlayerBase pb = mWeakPB.get(); 447cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi if (pb != null) { 448cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi pb.playerStart(); 449cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi } 4509dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi } 4519dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi 4529dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi @Override 4539dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi public void pause() { 454cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi final PlayerBase pb = mWeakPB.get(); 455cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi if (pb != null) { 456cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi pb.playerPause(); 457cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi } 4589dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi } 4599dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi 460292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi @Override 4619dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi public void stop() { 462cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi final PlayerBase pb = mWeakPB.get(); 463cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi if (pb != null) { 464cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi pb.playerStop(); 465cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi } 4669dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi } 4679dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi 468292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi @Override 4699dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi public void setVolume(float vol) { 470cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi final PlayerBase pb = mWeakPB.get(); 471cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi if (pb != null) { 472cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi pb.baseSetVolume(vol, vol); 473cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi } 4749dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi } 47599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi 47699489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi @Override 47799489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi public void setPan(float pan) { 478cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi final PlayerBase pb = mWeakPB.get(); 479cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi if (pb != null) { 480cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi pb.baseSetPan(pan); 481cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi } 48299489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 48399489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi 48499489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi @Override 48599489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi public void setStartDelayMs(int delayMs) { 486cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi final PlayerBase pb = mWeakPB.get(); 487cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi if (pb != null) { 488cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi pb.baseSetStartDelayMs(delayMs); 489cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi } 49099489ccf740d369193a8ffc7eeb4bbde6919bd65Jean-Michel Trivi } 491035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung 492035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung @Override 493035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung public void applyVolumeShaper( 494035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung @NonNull VolumeShaper.Configuration configuration, 495035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung @NonNull VolumeShaper.Operation operation) { 496cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi final PlayerBase pb = mWeakPB.get(); 497cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi if (pb != null) { 498cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi pb.playerApplyVolumeShaper(configuration, operation); 499cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi } 500035d4ec772b0cde2a8d4b05d2daa9b9cbe11e117Andy Hung } 501cf1b224a789f8412211d22fba9551ce01e54be14Jean-Michel Trivi } 502292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 503292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi //===================================================================== 504292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi /** 505292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi * Class holding all the information about a player that needs to be known at registration time 506292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi */ 507292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi public static class PlayerIdCard implements Parcelable { 508292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi public final int mPlayerType; 509292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 510aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi public static final int AUDIO_ATTRIBUTES_NONE = 0; 511aee6ee94675d56e71a42d52b16b8d8e5fa6ea3ffJean-Michel Trivi public static final int AUDIO_ATTRIBUTES_DEFINED = 1; 512292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi public final AudioAttributes mAttributes; 5139dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi public final IPlayer mIPlayer; 514292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 5159dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi PlayerIdCard(int type, @NonNull AudioAttributes attr, @NonNull IPlayer iplayer) { 516292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi mPlayerType = type; 517292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi mAttributes = attr; 5189dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi mIPlayer = iplayer; 519292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 520292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 521292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi @Override 522292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi public int hashCode() { 52344a8f53f94808fdc5ac35a249d21ff2ba23e9419Jean-Michel Trivi return Objects.hash(mPlayerType); 524292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 525292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 526292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi @Override 527292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi public int describeContents() { 528292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi return 0; 529292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 530292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 531292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi @Override 532292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi public void writeToParcel(Parcel dest, int flags) { 533292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi dest.writeInt(mPlayerType); 534292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi mAttributes.writeToParcel(dest, 0); 5359dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi dest.writeStrongBinder(mIPlayer == null ? null : mIPlayer.asBinder()); 536292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 537292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 538292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi public static final Parcelable.Creator<PlayerIdCard> CREATOR 539292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi = new Parcelable.Creator<PlayerIdCard>() { 540292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi /** 541292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi * Rebuilds an PlayerIdCard previously stored with writeToParcel(). 542292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi * @param p Parcel object to read the PlayerIdCard from 543292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi * @return a new PlayerIdCard created from the data in the parcel 544292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi */ 545292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi public PlayerIdCard createFromParcel(Parcel p) { 546292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi return new PlayerIdCard(p); 547292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 548292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi public PlayerIdCard[] newArray(int size) { 549292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi return new PlayerIdCard[size]; 550292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 551292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi }; 552292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 553292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi private PlayerIdCard(Parcel in) { 554292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi mPlayerType = in.readInt(); 555292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi mAttributes = AudioAttributes.CREATOR.createFromParcel(in); 5569dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi // IPlayer can be null if unmarshalling a Parcel coming from who knows where 5579dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi final IBinder b = in.readStrongBinder(); 5589dc22c227cb5c01136a6aa1b52c7dfa3383c0bd7Jean-Michel Trivi mIPlayer = (b == null ? null : IPlayer.Stub.asInterface(b)); 559292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 560292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 561292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi @Override 562292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi public boolean equals(Object o) { 563292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi if (this == o) return true; 564292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi if (o == null || !(o instanceof PlayerIdCard)) return false; 565292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 566292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi PlayerIdCard that = (PlayerIdCard) o; 567292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 56844a8f53f94808fdc5ac35a249d21ff2ba23e9419Jean-Michel Trivi // FIXME change to the binder player interface once supported as a member 56944a8f53f94808fdc5ac35a249d21ff2ba23e9419Jean-Michel Trivi return ((mPlayerType == that.mPlayerType) && mAttributes.equals(that.mAttributes)); 570292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 571292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi } 572292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi 573292a6a4e9934a94eea97b018befde3baed895f7dJean-Michel Trivi //===================================================================== 5742f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi // Utilities 5752f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi 5762f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi /** 5772f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi * Use to generate warning or exception in legacy code paths that allowed passing stream types 5782f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi * to qualify audio playback. 5792f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi * @param streamType the stream type to check 5802f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi * @throws IllegalArgumentException 5812f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi */ 5822f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi public static void deprecateStreamTypeForPlayback(int streamType, String className, 5832f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi String opName) throws IllegalArgumentException { 5842f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi // STREAM_ACCESSIBILITY was introduced at the same time the use of stream types 5852f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi // for audio playback was deprecated, so it is not allowed at all to qualify a playback 5862f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi // use case 5872f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi if (streamType == AudioManager.STREAM_ACCESSIBILITY) { 5882f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi throw new IllegalArgumentException("Use of STREAM_ACCESSIBILITY is reserved for " 5892f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi + "volume control"); 5902f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi } 591c4c13b44b816540af7fe99b40b276c1c6979a44cJean-Michel Trivi Log.w(className, "Use of stream types is deprecated for operations other than " + 592c4c13b44b816540af7fe99b40b276c1c6979a44cJean-Michel Trivi "volume control"); 593c4c13b44b816540af7fe99b40b276c1c6979a44cJean-Michel Trivi Log.w(className, "See the documentation of " + opName + " for what to use instead with " + 5942f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi "android.media.AudioAttributes to qualify your playback use case"); 5952f7511fd065aa121287da3d4b5b8bea3e528b0bcJean-Michel Trivi } 5963c86a343dfca1b9e2e28c240dc894f60709e392cJean-Michel Trivi} 597