audioflinger: send priority request from a thread
When creating a fast AudioTrack, a request is sent to SchedulingPolicyService
to elevate the requesting thread priority. This generates a binder
call into system_server process and to a JAVA service via JNI.
If the thread from which the track was created is in the system_server
process and does not have the "can call java" attribute, a crash occurs because
the binder optimization reuses the same thread to process the returning binder
call and no JNI env is present.
The fix consists in sending the priority change request from the AudioFlinger
mixer thread, not from the binder thread.
This also reverts the workaround in commit 73431968
Bug 7126707.
Change-Id: I3347adf71ffbb56ed8436506d4357eab693078a3
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index c956861..8a020fa 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -471,14 +471,63 @@
Vector < sp<SyncEvent> >mSyncEvents;
};
+ enum {
+ CFG_EVENT_IO,
+ CFG_EVENT_PRIO
+ };
+
class ConfigEvent {
public:
- ConfigEvent() : mEvent(0), mParam(0) {}
+ ConfigEvent(int type) : mType(type) {}
+ virtual ~ConfigEvent() {}
- int mEvent;
- int mParam;
+ int type() const { return mType; }
+
+ virtual void dump(char *buffer, size_t size) = 0;
+
+ private:
+ const int mType;
};
+ class IoConfigEvent : public ConfigEvent {
+ public:
+ IoConfigEvent(int event, int param) :
+ ConfigEvent(CFG_EVENT_IO), mEvent(event), mParam(event) {}
+ virtual ~IoConfigEvent() {}
+
+ int event() const { return mEvent; }
+ int param() const { return mParam; }
+
+ virtual void dump(char *buffer, size_t size) {
+ snprintf(buffer, size, "IO event: event %d, param %d\n", mEvent, mParam);
+ }
+
+ private:
+ const int mEvent;
+ const int mParam;
+ };
+
+ class PrioConfigEvent : public ConfigEvent {
+ public:
+ PrioConfigEvent(pid_t pid, pid_t tid, int32_t prio) :
+ ConfigEvent(CFG_EVENT_PRIO), mPid(pid), mTid(tid), mPrio(prio) {}
+ virtual ~PrioConfigEvent() {}
+
+ pid_t pid() const { return mPid; }
+ pid_t tid() const { return mTid; }
+ int32_t prio() const { return mPrio; }
+
+ virtual void dump(char *buffer, size_t size) {
+ snprintf(buffer, size, "Prio event: pid %d, tid %d, prio %d\n", mPid, mTid, mPrio);
+ }
+
+ private:
+ const pid_t mPid;
+ const pid_t mTid;
+ const int32_t mPrio;
+ };
+
+
class PMDeathRecipient : public IBinder::DeathRecipient {
public:
PMDeathRecipient(const wp<ThreadBase>& thread) : mThread(thread) {}
@@ -516,8 +565,9 @@
virtual status_t setParameters(const String8& keyValuePairs);
virtual String8 getParameters(const String8& keys) = 0;
virtual void audioConfigChanged_l(int event, int param = 0) = 0;
- void sendConfigEvent(int event, int param = 0);
- void sendConfigEvent_l(int event, int param = 0);
+ void sendIoConfigEvent(int event, int param = 0);
+ void sendIoConfigEvent_l(int event, int param = 0);
+ void sendPrioConfigEvent_l(pid_t pid, pid_t tid, int32_t prio);
void processConfigEvents();
// see note at declaration of mStandby, mOutDevice and mInDevice
@@ -666,7 +716,7 @@
Vector<String8> mNewParameters;
status_t mParamStatus;
- Vector<ConfigEvent> mConfigEvents;
+ Vector<ConfigEvent *> mConfigEvents;
// These fields are written and read by thread itself without lock or barrier,
// and read by other threads without lock or barrier via standby() , outDevice()