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

Commit d0028c58 authored by Chris Thornton's avatar Chris Thornton Committed by Android (Google) Code Review
Browse files

Merge "Fix deadlock in SoundTriggerService using intent API."

parents 62c1fb0f ae5fb990
Loading
Loading
Loading
Loading
+27 −13
Original line number Original line Diff line number Diff line
@@ -66,6 +66,7 @@ public class SoundTriggerService extends SystemService {
    private SoundTriggerDbHelper mDbHelper;
    private SoundTriggerDbHelper mDbHelper;
    private SoundTriggerHelper mSoundTriggerHelper;
    private SoundTriggerHelper mSoundTriggerHelper;
    private final TreeMap<UUID, SoundModel> mLoadedModels;
    private final TreeMap<UUID, SoundModel> mLoadedModels;
    private Object mCallbacksLock;
    private final TreeMap<UUID, LocalSoundTriggerRecognitionStatusCallback> mIntentCallbacks;
    private final TreeMap<UUID, LocalSoundTriggerRecognitionStatusCallback> mIntentCallbacks;
    private PowerManager.WakeLock mWakelock;
    private PowerManager.WakeLock mWakelock;


@@ -75,6 +76,7 @@ public class SoundTriggerService extends SystemService {
        mServiceStub = new SoundTriggerServiceStub();
        mServiceStub = new SoundTriggerServiceStub();
        mLocalSoundTriggerService = new LocalSoundTriggerService(context);
        mLocalSoundTriggerService = new LocalSoundTriggerService(context);
        mLoadedModels = new TreeMap<UUID, SoundModel>();
        mLoadedModels = new TreeMap<UUID, SoundModel>();
        mCallbacksLock = new Object();
        mIntentCallbacks = new TreeMap<UUID, LocalSoundTriggerRecognitionStatusCallback>();
        mIntentCallbacks = new TreeMap<UUID, LocalSoundTriggerRecognitionStatusCallback>();
        mLock = new Object();
        mLock = new Object();
    }
    }
@@ -211,8 +213,10 @@ public class SoundTriggerService extends SystemService {
                // don't know if the other model is loaded.
                // don't know if the other model is loaded.
                if (oldModel != null && !oldModel.equals(soundModel)) {
                if (oldModel != null && !oldModel.equals(soundModel)) {
                    mSoundTriggerHelper.unloadGenericSoundModel(soundModel.uuid);
                    mSoundTriggerHelper.unloadGenericSoundModel(soundModel.uuid);
                    synchronized (mCallbacksLock) {
                        mIntentCallbacks.remove(soundModel.uuid);
                        mIntentCallbacks.remove(soundModel.uuid);
                    }
                    }
                }
                mLoadedModels.put(soundModel.uuid, soundModel);
                mLoadedModels.put(soundModel.uuid, soundModel);
            }
            }
            return STATUS_OK;
            return STATUS_OK;
@@ -240,8 +244,10 @@ public class SoundTriggerService extends SystemService {
                // don't know if the other model is loaded.
                // don't know if the other model is loaded.
                if (oldModel != null && !oldModel.equals(soundModel)) {
                if (oldModel != null && !oldModel.equals(soundModel)) {
                    mSoundTriggerHelper.unloadKeyphraseSoundModel(soundModel.keyphrases[0].id);
                    mSoundTriggerHelper.unloadKeyphraseSoundModel(soundModel.keyphrases[0].id);
                    synchronized (mCallbacksLock) {
                        mIntentCallbacks.remove(soundModel.uuid);
                        mIntentCallbacks.remove(soundModel.uuid);
                    }
                    }
                }
                mLoadedModels.put(soundModel.uuid, soundModel);
                mLoadedModels.put(soundModel.uuid, soundModel);
            }
            }
            return STATUS_OK;
            return STATUS_OK;
@@ -262,8 +268,10 @@ public class SoundTriggerService extends SystemService {
                    Slog.e(TAG, soundModelId + " is not loaded");
                    Slog.e(TAG, soundModelId + " is not loaded");
                    return STATUS_ERROR;
                    return STATUS_ERROR;
                }
                }
                LocalSoundTriggerRecognitionStatusCallback callback = mIntentCallbacks.get(
                LocalSoundTriggerRecognitionStatusCallback callback = null;
                        soundModelId.getUuid());
                synchronized (mCallbacksLock) {
                    callback = mIntentCallbacks.get(soundModelId.getUuid());
                }
                if (callback != null) {
                if (callback != null) {
                    Slog.e(TAG, soundModelId + " is already running");
                    Slog.e(TAG, soundModelId + " is already running");
                    return STATUS_ERROR;
                    return STATUS_ERROR;
@@ -291,8 +299,10 @@ public class SoundTriggerService extends SystemService {
                    Slog.e(TAG, "Failed to start model: " + ret);
                    Slog.e(TAG, "Failed to start model: " + ret);
                    return ret;
                    return ret;
                }
                }
                synchronized (mCallbacksLock) {
                    mIntentCallbacks.put(soundModelId.getUuid(), callback);
                    mIntentCallbacks.put(soundModelId.getUuid(), callback);
                }
                }
            }
            return STATUS_OK;
            return STATUS_OK;
        }
        }


@@ -310,8 +320,10 @@ public class SoundTriggerService extends SystemService {
                    Slog.e(TAG, soundModelId + " is not loaded");
                    Slog.e(TAG, soundModelId + " is not loaded");
                    return STATUS_ERROR;
                    return STATUS_ERROR;
                }
                }
                LocalSoundTriggerRecognitionStatusCallback callback = mIntentCallbacks.get(
                LocalSoundTriggerRecognitionStatusCallback callback = null;
                        soundModelId.getUuid());
                synchronized (mCallbacksLock) {
                     callback = mIntentCallbacks.get(soundModelId.getUuid());
                }
                if (callback == null) {
                if (callback == null) {
                    Slog.e(TAG, soundModelId + " is not running");
                    Slog.e(TAG, soundModelId + " is not running");
                    return STATUS_ERROR;
                    return STATUS_ERROR;
@@ -334,8 +346,10 @@ public class SoundTriggerService extends SystemService {
                    Slog.e(TAG, "Failed to stop model: " + ret);
                    Slog.e(TAG, "Failed to stop model: " + ret);
                    return ret;
                    return ret;
                }
                }
                synchronized (mCallbacksLock) {
                    mIntentCallbacks.remove(soundModelId.getUuid());
                    mIntentCallbacks.remove(soundModelId.getUuid());
                }
                }
            }
            return STATUS_OK;
            return STATUS_OK;
        }
        }


@@ -379,14 +393,14 @@ public class SoundTriggerService extends SystemService {
        public boolean isRecognitionActive(ParcelUuid parcelUuid) {
        public boolean isRecognitionActive(ParcelUuid parcelUuid) {
            enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
            enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
            if (!isInitialized()) return false;
            if (!isInitialized()) return false;
            synchronized (mLock) {
            synchronized (mCallbacksLock) {
                LocalSoundTriggerRecognitionStatusCallback callback =
                LocalSoundTriggerRecognitionStatusCallback callback =
                        mIntentCallbacks.get(parcelUuid.getUuid());
                        mIntentCallbacks.get(parcelUuid.getUuid());
                if (callback == null) {
                if (callback == null) {
                    return false;
                    return false;
                }
                }
                return mSoundTriggerHelper.isRecognitionRequested(parcelUuid.getUuid());
            }
            }
            return mSoundTriggerHelper.isRecognitionRequested(parcelUuid.getUuid());
        }
        }
    }
    }


@@ -513,7 +527,7 @@ public class SoundTriggerService extends SystemService {


        private void removeCallback(boolean releaseWakeLock) {
        private void removeCallback(boolean releaseWakeLock) {
            mCallbackIntent = null;
            mCallbackIntent = null;
            synchronized (mLock) {
            synchronized (mCallbacksLock) {
                mIntentCallbacks.remove(mUuid);
                mIntentCallbacks.remove(mUuid);
                if (releaseWakeLock) {
                if (releaseWakeLock) {
                    mWakelock.release();
                    mWakelock.release();
@@ -523,7 +537,7 @@ public class SoundTriggerService extends SystemService {
    }
    }


    private void grabWakeLock() {
    private void grabWakeLock() {
        synchronized (mLock) {
        synchronized (mCallbacksLock) {
            if (mWakelock == null) {
            if (mWakelock == null) {
                PowerManager pm = ((PowerManager) mContext.getSystemService(Context.POWER_SERVICE));
                PowerManager pm = ((PowerManager) mContext.getSystemService(Context.POWER_SERVICE));
                mWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
                mWakelock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
@@ -537,7 +551,7 @@ public class SoundTriggerService extends SystemService {
        public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
        public void onSendFinished(PendingIntent pendingIntent, Intent intent, int resultCode,
                String resultData, Bundle resultExtras) {
                String resultData, Bundle resultExtras) {
            // We're only ever invoked when the callback is done, so release the lock.
            // We're only ever invoked when the callback is done, so release the lock.
            synchronized (mLock) {
            synchronized (mCallbacksLock) {
                mWakelock.release();
                mWakelock.release();
            }
            }
        }
        }