summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/A2dpAudioInterface.cpp89
-rw-r--r--services/audioflinger/A2dpAudioInterface.h1
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java29
-rw-r--r--services/java/com/android/server/ScreenRotationAnimation.java152
-rw-r--r--services/java/com/android/server/WindowManagerService.java43
5 files changed, 269 insertions, 45 deletions
diff --git a/services/audioflinger/A2dpAudioInterface.cpp b/services/audioflinger/A2dpAudioInterface.cpp
index 995e31c..aee01ab 100644
--- a/services/audioflinger/A2dpAudioInterface.cpp
+++ b/services/audioflinger/A2dpAudioInterface.cpp
@@ -23,10 +23,13 @@
#include "A2dpAudioInterface.h"
#include "audio/liba2dp.h"
-
+#include <hardware_legacy/power.h>
namespace android {
+static const char *sA2dpWakeLock = "A2dpOutputStream";
+#define MAX_WRITE_RETRIES 5
+
// ----------------------------------------------------------------------------
//AudioHardwareInterface* A2dpAudioInterface::createA2dpInterface()
@@ -263,44 +266,55 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
A2dpAudioInterface::A2dpAudioStreamOut::~A2dpAudioStreamOut()
{
LOGV("A2dpAudioStreamOut destructor");
- standby();
close();
LOGV("A2dpAudioStreamOut destructor returning from close()");
}
ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t bytes)
{
- Mutex::Autolock lock(mLock);
-
- size_t remaining = bytes;
status_t status = -1;
+ {
+ Mutex::Autolock lock(mLock);
- if (!mBluetoothEnabled || mClosing || mSuspended) {
- LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
- mBluetoothEnabled %d, mClosing %d, mSuspended %d",
- mBluetoothEnabled, mClosing, mSuspended);
- goto Error;
- }
-
- status = init();
- if (status < 0)
- goto Error;
+ size_t remaining = bytes;
- while (remaining > 0) {
- status = a2dp_write(mData, buffer, remaining);
- if (status <= 0) {
- LOGE("a2dp_write failed err: %d\n", status);
+ if (!mBluetoothEnabled || mClosing || mSuspended) {
+ LOGV("A2dpAudioStreamOut::write(), but bluetooth disabled \
+ mBluetoothEnabled %d, mClosing %d, mSuspended %d",
+ mBluetoothEnabled, mClosing, mSuspended);
goto Error;
}
- remaining -= status;
- buffer = ((char *)buffer) + status;
- }
- mStandby = false;
+ if (mStandby) {
+ acquire_wake_lock (PARTIAL_WAKE_LOCK, sA2dpWakeLock);
+ mStandby = false;
+ }
+
+ status = init();
+ if (status < 0)
+ goto Error;
+
+ int retries = MAX_WRITE_RETRIES;
+ while (remaining > 0 && retries) {
+ status = a2dp_write(mData, buffer, remaining);
+ if (status < 0) {
+ LOGE("a2dp_write failed err: %d\n", status);
+ goto Error;
+ }
+ if (status == 0) {
+ retries--;
+ }
+ remaining -= status;
+ buffer = (char *)buffer + status;
+ }
- return bytes;
+ return bytes;
+ }
Error:
+
+ standby();
+
// Simulate audio output timing in case of error
usleep(((bytes * 1000 )/ frameSize() / sampleRate()) * 1000);
@@ -324,19 +338,22 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::init()
status_t A2dpAudioInterface::A2dpAudioStreamOut::standby()
{
- int result = 0;
-
- if (mClosing) {
- LOGV("Ignore standby, closing");
- return result;
- }
-
Mutex::Autolock lock(mLock);
+ return standby_l();
+}
+
+status_t A2dpAudioInterface::A2dpAudioStreamOut::standby_l()
+{
+ int result = NO_ERROR;
if (!mStandby) {
- result = a2dp_stop(mData);
- if (result == 0)
- mStandby = true;
+ LOGV_IF(mClosing || !mBluetoothEnabled, "Standby skip stop: closing %d enabled %d",
+ mClosing, mBluetoothEnabled);
+ if (!mClosing && mBluetoothEnabled) {
+ result = a2dp_stop(mData);
+ }
+ release_wake_lock(sA2dpWakeLock);
+ mStandby = true;
}
return result;
@@ -362,6 +379,9 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::setParameters(const String8& ke
key = String8("closing");
if (param.get(key, value) == NO_ERROR) {
mClosing = (value == "true");
+ if (mClosing) {
+ standby();
+ }
param.remove(key);
}
key = AudioParameter::keyRouting;
@@ -444,6 +464,7 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::close()
status_t A2dpAudioInterface::A2dpAudioStreamOut::close_l()
{
+ standby_l();
if (mData) {
LOGV("A2dpAudioStreamOut::close_l() calling a2dp_cleanup(mData)");
a2dp_cleanup(mData);
diff --git a/services/audioflinger/A2dpAudioInterface.h b/services/audioflinger/A2dpAudioInterface.h
index 48154f9..cef1926 100644
--- a/services/audioflinger/A2dpAudioInterface.h
+++ b/services/audioflinger/A2dpAudioInterface.h
@@ -103,6 +103,7 @@ private:
status_t setAddress(const char* address);
status_t setBluetoothEnabled(bool enabled);
status_t setSuspended(bool onOff);
+ status_t standby_l();
private:
int mFd;
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index eca37b7..723432d 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -1300,7 +1300,18 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
public void setInputMethod(IBinder token, String id) {
- setInputMethodWithSubtype(token, id, NOT_A_SUBTYPE_ID);
+ setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
+ }
+
+ public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
+ synchronized (mMethodMap) {
+ if (subtype != null) {
+ setInputMethodWithSubtypeId(token, id, getSubtypeIdFromHashCode(
+ mMethodMap.get(id), subtype.hashCode()));
+ } else {
+ setInputMethod(token, id);
+ }
+ }
}
public boolean switchToLastInputMethod(IBinder token) {
@@ -1309,7 +1320,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (lastIme != null) {
InputMethodInfo imi = mMethodMap.get(lastIme.first);
if (imi != null) {
- setInputMethodWithSubtype(token, lastIme.first, getSubtypeIdFromHashCode(
+ setInputMethodWithSubtypeId(token, lastIme.first, getSubtypeIdFromHashCode(
imi, Integer.valueOf(lastIme.second)));
return true;
}
@@ -1318,7 +1329,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
- private void setInputMethodWithSubtype(IBinder token, String id, int subtypeId) {
+ private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
synchronized (mMethodMap) {
if (token == null) {
if (mContext.checkCallingOrSelfPermission(
@@ -1909,11 +1920,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
private int getSubtypeIdFromHashCode(InputMethodInfo imi, int subtypeHashCode) {
- ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes();
- for (int i = 0; i < subtypes.size(); ++i) {
- InputMethodSubtype ims = subtypes.get(i);
- if (subtypeHashCode == ims.hashCode()) {
- return i;
+ if (imi != null) {
+ ArrayList<InputMethodSubtype> subtypes = imi.getSubtypes();
+ for (int i = 0; i < subtypes.size(); ++i) {
+ InputMethodSubtype ims = subtypes.get(i);
+ if (subtypeHashCode == ims.hashCode()) {
+ return i;
+ }
}
}
return NOT_A_SUBTYPE_ID;
diff --git a/services/java/com/android/server/ScreenRotationAnimation.java b/services/java/com/android/server/ScreenRotationAnimation.java
new file mode 100644
index 0000000..299567a
--- /dev/null
+++ b/services/java/com/android/server/ScreenRotationAnimation.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2010 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; // TODO: use com.android.server.wm, once things move there
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.util.DisplayMetrics;
+import android.util.Slog;
+import android.view.Display;
+import android.view.Surface;
+import android.view.SurfaceSession;
+
+class ScreenRotationAnimation {
+ private static final String TAG = "ScreenRotationAnimation";
+
+ Surface mSurface;
+ int mWidth, mHeight;
+
+ int mBaseRotation;
+ int mCurRotation;
+ int mDeltaRotation;
+
+ final Matrix mMatrix = new Matrix();
+ final float[] mTmpFloats = new float[9];
+
+ public ScreenRotationAnimation(Display display, SurfaceSession session) {
+ final DisplayMetrics dm = new DisplayMetrics();
+ display.getMetrics(dm);
+
+ Bitmap screenshot = Surface.screenshot(0, 0);
+
+ if (screenshot != null) {
+ // Screenshot does NOT include rotation!
+ mBaseRotation = 0;
+ mWidth = screenshot.getWidth();
+ mHeight = screenshot.getHeight();
+ } else {
+ // Just in case.
+ mBaseRotation = display.getRotation();
+ mWidth = dm.widthPixels;
+ mHeight = dm.heightPixels;
+ }
+
+ Surface.openTransaction();
+ if (mSurface != null) {
+ mSurface.destroy();
+ mSurface = null;
+ }
+ try {
+ mSurface = new Surface(session, 0, "FreezeSurface",
+ -1, mWidth, mHeight, PixelFormat.OPAQUE, 0);
+ } catch (Surface.OutOfResourcesException e) {
+ Slog.w(TAG, "Unable to allocate freeze surface", e);
+ }
+ mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 200);
+ setRotation(display.getRotation());
+
+ Rect dirty = new Rect(0, 0, mWidth, mHeight);
+ Canvas c = null;
+ try {
+ c = mSurface.lockCanvas(dirty);
+ } catch (IllegalArgumentException e) {
+ Slog.w(TAG, "Unable to lock surface", e);
+ return;
+ } catch (Surface.OutOfResourcesException e) {
+ Slog.w(TAG, "Unable to lock surface", e);
+ return;
+ }
+ if (c == null) {
+ Slog.w(TAG, "Null surface");
+ return;
+ }
+
+ if (screenshot != null) {
+ c.drawBitmap(screenshot, 0, 0, new Paint(0));
+ } else {
+ c.drawColor(Color.GREEN);
+ }
+
+ mSurface.unlockCanvasAndPost(c);
+ Surface.closeTransaction();
+
+ screenshot.recycle();
+ }
+
+ // Must be called while in a transaction.
+ public void setRotation(int rotation) {
+ mCurRotation = rotation;
+ int delta = mCurRotation - mBaseRotation;
+ if (delta < 0) delta += 4;
+ mDeltaRotation = delta;
+
+ switch (delta) {
+ case Surface.ROTATION_0:
+ mMatrix.reset();
+ break;
+ case Surface.ROTATION_90:
+ mMatrix.setRotate(90, 0, 0);
+ mMatrix.postTranslate(0, mWidth);
+ break;
+ case Surface.ROTATION_180:
+ mMatrix.setRotate(180, 0, 0);
+ mMatrix.postTranslate(mWidth, mHeight);
+ break;
+ case Surface.ROTATION_270:
+ mMatrix.setRotate(270, 0, 0);
+ mMatrix.postTranslate(mHeight, 0);
+ break;
+ }
+
+ mMatrix.getValues(mTmpFloats);
+ mSurface.setPosition((int)mTmpFloats[Matrix.MTRANS_X],
+ (int)mTmpFloats[Matrix.MTRANS_Y]);
+ mSurface.setMatrix(
+ mTmpFloats[Matrix.MSCALE_X], mTmpFloats[Matrix.MSKEW_X],
+ mTmpFloats[Matrix.MSKEW_Y], mTmpFloats[Matrix.MSCALE_Y]);
+
+ if (false) {
+ float[] srcPnts = new float[] { 0, 0, mWidth, mHeight };
+ float[] dstPnts = new float[8];
+ mMatrix.mapPoints(dstPnts, srcPnts);
+ Slog.i(TAG, "**** ROTATION: " + delta);
+ Slog.i(TAG, "Original : (" + srcPnts[0] + "," + srcPnts[1]
+ + ")-(" + srcPnts[2] + "," + srcPnts[3] + ")");
+ Slog.i(TAG, "Transformed: (" + dstPnts[0] + "," + dstPnts[1]
+ + ")-(" + dstPnts[2] + "," + dstPnts[3] + ")");
+ }
+ }
+
+ public void dismiss() {
+ mSurface.destroy();
+ }
+}
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index b3ea836..89512ae 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -201,6 +201,12 @@ public class WindowManagerService extends IWindowManager.Stub
*/
static final int DEFAULT_FADE_IN_OUT_DURATION = 400;
+ /**
+ * If true, the window manager will do its own custom freezing and general
+ * management of the screen during rotation.
+ */
+ static final boolean CUSTOM_SCREEN_ROTATION = true;
+
// Maximum number of milliseconds to wait for input event injection.
// FIXME is this value reasonable?
private static final int INJECTION_TIMEOUT_MILLIS = 30 * 1000;
@@ -374,6 +380,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean mBlurShown;
Watermark mWatermark;
StrictModeFlash mStrictModeFlash;
+ ScreenRotationAnimation mScreenRotationAnimation;
int mTransactionSequence = 0;
@@ -4911,6 +4918,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ public void setStrictModeVisualIndicatorPreference(String value) {
+ SystemProperties.set(StrictMode.VISUAL_PROPERTY, value);
+ }
+
public void freezeRotation() {
if (!checkCallingPermission(android.Manifest.permission.SET_ORIENTATION,
"setRotation()")) {
@@ -4998,7 +5009,18 @@ public class WindowManagerService extends IWindowManager.Stub
Slog.i(TAG, "Setting rotation to " + rotation + ", animFlags=" + animFlags);
mInputManager.setDisplayOrientation(0, rotation);
if (mDisplayEnabled) {
- Surface.setOrientation(0, rotation, animFlags);
+ if (CUSTOM_SCREEN_ROTATION) {
+ Surface.freezeDisplay(0);
+ Surface.openTransaction();
+ if (mScreenRotationAnimation != null) {
+ mScreenRotationAnimation.setRotation(rotation);
+ }
+ Surface.closeTransaction();
+ Surface.setOrientation(0, rotation, animFlags);
+ Surface.unfreezeDisplay(0);
+ } else {
+ Surface.setOrientation(0, rotation, animFlags);
+ }
}
for (int i=mWindows.size()-1; i>=0; i--) {
WindowState w = mWindows.get(i);
@@ -10817,7 +10839,14 @@ public class WindowManagerService extends IWindowManager.Stub
File file = new File("/data/system/frozen");
Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
}
- Surface.freezeDisplay(0);
+
+ if (CUSTOM_SCREEN_ROTATION) {
+ if (mScreenRotationAnimation == null) {
+ mScreenRotationAnimation = new ScreenRotationAnimation(mDisplay, mFxSession);
+ }
+ } else {
+ Surface.freezeDisplay(0);
+ }
}
private void stopFreezingDisplayLocked() {
@@ -10834,7 +10863,15 @@ public class WindowManagerService extends IWindowManager.Stub
if (PROFILE_ORIENTATION) {
Debug.stopMethodTracing();
}
- Surface.unfreezeDisplay(0);
+
+ if (CUSTOM_SCREEN_ROTATION) {
+ if (mScreenRotationAnimation != null) {
+ mScreenRotationAnimation.dismiss();
+ mScreenRotationAnimation = null;
+ }
+ } else {
+ Surface.unfreezeDisplay(0);
+ }
mInputMonitor.thawInputDispatchingLw();