• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
init(Context context, Handler handler)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 
enable()66     static void enable() {
67         ((DisplayManager) sContext.getSystemService(Context.DISPLAY_SERVICE))
68                 .registerDisplayListener(sDisplayListener, sHandler);
69         updateOrientation();
70     }
71 
disable()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      */
updateOrientation()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         // TODO(b/148458001): Support multi-display
84         int newRotation = ((WindowManager) sContext.getSystemService(
85                 Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
86         synchronized(sRotationLock) {
87             if (newRotation != sDeviceRotation) {
88                 sDeviceRotation = newRotation;
89                 publishRotation(sDeviceRotation);
90             }
91         }
92     }
93 
publishRotation(int rotation)94     private static void publishRotation(int rotation) {
95         Log.v(TAG, "publishing device rotation =" + rotation + " (x90deg)");
96         switch (rotation) {
97             case Surface.ROTATION_0:
98                 AudioSystem.setParameters("rotation=0");
99                 break;
100             case Surface.ROTATION_90:
101                 AudioSystem.setParameters("rotation=90");
102                 break;
103             case Surface.ROTATION_180:
104                 AudioSystem.setParameters("rotation=180");
105                 break;
106             case Surface.ROTATION_270:
107                 AudioSystem.setParameters("rotation=270");
108                 break;
109             default:
110                 Log.e(TAG, "Unknown device rotation");
111         }
112     }
113 
114     /**
115      * Uses android.hardware.display.DisplayManager.DisplayListener
116      */
117     final static class AudioDisplayListener implements DisplayManager.DisplayListener {
118 
119         @Override
onDisplayAdded(int displayId)120         public void onDisplayAdded(int displayId) {
121         }
122 
123         @Override
onDisplayRemoved(int displayId)124         public void onDisplayRemoved(int displayId) {
125         }
126 
127         @Override
onDisplayChanged(int displayId)128         public void onDisplayChanged(int displayId) {
129             updateOrientation();
130         }
131     }
132 }