Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android link headphone volume to master volume

I have an android TV (Philips 49PUS6401) I want to connect a surround sound system to it which is much better quality than the built in speakers even when only being used in stereo.

however this TV separates the volume control for the master output and the headphone output, the result being that even with the in TV speakers turned off, the volume keys on the remote do not adjust the headphone volume (which i'm using as a line out)

I am planning to write a simple app to adjust the headphone volume whenever the mast volume is changed, but i can't seem to figure out how to get or set the headphone volume, as the audio manager deals with streams rather than outputs, so the only value i can get from it is the master.

How do I go about finding a way to get/set the headphone volume? I have got shell access through adb, but i cannot get root.

for reference the tv is running the latest firmware, which is android 5.1.1

like image 994
James Kent Avatar asked Oct 31 '16 20:10

James Kent


1 Answers

As I understand it is common issue of Philips Android TV users (for example p. 22 in this thread, or that discussion). In general, template for your task is Service which tracking plug/unplug event and volume of "system/music" audio stream (or media button press) than make corresponding changes on "wired headphones" audio "stream" (there is no such stream in "standard" Android, but obviously something like that present in "Android Philips") level. The issue is that seems to be impossible change volume "wiredheadphones" audio stream level using only Android SDK without "Philips Android TV API" (probably it's not a public).

Template source code for "VolumeTrackingService" may be something like this:

public class VolumeTrackingService extends Service {

    private static final String TAG = VolumeTrackingService.class.getSimpleName();

    public static final String ACTION_START = "VolumeTrackingService.ACTION_START";
    public static final String ACTION_STOP = "VolumeTrackingService.ACTION_STOP";

    HeadsetPlugIntentReceiver mHeadsetPlugReceiver;
    private static boolean mHeadsetPlugged = false;

    private SettingsContentObserver mSettingsContentObserver;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mHeadsetPlugReceiver = new HeadsetPlugIntentReceiver();
        registerReceiver(mHeadsetPlugReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
        mSettingsContentObserver = new SettingsContentObserver(new Handler());
        getApplicationContext().getContentResolver().registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mSettingsContentObserver);
    }

    @Override
    public void onDestroy() {
        getApplicationContext().getContentResolver().unregisterContentObserver(mSettingsContentObserver);
        unregisterReceiver(mHeadsetPlugReceiver);
        super.onDestroy();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null) {
            String actionRequested = intent.getAction();
            if (ACTION_START.equals(actionRequested)) {
            } else if (ACTION_STOP.equals(actionRequested)) {
                stopSelf();
            }
        }
        return START_STICKY;
    }

    private int getSystemVolumeInPercentage() {
        AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
        final int streamVolumeMax = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        final int streamVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        return 100 * streamVolume / streamVolumeMax;
    }

    private void setHeadphonesVolume(int volumeInPercentage) {
        // there should be magic of wired headphones volume level changing
    }

    private void processVolumeChanges() {
        if (mHeadsetPlugged) {
            int systemVolumeInPercentage = getSystemVolumeInPercentage();
            setHeadphonesVolume(systemVolumeInPercentage);
        }
    }


    public class SettingsContentObserver extends ContentObserver {

        public SettingsContentObserver(Handler handler) {
            super(handler);
        }

        @Override
        public boolean deliverSelfNotifications() {
            return super.deliverSelfNotifications();
        }

        @Override
        public void onChange(boolean selfChange) {
            super.onChange(selfChange);
            if (mHeadsetPlugged ) {
                processVolumeChanges();
            }
        }
    }

    public class HeadsetPlugIntentReceiver extends android.content.BroadcastReceiver {
        @Override
        public void onReceive(Context ctx, Intent intent) {
            if (intent.getAction().equals(android.media.AudioManager.ACTION_HEADSET_PLUG)) {
                mHeadsetPlugged = intent.getIntExtra("state", 0) == 1;
            }
        }
    }
}

unfortunately it not solves main issue: changing volume level of wired headphones (probably it's impossible without "Philips Android TV API").

But if your surround sound system has remote control You can do some workaround: emulate sound system remote control commands in Service described above and send it via IR dongle connected to USB Host of your Philips 49PUS6401 Android TV.

like image 163
Andrii Omelchenko Avatar answered Oct 18 '22 02:10

Andrii Omelchenko