/*
 * Copyright (C) 2016 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.
 */
package com.google.android.exoplayer2.audio;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.support.annotation.Nullable;
import com.google.android.exoplayer2.util.Assertions;
import com.google.android.exoplayer2.util.Util;

/**
 * Receives broadcast events indicating changes to the device's audio capabilities, notifying a
 * {@link Listener} when audio capability changes occur.
 */
public final class AudioCapabilitiesReceiver {

  /**
   * Listener notified when audio capabilities change.
   */
  public interface Listener {

    /**
     * Called when the audio capabilities change.
     *
     * @param audioCapabilities The current audio capabilities for the device.
     */
    void onAudioCapabilitiesChanged(AudioCapabilities audioCapabilities);

  }

  private final Context context;
  private final Listener listener;
  private final @Nullable BroadcastReceiver receiver;

  /* package */ @Nullable AudioCapabilities audioCapabilities;

  /**
   * @param context A context for registering the receiver.
   * @param listener The listener to notify when audio capabilities change.
   */
  public AudioCapabilitiesReceiver(Context context, Listener listener) {
    this.context = Assertions.checkNotNull(context);
    this.listener = Assertions.checkNotNull(listener);
    this.receiver = Util.SDK_INT >= 21 ? new HdmiAudioPlugBroadcastReceiver() : null;
  }

  /**
   * Registers the receiver, meaning it will notify the listener when audio capability changes
   * occur. The current audio capabilities will be returned. It is important to call
   * {@link #unregister} when the receiver is no longer required.
   *
   * @return The current audio capabilities for the device.
   */
  @SuppressWarnings("InlinedApi")
  public AudioCapabilities register() {
    Intent stickyIntent = receiver == null ? null
        : context.registerReceiver(receiver, new IntentFilter(AudioManager.ACTION_HDMI_AUDIO_PLUG));
    audioCapabilities = AudioCapabilities.getCapabilities(stickyIntent);
    return audioCapabilities;
  }

  /**
   * Unregisters the receiver, meaning it will no longer notify the listener when audio capability
   * changes occur.
   */
  public void unregister() {
    if (receiver != null) {
      context.unregisterReceiver(receiver);
    }
  }

  private final class HdmiAudioPlugBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
      if (!isInitialStickyBroadcast()) {
        AudioCapabilities newAudioCapabilities = AudioCapabilities.getCapabilities(intent);
        if (!newAudioCapabilities.equals(audioCapabilities)) {
          audioCapabilities = newAudioCapabilities;
          listener.onAudioCapabilitiesChanged(newAudioCapabilities);
        }
      }
    }

  }

}

@@ -832,24 +832,51 @@
 dioManager;%0A
+import android.os.Handler;%0A
 import andro
@@ -907,16 +907,16 @@
 llable;%0A
-
 import c
@@ -1582,16 +1582,59 @@
 ontext;%0A
+  private final @Nullable Handler handler;%0A
   privat
@@ -1996,24 +1996,475 @@
 listener) %7B%0A
+    this(context, /* handler= */ null, listener);%0A  %7D%0A%0A  /**%0A   * @param context A context for registering the receiver.%0A   * @param handler The handler to which %7B@link Listener%7D events will be posted. If null, listener%0A   *     methods are invoked on the main thread.%0A   * @param listener The listener to notify when audio capabilities change.%0A   */%0A  public AudioCapabilitiesReceiver(Context context, @Nullable Handler handler, Listener listener) %7B%0A
     this.con
@@ -2500,24 +2500,52 @@
 l(context);%0A
+    this.handler = handler;%0A
     this.lis
@@ -3101,16 +3101,30 @@
 ntent = 
+null;%0A    if (
 receiver
@@ -3128,67 +3128,52 @@
 ver 
-=
+!
 = null
- ? null%0A        : context.registerReceiver(receiver,
+) %7B%0A      IntentFilter intentFilter =
  new
@@ -3222,18 +3222,292 @@
 IO_PLUG)
-)
 ;
+%0A      if (handler != null) %7B%0A        stickyIntent =%0A            context.registerReceiver(%0A                receiver, intentFilter, /* broadcastPermission= */ null, handler);%0A      %7D else %7B%0A        stickyIntent = context.registerReceiver(receiver, intentFilter);%0A      %7D%0A    %7D
 %0A    aud

Add support for reporting AudioCapabilities changes on custom threads