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

Commit cfcf1032 authored by jiabin's avatar jiabin
Browse files

Add context in AudioManager.hasHapticChannels.

A context will be required for resolving a Uri. Using the context in
AudioService may not always work and it may cause not oneway binder call
issue. In that case, using the context in RingtoneManager could help.
In AudioManager, caching a static context so that it can be used when
there is not context provided.

Test: atest RingtoneManagerTest
Bug: 187842281
Change-Id: Ia2f514cb8f821926cf3d353cf912a44aeb584ab6
parent 35929095
Loading
Loading
Loading
Loading
+48 −4
Original line number Original line Diff line number Diff line
@@ -103,6 +103,8 @@ public class AudioManager {
    private static final AudioVolumeGroupChangeHandler sAudioAudioVolumeGroupChangedHandler =
    private static final AudioVolumeGroupChangeHandler sAudioAudioVolumeGroupChangedHandler =
            new AudioVolumeGroupChangeHandler();
            new AudioVolumeGroupChangeHandler();


    private static Context sContext;

    /**
    /**
     * Broadcast intent, a hint for applications that audio is about to become
     * Broadcast intent, a hint for applications that audio is about to become
     * 'noisy' due to a change in audio outputs. For example, this intent may
     * 'noisy' due to a change in audio outputs. For example, this intent may
@@ -798,6 +800,7 @@ public class AudioManager {
        } else {
        } else {
            mOriginalContext = context;
            mOriginalContext = context;
        }
        }
        sContext = context;
    }
    }


    @UnsupportedAppUsage
    @UnsupportedAppUsage
@@ -7220,17 +7223,58 @@ public class AudioManager {


    /**
    /**
     * Return if an asset contains haptic channels or not.
     * Return if an asset contains haptic channels or not.
     *
     * @param context the {@link Context} to resolve the uri.
     * @param uri the {@link Uri} of the asset.
     * @param uri the {@link Uri} of the asset.
     * @return true if the assert contains haptic channels.
     * @return true if the assert contains haptic channels.
     * @hide
     * @hide
     */
     */
    public static boolean hasHapticChannels(Uri uri) {
    public static boolean hasHapticChannelsImpl(@NonNull Context context, @NonNull Uri uri) {
        MediaExtractor extractor = new MediaExtractor();
        try {
            extractor.setDataSource(context, uri, null);
            for (int i = 0; i < extractor.getTrackCount(); i++) {
                MediaFormat format = extractor.getTrackFormat(i);
                if (format.containsKey(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT)
                        && format.getInteger(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT) > 0) {
                    return true;
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "hasHapticChannels failure:" + e);
        }
        return false;
    }

    /**
     * Return if an asset contains haptic channels or not.
     *
     * @param context the {@link Context} to resolve the uri.
     * @param uri the {@link Uri} of the asset.
     * @return true if the assert contains haptic channels.
     * @hide
     */
    public static boolean hasHapticChannels(@Nullable Context context, @NonNull Uri uri) {
        Objects.requireNonNull(uri);
        if (context != null) {
            return hasHapticChannelsImpl(context, uri);
        } else if (sContext != null) {
            if (DEBUG) {
                Log.d(TAG, "Try to use static context to query if having haptic channels");
            }
            return hasHapticChannelsImpl(sContext, uri);
        } else {
            // Try with audio service context, this may fail to get correct result.
            if (DEBUG) {
                Log.d(TAG, "Try to use audio service context to query if having haptic channels");
            }
            try {
            try {
                return getService().hasHapticChannels(uri);
                return getService().hasHapticChannels(uri);
            } catch (RemoteException e) {
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
                throw e.rethrowFromSystemServer();
            }
            }
        }
        }
    }


    /**
    /**
     * Set whether or not there is an active RTT call.
     * Set whether or not there is an active RTT call.
+1 −1
Original line number Original line Diff line number Diff line
@@ -407,7 +407,7 @@ public class Ringtone {
        if (mLocalPlayer != null) {
        if (mLocalPlayer != null) {
            // Play ringtones if stream volume is over 0 or if it is a haptic-only ringtone
            // Play ringtones if stream volume is over 0 or if it is a haptic-only ringtone
            // (typically because ringer mode is vibrate).
            // (typically because ringer mode is vibrate).
            boolean isHapticOnly = AudioManager.hasHapticChannels(mUri)
            boolean isHapticOnly = AudioManager.hasHapticChannels(mContext, mUri)
                    && !mAudioAttributes.areHapticChannelsMuted() && mVolume == 0;
                    && !mAudioAttributes.areHapticChannelsMuted() && mVolume == 0;
            if (isHapticOnly || mAudioManager.getStreamVolume(
            if (isHapticOnly || mAudioManager.getStreamVolume(
                    AudioAttributes.toLegacyStreamType(mAudioAttributes)) != 0) {
                    AudioAttributes.toLegacyStreamType(mAudioAttributes)) != 0) {
+6 −3
Original line number Original line Diff line number Diff line
@@ -1082,18 +1082,21 @@ public class RingtoneManager {
     * @return true if the ringtone contains haptic channels.
     * @return true if the ringtone contains haptic channels.
     */
     */
    public boolean hasHapticChannels(int position) {
    public boolean hasHapticChannels(int position) {
        return hasHapticChannels(getRingtoneUri(position));
        return AudioManager.hasHapticChannels(mContext, getRingtoneUri(position));
    }
    }


    /**
    /**
     * Returns if the {@link Ringtone} from a given sound URI contains
     * Returns if the {@link Ringtone} from a given sound URI contains
     * haptic channels or not.
     * haptic channels or not. As this function doesn't has a context
     * to resolve the uri, the result may be wrong if the uri cannot be
     * resolved correctly.
     * Use {@link #hasHapticChannels(int)} instead when possible.
     *
     *
     * @param ringtoneUri The {@link Uri} of a sound or ringtone.
     * @param ringtoneUri The {@link Uri} of a sound or ringtone.
     * @return true if the ringtone contains haptic channels.
     * @return true if the ringtone contains haptic channels.
     */
     */
    public static boolean hasHapticChannels(@NonNull Uri ringtoneUri) {
    public static boolean hasHapticChannels(@NonNull Uri ringtoneUri) {
        return AudioManager.hasHapticChannels(ringtoneUri);
        return AudioManager.hasHapticChannels(null, ringtoneUri);
    }
    }


    /**
    /**
+2 −18
Original line number Original line Diff line number Diff line
@@ -95,8 +95,6 @@ import android.media.IRecordingConfigDispatcher;
import android.media.IRingtonePlayer;
import android.media.IRingtonePlayer;
import android.media.IStrategyPreferredDevicesDispatcher;
import android.media.IStrategyPreferredDevicesDispatcher;
import android.media.IVolumeController;
import android.media.IVolumeController;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.media.MediaMetrics;
import android.media.MediaMetrics;
import android.media.MediaRecorder.AudioSource;
import android.media.MediaRecorder.AudioSource;
import android.media.PlayerBase;
import android.media.PlayerBase;
@@ -163,7 +161,6 @@ import com.android.server.pm.UserManagerService;
import com.android.server.wm.ActivityTaskManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;


import java.io.FileDescriptor;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
@@ -6305,23 +6302,10 @@ public class AudioService extends IAudioService.Stub
    }
    }


    /**
    /**
     * See AudioManager.hasHapticChannels(Uri).
     * See AudioManager.hasHapticChannels(Context, Uri).
     */
     */
    public boolean hasHapticChannels(Uri uri) {
    public boolean hasHapticChannels(Uri uri) {
        MediaExtractor extractor = new MediaExtractor();
        return AudioManager.hasHapticChannelsImpl(mContext, uri);
        try {
            extractor.setDataSource(mContext, uri, null);
            for (int i = 0; i < extractor.getTrackCount(); i++) {
                MediaFormat format = extractor.getTrackFormat(i);
                if (format.containsKey(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT)
                        && format.getInteger(MediaFormat.KEY_HAPTIC_CHANNEL_COUNT) > 0) {
                    return true;
                }
            }
        } catch (IOException e) {
            Log.e(TAG, "hasHapticChannels failure:" + e);
        }
        return false;
    }
    }


    ///////////////////////////////////////////////////////////////////////////
    ///////////////////////////////////////////////////////////////////////////