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

Commit dd45d011 authored by Eric Laurent's avatar Eric Laurent
Browse files

enforce camera sound according to country code

Use mcc config overlay mechanism to enforce camera shutter sounds
in countries where it is mandatory.
Property ro.camera.sound.forced is not needed anymore.
When camera sound is forced, STREAM_SYSTEM_ENFORCED is removed from
streams affected by ringer mode and its volume is
maxed out. AudioSystem.FORCE_SYSTEM_ENFORCED is sent to audio
policy manager to alter the routing policy for STREAM_SYSTEM_ENFORCED.

Also fix streams being unmuted when settings are reloaded
upon user switch while in silent mode.

Add ringer mode to audio service dump.

Bug 7032634.

Change-Id: Iceea5bba3b8d3aabf8e42b222deb33a893dc8f38
parent 0e2aade9
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
** Copyright 2012, The Android Open Source 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.
*/
-->

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">

    <!-- Whether camera shutter sound is forced or not  (country specific). -->
    <bool name="config_camera_sound_forced">true</bool>

</resources>
+3 −0
Original line number Diff line number Diff line
@@ -981,4 +981,7 @@
    -->
    <bool name="config_wifiDisplaySupportsProtectedBuffers">false</bool>

    <!-- Whether camera shutter sound is forced or not  (country specific). -->
    <bool name="config_camera_sound_forced">false</bool>

</resources>
+1 −0
Original line number Diff line number Diff line
@@ -275,6 +275,7 @@
  <java-symbol type="bool" name="config_enableWifiDisplay" />
  <java-symbol type="bool" name="config_useDevInputEventForAudioJack" />
  <java-symbol type="bool" name="config_safe_media_volume_enabled" />
  <java-symbol type="bool" name="config_camera_sound_forced" />

  <java-symbol type="integer" name="config_cursorWindowSize" />
  <java-symbol type="integer" name="config_longPressOnPowerBehavior" />
+176 −36
Original line number Diff line number Diff line
@@ -462,7 +462,21 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        mVolumePanel = new VolumePanel(context, this);
        mMode = AudioSystem.MODE_NORMAL;
        mForcedUseForComm = AudioSystem.FORCE_NONE;

        createAudioSystemThread();

        boolean cameraSoundForced = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_camera_sound_forced);
        mCameraSoundForced = new Boolean(cameraSoundForced);
        sendMsg(mAudioHandler,
                MSG_SET_FORCE_USE,
                SENDMSG_QUEUE,
                AudioSystem.FOR_SYSTEM,
                cameraSoundForced ?
                        AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
                null,
                0);

        readPersistedSettings();
        mSettingsObserver = new SettingsObserver();
        updateStreamVolumeAlias(false /*updateVolumes*/);
@@ -585,6 +599,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            mStreamStates[i].dump(pw);
            pw.println("");
        }
        pw.print("\n- mute affected streams = 0x");
        pw.println(Integer.toHexString(mMuteAffectedStreams));
    }


@@ -634,10 +650,10 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        }
        synchronized(mSettingsLock) {
            mRingerMode = ringerMode;
        }

            // System.VIBRATE_ON is not used any more but defaults for mVibrateSetting
        // are still needed while setVibrateSetting() and getVibrateSetting() are being deprecated.
            // are still needed while setVibrateSetting() and getVibrateSetting() are being
            // deprecated.
            mVibrateSetting = getValueForVibrateSetting(0,
                                            AudioManager.VIBRATE_TYPE_NOTIFICATION,
                                            mHasVibrator ? AudioManager.VIBRATE_SETTING_ONLY_SILENT
@@ -659,10 +675,19 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            } else {
                mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
            }
            synchronized (mCameraSoundForced) {
                if (mCameraSoundForced) {
                    mRingerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
                } else {
                    mRingerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
                }
            }

            Settings.System.putIntForUser(cr,
                    Settings.System.MODE_RINGER_STREAMS_AFFECTED,
                    mRingerModeAffectedStreams,
                    UserHandle.USER_CURRENT);
        }

        mMuteAffectedStreams = System.getIntForUser(cr,
                System.MUTE_STREAMS_AFFECTED,
@@ -2601,12 +2626,18 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            // only be stale values
            // on first call to readSettings() at init time, muteCount() is always 0 so we will
            // always create entries for default device
            if ((muteCount() == 0) && (mStreamType == AudioSystem.STREAM_SYSTEM) ||
            if ((mStreamType == AudioSystem.STREAM_SYSTEM) ||
                    (mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED)) {
                mLastAudibleIndex.put(AudioSystem.DEVICE_OUT_DEFAULT,
                                          10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]);
                mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT,
                               10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType]);
                int index = 10 * AudioManager.DEFAULT_STREAM_VOLUME[mStreamType];
                synchronized (mCameraSoundForced) {
                    if (mCameraSoundForced) {
                        index = mIndexMax;
                    }
                }
                if (muteCount() == 0) {
                    mIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
                }
                mLastAudibleIndex.put(AudioSystem.DEVICE_OUT_DEFAULT, index);
                return;
            }

@@ -2618,10 +2649,11 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                remainingDevices &= ~device;

                // ignore settings for fixed volume devices: volume should always be at max
                if ((muteCount() == 0) &&
                        (mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) &&
                if ((mStreamVolumeAlias[mStreamType] == AudioSystem.STREAM_MUSIC) &&
                        ((device & mFixedVolumeDevices) != 0)) {
                    if (muteCount() == 0) {
                        mIndex.put(device, mIndexMax);
                    }
                    mLastAudibleIndex.put(device, mIndexMax);
                    continue;
                }
@@ -2676,9 +2708,11 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                            this,
                            PERSIST_DELAY);
                }
                if (muteCount() == 0) {
                    mIndex.put(device, getValidIndex(10 * index));
                }
            }
        }

        public void applyDeviceVolume(int device) {
            AudioSystem.setStreamVolumeIndex(mStreamType,
@@ -2716,6 +2750,11 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        public synchronized boolean setIndex(int index, int device, boolean lastAudible) {
            int oldIndex = getIndex(device, false  /* lastAudible */);
            index = getValidIndex(index);
            synchronized (mCameraSoundForced) {
                if ((mStreamType == AudioSystem.STREAM_SYSTEM_ENFORCED) && mCameraSoundForced) {
                    index = mIndexMax;
                }
            }
            mIndex.put(device, getValidIndex(index));

            if (oldIndex != index) {
@@ -2819,6 +2858,21 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
            }
        }

        public synchronized void setAllIndexesToMax() {
            Set set = mIndex.entrySet();
            Iterator i = set.iterator();
            while (i.hasNext()) {
                Map.Entry entry = (Map.Entry)i.next();
                entry.setValue(mIndexMax);
            }
            set = mLastAudibleIndex.entrySet();
            i = set.iterator();
            while (i.hasNext()) {
                Map.Entry entry = (Map.Entry)i.next();
                entry.setValue(mIndexMax);
            }
        }

        public synchronized void mute(IBinder cb, boolean state) {
            VolumeDeathHandler handler = getDeathHandler(cb, state);
            if (handler == null) {
@@ -2967,6 +3021,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        }

        private void dump(PrintWriter pw) {
            pw.print("   Mute count: ");
            pw.println(muteCount());
            pw.print("   Current: ");
            Set set = mIndex.entrySet();
            Iterator i = set.iterator();
@@ -3215,6 +3271,8 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                    // Restore forced usage for communcations and record
                    AudioSystem.setForceUse(AudioSystem.FOR_COMMUNICATION, mForcedUseForComm);
                    AudioSystem.setForceUse(AudioSystem.FOR_RECORD, mForcedUseForComm);
                    AudioSystem.setForceUse(AudioSystem.FOR_SYSTEM, mCameraSoundForced ?
                                    AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE);

                    // Restore stream volumes
                    int numStreamTypes = AudioSystem.getNumStreamTypes();
@@ -3372,6 +3430,13 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                } else {
                    ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_MUSIC);
                }
                synchronized (mCameraSoundForced) {
                    if (mCameraSoundForced) {
                        ringerModeAffectedStreams &= ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
                    } else {
                        ringerModeAffectedStreams |= (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
                    }
                }
                if (ringerModeAffectedStreams != mRingerModeAffectedStreams) {
                    /*
                     * Ensure all stream types that should be affected by ringer mode
@@ -5587,6 +5652,48 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
                    0,
                    null,
                    0);

            boolean cameraSoundForced = mContext.getResources().getBoolean(
                    com.android.internal.R.bool.config_camera_sound_forced);
            synchronized (mSettingsLock) {
                synchronized (mCameraSoundForced) {
                    if (cameraSoundForced != mCameraSoundForced) {
                        mCameraSoundForced = cameraSoundForced;

                        VolumeStreamState s = mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED];
                        if (cameraSoundForced) {
                            s.setAllIndexesToMax();
                            mRingerModeAffectedStreams &=
                                    ~(1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
                        } else {
                            s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM],
                                            false /*lastAudible*/);
                            s.setAllIndexes(mStreamStates[AudioSystem.STREAM_SYSTEM],
                                            true /*lastAudible*/);
                            mRingerModeAffectedStreams |=
                                    (1 << AudioSystem.STREAM_SYSTEM_ENFORCED);
                        }
                        // take new state into account for streams muted by ringer mode
                        setRingerModeInt(getRingerMode(), false);

                        sendMsg(mAudioHandler,
                                MSG_SET_FORCE_USE,
                                SENDMSG_QUEUE,
                                AudioSystem.FOR_SYSTEM,
                                cameraSoundForced ?
                                        AudioSystem.FORCE_SYSTEM_ENFORCED : AudioSystem.FORCE_NONE,
                                null,
                                0);

                        sendMsg(mAudioHandler,
                                MSG_SET_ALL_VOLUMES,
                                SENDMSG_QUEUE,
                                0,
                                0,
                                mStreamStates[AudioSystem.STREAM_SYSTEM_ENFORCED], 0);
                    }
                }
            }
        } catch (Exception e) {
            Log.e(TAG, "Error retrieving device orientation: " + e);
        }
@@ -5762,6 +5869,38 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
    }


    //==========================================================================================
    // Camera shutter sound policy.
    // config_camera_sound_forced configuration option in config.xml defines if the camera shutter
    // sound is forced (sound even if the device is in silent mode) or not. This option is false by
    // default and can be overridden by country specific overlay in values-mccXXX/config.xml.
    //==========================================================================================

    // cached value of com.android.internal.R.bool.config_camera_sound_forced
    private Boolean mCameraSoundForced;

    // called by android.hardware.Camera to populate CameraInfo.canDisableShutterSound
    public boolean isCameraSoundForced() {
        synchronized (mCameraSoundForced) {
            return mCameraSoundForced;
        }
    }

    private static final String[] RINGER_MODE_NAMES = new String[] {
            "SILENT",
            "VIBRATE",
            "NORMAL"
    };

    private void dumpRingerMode(PrintWriter pw) {
        pw.println("\nRinger mode: ");
        pw.println("- mode: "+RINGER_MODE_NAMES[mRingerMode]);
        pw.print("- ringer mode affected streams = 0x");
        pw.println(Integer.toHexString(mRingerModeAffectedStreams));
        pw.print("- ringer mode muted streams = 0x");
        pw.println(Integer.toHexString(mRingerModeMutedStreams));
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
@@ -5770,6 +5909,7 @@ public class AudioService extends IAudioService.Stub implements OnFinished {
        dumpRCStack(pw);
        dumpRCCStack(pw);
        dumpStreamStates(pw);
        dumpRingerMode(pw);
        pw.println("\nAudio routes:");
        pw.print("  mMainType=0x"); pw.println(Integer.toHexString(mCurAudioRoutes.mMainType));
        pw.print("  mBluetoothName="); pw.println(mCurAudioRoutes.mBluetoothName);
+4 −2
Original line number Diff line number Diff line
@@ -354,7 +354,8 @@ public class AudioSystem
    public static final int FORCE_DIGITAL_DOCK = 9;
    public static final int FORCE_NO_BT_A2DP = 10;
    public static final int FORCE_REMOTE_SUBMIX = 11;
    private static final int NUM_FORCE_CONFIG = 12;
    public static final int FORCE_SYSTEM_ENFORCED = 12;
    private static final int NUM_FORCE_CONFIG = 13;
    public static final int FORCE_DEFAULT = FORCE_NONE;

    // usage for setForceUse, must match AudioSystem::force_use
@@ -362,7 +363,8 @@ public class AudioSystem
    public static final int FOR_MEDIA = 1;
    public static final int FOR_RECORD = 2;
    public static final int FOR_DOCK = 3;
    private static final int NUM_FORCE_USE = 4;
    public static final int FOR_SYSTEM = 4;
    private static final int NUM_FORCE_USE = 5;

    // usage for AudioRecord.startRecordingSync(), must match AudioSystem::sync_event_t
    public static final int SYNC_EVENT_NONE = 0;
Loading