Home | History | Annotate | Download | only in audio
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.audio;
     18 
     19 import android.content.Context;
     20 import android.hardware.display.DisplayManager;
     21 import android.media.AudioSystem;
     22 import android.os.Handler;
     23 import android.util.Log;
     24 import android.view.Surface;
     25 import android.view.WindowManager;
     26 
     27 /**
     28  * Class to handle device rotation events for AudioService, and forward device rotation
     29  * to the audio HALs through AudioSystem.
     30  *
     31  * The role of this class is to monitor device orientation changes, and upon rotation,
     32  * verify the UI orientation. In case of a change, send the new orientation, in increments
     33  * of 90deg, through AudioSystem.
     34  *
     35  * Note that even though we're responding to device orientation events, we always
     36  * query the display rotation so audio stays in sync with video/dialogs. This is
     37  * done with .getDefaultDisplay().getRotation() from WINDOW_SERVICE.
     38  */
     39 class RotationHelper {
     40 
     41     private static final String TAG = "AudioService.RotationHelper";
     42 
     43     private static AudioDisplayListener sDisplayListener;
     44 
     45     private static final Object sRotationLock = new Object();
     46     private static int sDeviceRotation = Surface.ROTATION_0; // R/W synchronized on sRotationLock
     47 
     48     private static Context sContext;
     49     private static Handler sHandler;
     50 
     51     /**
     52      * post conditions:
     53      * - sDisplayListener != null
     54      * - sContext != null
     55      */
     56     static void init(Context context, Handler handler) {
     57         if (context == null) {
     58             throw new IllegalArgumentException("Invalid null context");
     59         }
     60         sContext = context;
     61         sHandler = handler;
     62         sDisplayListener = new AudioDisplayListener();
     63         enable();
     64     }
     65 
     66     static void enable() {
     67         ((DisplayManager) sContext.getSystemService(Context.DISPLAY_SERVICE))
     68                 .registerDisplayListener(sDisplayListener, sHandler);
     69         updateOrientation();
     70     }
     71 
     72     static void disable() {
     73         ((DisplayManager) sContext.getSystemService(Context.DISPLAY_SERVICE))
     74                 .unregisterDisplayListener(sDisplayListener);
     75     }
     76 
     77     /**
     78      * Query current display rotation and publish the change if any.
     79      */
     80     static void updateOrientation() {
     81         // Even though we're responding to device orientation events,
     82         // use display rotation so audio stays in sync with video/dialogs
     83         int newRotation = ((WindowManager) sContext.getSystemService(
     84                 Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
     85         synchronized(sRotationLock) {
     86             if (newRotation != sDeviceRotation) {
     87                 sDeviceRotation = newRotation;
     88                 publishRotation(sDeviceRotation);
     89             }
     90         }
     91     }
     92 
     93     private static void publishRotation(int rotation) {
     94         Log.v(TAG, "publishing device rotation =" + rotation + " (x90deg)");
     95         switch (rotation) {
     96             case Surface.ROTATION_0:
     97                 AudioSystem.setParameters("rotation=0");
     98                 break;
     99             case Surface.ROTATION_90:
    100                 AudioSystem.setParameters("rotation=90");
    101                 break;
    102             case Surface.ROTATION_180:
    103                 AudioSystem.setParameters("rotation=180");
    104                 break;
    105             case Surface.ROTATION_270:
    106                 AudioSystem.setParameters("rotation=270");
    107                 break;
    108             default:
    109                 Log.e(TAG, "Unknown device rotation");
    110         }
    111     }
    112 
    113     /**
    114      * Uses android.hardware.display.DisplayManager.DisplayListener
    115      */
    116     final static class AudioDisplayListener implements DisplayManager.DisplayListener {
    117 
    118         @Override
    119         public void onDisplayAdded(int displayId) {
    120         }
    121 
    122         @Override
    123         public void onDisplayRemoved(int displayId) {
    124         }
    125 
    126         @Override
    127         public void onDisplayChanged(int displayId) {
    128             updateOrientation();
    129         }
    130     }
    131 }