diff options
7 files changed, 159 insertions, 42 deletions
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java index 0f8efd10f436..6056c75f3b96 100644 --- a/core/java/android/text/SpannableStringBuilder.java +++ b/core/java/android/text/SpannableStringBuilder.java @@ -18,6 +18,7 @@ package android.text; import android.graphics.Canvas; import android.graphics.Paint; +import android.util.Log; import com.android.internal.util.ArrayUtils; @@ -485,15 +486,12 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable // 0-length Spanned.SPAN_EXCLUSIVE_EXCLUSIVE if (flagsStart == POINT && flagsEnd == MARK && start == end) { - if (send) { - throw new IllegalArgumentException( - "SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length"); - } else { - // Silently ignore invalid spans when they are created from this class. - // This avoids the duplication of the above test code before all the - // calls to setSpan that are done in this class - return; - } + if (send) Log.e("SpannableStringBuilder", + "SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length"); + // Silently ignore invalid spans when they are created from this class. + // This avoids the duplication of the above test code before all the + // calls to setSpan that are done in this class + return; } int nstart = start; diff --git a/media/java/android/media/audiofx/AcousticEchoCanceler.java b/media/java/android/media/audiofx/AcousticEchoCanceler.java index 7197dd2fc768..e31f84c0e7cc 100644 --- a/media/java/android/media/audiofx/AcousticEchoCanceler.java +++ b/media/java/android/media/audiofx/AcousticEchoCanceler.java @@ -16,6 +16,8 @@ package android.media.audiofx; +import android.util.Log; + /** * Acoustic Echo Canceler (AEC). * <p>Acoustic Echo Canceler (AEC) is an audio pre-processing which removes the contribution of the @@ -26,14 +28,13 @@ package android.media.audiofx; * <p>An application creates an AcousticEchoCanceler object to instantiate and control an AEC * engine in the audio capture path. * <p>To attach the AcousticEchoCanceler to a particular {@link android.media.AudioRecord}, - * specify the audio session ID of this AudioRecord when constructing the AcousticEchoCanceler. + * specify the audio session ID of this AudioRecord when creating the AcousticEchoCanceler. * The audio session is retrieved by calling * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance. * <p>On some devices, an AEC can be inserted by default in the capture path by the platform - * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can - * query which pre-processings are currently applied to an AudioRecord instance by calling - * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the - * AudioRecord. + * according to the {@link android.media.MediaRecorder.AudioSource} used. The application should + * call AcousticEchoCanceler.getEnable() after creating the AEC to check the default AEC activation + * state on a particular AudioRecord session. * <p>See {@link android.media.audiofx.AudioEffect} class for more details on * controlling audio effects. * @hide @@ -44,13 +45,43 @@ public class AcousticEchoCanceler extends AudioEffect { private final static String TAG = "AcousticEchoCanceler"; /** + * Checks if the device implements acoustic echo cancellation. + * @return true if the device implements acoustic echo cancellation, false otherwise. + */ + public static boolean isAvailable() { + return AudioEffect.isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_AEC); + } + + /** + * Creates an AcousticEchoCanceler and attaches it to the AudioRecord on the audio + * session specified. + * @param audioSession system wide unique audio session identifier. The AcousticEchoCanceler + * will be applied to the AudioRecord with the same audio session. + * @return AcousticEchoCanceler created or null if the device does not implement AEC. + */ + public static AcousticEchoCanceler create(int audioSession) { + AcousticEchoCanceler aec = null; + try { + aec = new AcousticEchoCanceler(audioSession); + } catch (IllegalArgumentException e) { + Log.w(TAG, "not implemented on this device"+ aec); + } catch (UnsupportedOperationException e) { + Log.w(TAG, "not enough resources"); + } catch (RuntimeException e) { + Log.w(TAG, "not enough memory"); + } finally { + return aec; + } + } + + /** * Class constructor. - * <p> The application must catch exceptions when creating an AcousticEchoCanceler as the - * constructor is not guarantied to succeed: + * <p> The constructor is not guarantied to succeed and throws the following exceptions: * <ul> * <li>IllegalArgumentException is thrown if the device does not implement an AEC</li> * <li>UnsupportedOperationException is thrown is the resources allocated to audio * pre-procesing are currently exceeded.</li> + * <li>RuntimeException is thrown if a memory allocation error occurs.</li> * </ul> * * @param audioSession system wide unique audio session identifier. The AcousticEchoCanceler @@ -59,6 +90,7 @@ public class AcousticEchoCanceler extends AudioEffect { * @throws java.lang.IllegalArgumentException * @throws java.lang.UnsupportedOperationException * @throws java.lang.RuntimeException + * @hide */ public AcousticEchoCanceler(int audioSession) throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java index 85be26733023..68a09de83543 100644 --- a/media/java/android/media/audiofx/AudioEffect.java +++ b/media/java/android/media/audiofx/AudioEffect.java @@ -452,6 +452,22 @@ public class AudioEffect { return (Descriptor[]) native_query_pre_processing(audioSession); } + /** + * Checks if the device implements the specified effect type. + * @param type the requested effect type. + * @return true if the device implements the specified effect type, false otherwise. + * @hide + */ + public static boolean isEffectTypeAvailable(UUID type) { + AudioEffect.Descriptor[] desc = AudioEffect.queryEffects(); + for (int i = 0; i < desc.length; i++) { + if (desc[i].type.equals(type)) { + return true; + } + } + return false; + } + // -------------------------------------------------------------------------- // Control methods // -------------------- diff --git a/media/java/android/media/audiofx/AutomaticGainControl.java b/media/java/android/media/audiofx/AutomaticGainControl.java index 44574f06f857..eca7eec618d8 100644 --- a/media/java/android/media/audiofx/AutomaticGainControl.java +++ b/media/java/android/media/audiofx/AutomaticGainControl.java @@ -16,24 +16,25 @@ package android.media.audiofx; +import android.util.Log; + /** * Automatic Gain Control (AGC). * <p>Automatic Gain Control (AGC) is an audio pre-processing which automatically normalizes the * output of the captured signal by boosting or lowering input from the microphone to match a preset - * level so that that the output signal level is virtually constant. + * level so that the output signal level is virtually constant. * AGC can be used by applications where the input signal dynamic range is not important but where * a constant strong capture level is desired. * <p>An application creates a AutomaticGainControl object to instantiate and control an AGC * engine in the audio framework. * <p>To attach the AutomaticGainControl to a particular {@link android.media.AudioRecord}, - * specify the audio session ID of this AudioRecord when constructing the AutomaticGainControl. + * specify the audio session ID of this AudioRecord when creating the AutomaticGainControl. * The audio session is retrieved by calling * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance. * <p>On some devices, an AGC can be inserted by default in the capture path by the platform - * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can - * query which pre-processings are currently applied to an AudioRecord instance by calling - * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the - * AudioRecord. + * according to the {@link android.media.MediaRecorder.AudioSource} used. The application should + * call AutomaticGainControl.getEnable() after creating the AGC to check the default AGC activation + * state on a particular AudioRecord session. * <p>See {@link android.media.audiofx.AudioEffect} class for more details on * controlling audio effects. * @hide @@ -44,13 +45,43 @@ public class AutomaticGainControl extends AudioEffect { private final static String TAG = "AutomaticGainControl"; /** + * Checks if the device implements automatic gain control. + * @return true if the device implements automatic gain control, false otherwise. + */ + public static boolean isAvailable() { + return AudioEffect.isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_AGC); + } + + /** + * Creates an AutomaticGainControl and attaches it to the AudioRecord on the audio + * session specified. + * @param audioSession system wide unique audio session identifier. The AutomaticGainControl + * will be applied to the AudioRecord with the same audio session. + * @return AutomaticGainControl created or null if the device does not implement AGC. + */ + public static AutomaticGainControl create(int audioSession) { + AutomaticGainControl agc = null; + try { + agc = new AutomaticGainControl(audioSession); + } catch (IllegalArgumentException e) { + Log.w(TAG, "not implemented on this device "+agc); + } catch (UnsupportedOperationException e) { + Log.w(TAG, "not enough resources"); + } catch (RuntimeException e) { + Log.w(TAG, "not enough memory"); + } finally { + return agc; + } + } + + /** * Class constructor. - * <p> The application must catch exceptions when creating an AutomaticGainControl as the - * constructor is not guarantied to succeed: + * <p> The constructor is not guarantied to succeed and throws the following exceptions: * <ul> * <li>IllegalArgumentException is thrown if the device does not implement an AGC</li> * <li>UnsupportedOperationException is thrown is the resources allocated to audio * pre-procesing are currently exceeded.</li> + * <li>RuntimeException is thrown if a memory allocation error occurs.</li> * </ul> * * @param audioSession system wide unique audio session identifier. The AutomaticGainControl @@ -59,6 +90,7 @@ public class AutomaticGainControl extends AudioEffect { * @throws java.lang.IllegalArgumentException * @throws java.lang.UnsupportedOperationException * @throws java.lang.RuntimeException + * @hide */ public AutomaticGainControl(int audioSession) throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { diff --git a/media/java/android/media/audiofx/NoiseSuppressor.java b/media/java/android/media/audiofx/NoiseSuppressor.java index 4e7a8b6ef07f..a2d3386c0841 100644 --- a/media/java/android/media/audiofx/NoiseSuppressor.java +++ b/media/java/android/media/audiofx/NoiseSuppressor.java @@ -16,6 +16,8 @@ package android.media.audiofx; +import android.util.Log; + /** * Noise Suppressor (NS). * <p>Noise suppression (NS) is an audio pre-processing which removes background noise from the @@ -27,14 +29,13 @@ package android.media.audiofx; * <p>An application creates a NoiseSuppressor object to instantiate and control an NS * engine in the audio framework. * <p>To attach the NoiseSuppressor to a particular {@link android.media.AudioRecord}, - * specify the audio session ID of this AudioRecord when constructing the NoiseSuppressor. + * specify the audio session ID of this AudioRecord when creating the NoiseSuppressor. * The audio session is retrieved by calling * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance. * <p>On some devices, NS can be inserted by default in the capture path by the platform - * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can - * query which pre-processings are currently applied to an AudioRecord instance by calling - * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the - * AudioRecord. + * according to the {@link android.media.MediaRecorder.AudioSource} used. The application should + * call NoiseSuppressor.getEnable() after creating the NS to check the default NS activation + * state on a particular AudioRecord session. * <p>See {@link android.media.audiofx.AudioEffect} class for more details on * controlling audio effects. * @hide @@ -45,13 +46,44 @@ public class NoiseSuppressor extends AudioEffect { private final static String TAG = "NoiseSuppressor"; /** + * Checks if the device implements noise suppression. + * @return true if the device implements noise suppression, false otherwise. + */ + public static boolean isAvailable() { + return AudioEffect.isEffectTypeAvailable(AudioEffect.EFFECT_TYPE_NS); + } + + /** + * Creates a NoiseSuppressor and attaches it to the AudioRecord on the audio + * session specified. + * @param audioSession system wide unique audio session identifier. The NoiseSuppressor + * will be applied to the AudioRecord with the same audio session. + * @return NoiseSuppressor created or null if the device does not implement noise + * suppression. + */ + public static NoiseSuppressor create(int audioSession) { + NoiseSuppressor ns = null; + try { + ns = new NoiseSuppressor(audioSession); + } catch (IllegalArgumentException e) { + Log.w(TAG, "not implemented on this device "+ns); + } catch (UnsupportedOperationException e) { + Log.w(TAG, "not enough resources"); + } catch (RuntimeException e) { + Log.w(TAG, "not enough memory"); + } finally { + return ns; + } + } + + /** * Class constructor. - * <p> The application must catch exceptions when creating an NoiseSuppressor as the - * constructor is not guarantied to succeed: + * <p> The constructor is not guarantied to succeed and throws the following exceptions: * <ul> * <li>IllegalArgumentException is thrown if the device does not implement an NS</li> * <li>UnsupportedOperationException is thrown is the resources allocated to audio * pre-procesing are currently exceeded.</li> + * <li>RuntimeException is thrown if a memory allocation error occurs.</li> * </ul> * * @param audioSession system wide unique audio session identifier. The NoiseSuppressor @@ -60,8 +92,9 @@ public class NoiseSuppressor extends AudioEffect { * @throws java.lang.IllegalArgumentException * @throws java.lang.UnsupportedOperationException * @throws java.lang.RuntimeException + * @hide */ - public NoiseSuppressor(int audioSession) + private NoiseSuppressor(int audioSession) throws IllegalArgumentException, UnsupportedOperationException, RuntimeException { super(EFFECT_TYPE_NS, EFFECT_TYPE_NULL, 0, audioSession); } diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java index 0d64b68cfdd4..1198a77936d7 100644 --- a/services/java/com/android/server/wm/WindowAnimator.java +++ b/services/java/com/android/server/wm/WindowAnimator.java @@ -471,9 +471,7 @@ public class WindowAnimator { Surface.closeTransaction(); } - if (mBulkUpdateParams != 0) { - mService.bulkSetParameters(mBulkUpdateParams); - } + mService.bulkSetParameters(mBulkUpdateParams); } WindowState mCurrentFocus; diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 00972fae48f1..86f4ca31ce45 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -6882,22 +6882,33 @@ public class WindowManagerService extends IWindowManager.Stub case BULK_UPDATE_PARAMETERS: { // Used to send multiple changes from the animation side to the layout side. synchronized (mWindowMap) { + boolean doRequest = false; // TODO(cmautner): As the number of bits grows, use masks of bit groups to // eliminate unnecessary tests. if ((msg.arg1 & LayoutFields.SET_UPDATE_ROTATION) != 0) { mInnerFields.mUpdateRotation = true; + doRequest = true; } if ((msg.arg1 & LayoutFields.SET_WALLPAPER_MAY_CHANGE) != 0) { mInnerFields.mWallpaperMayChange = true; + doRequest = true; } if ((msg.arg1 & LayoutFields.SET_FORCE_HIDING_CHANGED) != 0) { mInnerFields.mWallpaperForceHidingChanged = true; + doRequest = true; } if ((msg.arg1 & LayoutFields.CLEAR_ORIENTATION_CHANGE_COMPLETE) != 0) { mInnerFields.mOrientationChangeComplete = false; + } else { + mInnerFields.mOrientationChangeComplete = true; + if (mWindowsFreezingScreen) { + doRequest = true; + } } - requestTraversalLocked(); + if (doRequest) { + requestTraversalLocked(); + } } break; } @@ -8472,11 +8483,13 @@ public class WindowManagerService extends IWindowManager.Stub !mInnerFields.mUpdateRotation) { checkDrawnWindowsLocked(); } - mInnerFields.mOrientationChangeComplete = true; // Check to see if we are now in a state where the screen should // be enabled, because the window obscured flags have changed. enableScreenIfNeededLocked(); +// Slog.e(TAG, "performLayoutAndPlaceSurfacesLockedInner exit: mPendingLayoutChanges=" +// + Integer.toHexString(mPendingLayoutChanges) + " mLayoutNeeded=" + mLayoutNeeded +// + " animating=" + mAnimator.mAnimating); } void checkDrawnWindowsLocked() { @@ -9512,11 +9525,6 @@ public class WindowManagerService extends IWindowManager.Stub public void onHardKeyboardStatusChange(boolean available, boolean enabled); } - void notifyAnimationChangedLayout(final int pendingLayoutChanges) { - mPendingLayoutChanges |= pendingLayoutChanges; - requestTraversalLocked(); - } - void debugLayoutRepeats(final String msg, int pendingLayoutChanges) { if (mLayoutRepeatCount >= LAYOUT_REPEAT_THRESHOLD) { Slog.v(TAG, "Layouts looping: " + msg + ", mPendingLayoutChanges = 0x" + |