content: /*
   * Copyright (C) 2015 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.android.server.audio;
  
  import android.content.Context;
  import android.hardware.display.DisplayManager;
  import android.media.AudioSystem;
  import android.os.Handler;
  import android.util.Log;
  import android.view.Surface;
  import android.view.WindowManager;
  
  /**
   * Class to handle device rotation events for AudioService, and forward device rotation
   * to the audio HALs through AudioSystem.
   *
   * The role of this class is to monitor device orientation changes, and upon rotation,
   * verify the UI orientation. In case of a change, send the new orientation, in increments
   * of 90deg, through AudioSystem.
   *
   * Note that even though we're responding to device orientation events, we always
   * query the display rotation so audio stays in sync with video/dialogs. This is
   * done with .getDefaultDisplay().getRotation() from WINDOW_SERVICE.
   */
  class RotationHelper {
  
      private static final String TAG = "AudioService.RotationHelper";
  
      private static AudioDisplayListener sDisplayListener;
  
      private static final Object sRotationLock = new Object();
      private static int sDeviceRotation = Surface.ROTATION_0; // R/W synchronized on sRotationLock
  
      private static Context sContext;
      private static Handler sHandler;
  
      /**
       * post conditions:
       * - sDisplayListener != null
       * - sContext != null
       */
      static void init(Context context, Handler handler) {
          if (context == null) {
              throw new IllegalArgumentException("Invalid null context");
          }
          sContext = context;
          sHandler = handler;
          sDisplayListener = new AudioDisplayListener();
          enable();
      }
  
      static void enable() {
          ((DisplayManager) sContext.getSystemService(Context.DISPLAY_SERVICE))
                  .registerDisplayListener(sDisplayListener, sHandler);
          updateOrientation();
      }
  
      static void disable() {
          ((DisplayManager) sContext.getSystemService(Context.DISPLAY_SERVICE))
                  .unregisterDisplayListener(sDisplayListener);
      }
  
      /**
       * Query current display rotation and publish the change if any.
       */
      static void updateOrientation() {
          // Even though we're responding to device orientation events,
          // use display rotation so audio stays in sync with video/dialogs
          int newRotation = ((WindowManager) sContext.getSystemService(
                  Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
          synchronized(sRotationLock) {
              if (newRotation != sDeviceRotation) {
                  sDeviceRotation = newRotation;
                  publishRotation(sDeviceRotation);
              }
          }
      }
  
      private static void publishRotation(int rotation) {
          Log.v(TAG, "publishing device rotation =" + rotation + " (x90deg)");
          switch (rotation) {
              case Surface.ROTATION_0:
                  AudioSystem.setParameters("rotation=0");
                  break;
              case Surface.ROTATION_90:
                  AudioSystem.setParameters("rotation=90");
                  break;
              case Surface.ROTATION_180:
                  AudioSystem.setParameters("rotation=180");
                  break;
              case Surface.ROTATION_270:
                  AudioSystem.setParameters("rotation=270");
                  break;
              default:
                  Log.e(TAG, "Unknown device rotation");
          }
      }
  
      /**
       * Uses android.hardware.display.DisplayManager.DisplayListener
       */
      final static class AudioDisplayListener implements DisplayManager.DisplayListener {
  
          @Override
          public void onDisplayAdded(int displayId) {
          }
  
          @Override
          public void onDisplayRemoved(int displayId) {
          }
  
          @Override
          public void onDisplayChanged(int displayId) {
              updateOrientation();
          }
      }
  }