Merge "AudioService: handle errors when reconnecting mixes after server crash"
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.media;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.TestApi;
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
@@ -26,6 +27,8 @@ import android.media.audiofx.AudioEffect;
|
||||
import android.media.audiopolicy.AudioMix;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -431,6 +434,50 @@ public class AudioSystem
|
||||
public static final int DEAD_OBJECT = -6;
|
||||
public static final int WOULD_BLOCK = -7;
|
||||
|
||||
/** @hide */
|
||||
@IntDef({
|
||||
SUCCESS,
|
||||
ERROR,
|
||||
BAD_VALUE,
|
||||
INVALID_OPERATION,
|
||||
PERMISSION_DENIED,
|
||||
NO_INIT,
|
||||
DEAD_OBJECT,
|
||||
WOULD_BLOCK
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface AudioSystemError {}
|
||||
|
||||
/**
|
||||
* Convert an int error value to its String value for readability.
|
||||
* Accepted error values are the java AudioSystem errors, matching android_media_AudioErrors.h,
|
||||
* which map onto the native status_t type.
|
||||
* @param error one of the java AudioSystem errors
|
||||
* @return a human-readable string
|
||||
*/
|
||||
public static String audioSystemErrorToString(@AudioSystemError int error) {
|
||||
switch(error) {
|
||||
case SUCCESS:
|
||||
return "SUCCESS";
|
||||
case ERROR:
|
||||
return "ERROR";
|
||||
case BAD_VALUE:
|
||||
return "BAD_VALUE";
|
||||
case INVALID_OPERATION:
|
||||
return "INVALID_OPERATION";
|
||||
case PERMISSION_DENIED:
|
||||
return "PERMISSION_DENIED";
|
||||
case NO_INIT:
|
||||
return "NO_INIT";
|
||||
case DEAD_OBJECT:
|
||||
return "DEAD_OBJECT";
|
||||
case WOULD_BLOCK:
|
||||
return "WOULD_BLOCK";
|
||||
default:
|
||||
return ("unknown error:" + error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AudioPolicyService methods
|
||||
*/
|
||||
|
||||
@@ -853,6 +853,10 @@ public class AudioPolicy {
|
||||
Log.v(TAG, "notifyVolumeAdjust: " + adjustment);
|
||||
}
|
||||
}
|
||||
|
||||
public void notifyUnregistration() {
|
||||
setRegistration(null);
|
||||
}
|
||||
};
|
||||
|
||||
//==================================================
|
||||
|
||||
@@ -34,4 +34,8 @@ oneway interface IAudioPolicyCallback {
|
||||
|
||||
// callback for volume events
|
||||
void notifyVolumeAdjust(int adjustment);
|
||||
|
||||
// callback for unregistration (e.g. if policy couldn't automatically be re-registered after
|
||||
// an audioserver crash)
|
||||
void notifyUnregistration();
|
||||
}
|
||||
|
||||
@@ -1018,7 +1018,14 @@ public class AudioService extends IAudioService.Stub
|
||||
|
||||
synchronized (mAudioPolicies) {
|
||||
for (AudioPolicyProxy policy : mAudioPolicies.values()) {
|
||||
policy.connectMixes();
|
||||
final int status = policy.connectMixes();
|
||||
if (status != AudioSystem.SUCCESS) {
|
||||
// note that PERMISSION_DENIED may also indicate trouble getting to APService
|
||||
Log.e(TAG, "onAudioServerDied: error "
|
||||
+ AudioSystem.audioSystemErrorToString(status)
|
||||
+ " when connecting mixes for policy " + policy.toLogFriendlyString());
|
||||
policy.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7007,16 +7014,8 @@ public class AudioService extends IAudioService.Stub
|
||||
}
|
||||
|
||||
public void binderDied() {
|
||||
synchronized (mAudioPolicies) {
|
||||
Log.i(TAG, "audio policy " + mPolicyCallback + " died");
|
||||
release();
|
||||
mAudioPolicies.remove(mPolicyCallback.asBinder());
|
||||
}
|
||||
if (mIsVolumeController) {
|
||||
synchronized (mExtVolumeControllerLock) {
|
||||
mExtVolumeController = null;
|
||||
}
|
||||
}
|
||||
Log.i(TAG, "audio policy " + mPolicyCallback + " died");
|
||||
release();
|
||||
}
|
||||
|
||||
String getRegistrationId() {
|
||||
@@ -7040,9 +7039,20 @@ public class AudioService extends IAudioService.Stub
|
||||
Log.e(TAG, "Fail to unregister Audiopolicy callback from MediaProjection");
|
||||
}
|
||||
}
|
||||
if (mIsVolumeController) {
|
||||
synchronized (mExtVolumeControllerLock) {
|
||||
mExtVolumeController = null;
|
||||
}
|
||||
}
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
AudioSystem.registerPolicyMixes(mMixes, false);
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
synchronized (mAudioPolicies) {
|
||||
mAudioPolicies.remove(mPolicyCallback.asBinder());
|
||||
}
|
||||
try {
|
||||
mPolicyCallback.notifyUnregistration();
|
||||
} catch (RemoteException e) { }
|
||||
}
|
||||
|
||||
boolean hasMixAffectingUsage(int usage, int excludedFlags) {
|
||||
@@ -7093,7 +7103,7 @@ public class AudioService extends IAudioService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
int connectMixes() {
|
||||
@AudioSystem.AudioSystemError int connectMixes() {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
int status = AudioSystem.registerPolicyMixes(mMixes, true);
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
|
||||
Reference in New Issue
Block a user