am 6ee3fe88: Merge "Migrate ringtone playback to SystemUI." into jb-dev

* commit '6ee3fe884987d9d9915a8fce3d149719a35e9acb':
  Migrate ringtone playback to SystemUI.
This commit is contained in:
Jeff Sharkey
2012-04-27 16:29:55 -07:00
committed by Android Git Automerger
14 changed files with 393 additions and 131 deletions

View File

@@ -198,6 +198,7 @@ LOCAL_SRC_FILES += \
media/java/android/media/IMediaScannerService.aidl \
media/java/android/media/IRemoteControlClient.aidl \
media/java/android/media/IRemoteControlDisplay.aidl \
media/java/android/media/IRingtonePlayer.aidl \
telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
telephony/java/com/android/internal/telephony/ITelephony.aidl \

View File

@@ -21,6 +21,7 @@ import com.android.internal.R;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -213,7 +214,7 @@ public class Notification implements Parcelable
/**
* Use this constant as the value for audioStreamType to request that
* the default stream type for notifications be used. Currently the
* default stream type is STREAM_RING.
* default stream type is {@link AudioManager#STREAM_NOTIFICATION}.
*/
public static final int STREAM_DEFAULT = -1;

View File

@@ -628,6 +628,11 @@
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signature" />
<!-- Allows registration for remote audio playback. @hide -->
<permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK"
android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
android:protectionLevel="signature" />
<!-- =========================================== -->
<!-- Permissions associated with telephony state -->
<!-- =========================================== -->

View File

@@ -2306,4 +2306,12 @@ public class AudioManager {
}
}
/** {@hide} */
public IRingtonePlayer getRingtonePlayer() {
try {
return getService().getRingtonePlayer();
} catch (RemoteException e) {
return null;
}
}
}

View File

@@ -16,6 +16,7 @@
package android.media;
import static android.Manifest.permission.REMOTE_AUDIO_PLAYBACK;
import static android.media.AudioManager.RINGER_MODE_NORMAL;
import static android.media.AudioManager.RINGER_MODE_SILENT;
import static android.media.AudioManager.RINGER_MODE_VIBRATE;
@@ -360,7 +361,6 @@ public class AudioService extends IAudioService.Stub {
private int mPrevVolDirection = AudioManager.ADJUST_SAME;
// Keyguard manager proxy
private KeyguardManager mKeyguardManager;
// mVolumeControlStream is set by VolumePanel to temporarily force the stream type which volume
// is controlled by Vol keys.
private int mVolumeControlStream = -1;
@@ -369,6 +369,8 @@ public class AudioService extends IAudioService.Stub {
// server process so in theory it is not necessary to monitor the client death.
// However it is good to be ready for future evolutions.
private ForceControlStreamClient mForceControlStreamClient = null;
// Used to play ringtones outside system_server
private volatile IRingtonePlayer mRingtonePlayer;
///////////////////////////////////////////////////////////////////////////
// Construction
@@ -4230,6 +4232,17 @@ public class AudioService extends IAudioService.Stub {
}
}
@Override
public void setRingtonePlayer(IRingtonePlayer player) {
mContext.enforceCallingOrSelfPermission(REMOTE_AUDIO_PLAYBACK, null);
mRingtonePlayer = player;
}
@Override
public IRingtonePlayer getRingtonePlayer() {
return mRingtonePlayer;
}
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG);
@@ -4238,6 +4251,4 @@ public class AudioService extends IAudioService.Stub {
dumpFocusStack(pw);
dumpRCStack(pw);
}
}

View File

@@ -21,6 +21,8 @@ import android.content.ComponentName;
import android.media.IAudioFocusDispatcher;
import android.media.IRemoteControlClient;
import android.media.IRemoteControlDisplay;
import android.media.IRingtonePlayer;
import android.net.Uri;
/**
* {@hide}
@@ -113,10 +115,11 @@ interface IAudioService {
oneway void remoteControlDisplayUsesBitmapSize(in IRemoteControlDisplay rcd, int w, int h);
void startBluetoothSco(IBinder cb);
void stopBluetoothSco(IBinder cb);
void forceVolumeControlStream(int streamType, IBinder cb);
void setRingtonePlayer(IRingtonePlayer player);
IRingtonePlayer getRingtonePlayer();
int getMasterStreamType();
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2012 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 android.media;
import android.net.Uri;
/**
* @hide
*/
interface IRingtonePlayer {
/** Used for Ringtone.java playback */
void play(IBinder token, in Uri uri, int streamType);
void stop(IBinder token);
boolean isPlaying(IBinder token);
/** Used for Notification sound playback. */
void playAsync(in Uri uri, boolean looping, int streamType);
void stopAsync();
}

View File

@@ -18,17 +18,15 @@ package android.media;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Binder;
import android.os.RemoteException;
import android.provider.DrmStore;
import android.provider.MediaStore;
import android.provider.Settings;
import android.util.Log;
import java.io.FileDescriptor;
import java.io.IOException;
/**
@@ -41,7 +39,8 @@ import java.io.IOException;
* @see RingtoneManager
*/
public class Ringtone {
private static String TAG = "Ringtone";
private static final String TAG = "Ringtone";
private static final boolean LOGD = true;
private static final String[] MEDIA_COLUMNS = new String[] {
MediaStore.Audio.Media._ID,
@@ -55,21 +54,26 @@ public class Ringtone {
DrmStore.Audio.TITLE
};
private MediaPlayer mAudio;
private final Context mContext;
private final AudioManager mAudioManager;
private final boolean mAllowRemote;
private final IRingtonePlayer mRemotePlayer;
private final Binder mRemoteToken;
private MediaPlayer mLocalPlayer;
private Uri mUri;
private String mTitle;
private FileDescriptor mFileDescriptor;
private AssetFileDescriptor mAssetFileDescriptor;
private int mStreamType = AudioManager.STREAM_RING;
private AudioManager mAudioManager;
private Context mContext;
Ringtone(Context context) {
/** {@hide} */
public Ringtone(Context context, boolean allowRemote) {
mContext = context;
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
mAllowRemote = allowRemote;
mRemotePlayer = allowRemote ? mAudioManager.getRingtonePlayer() : null;
mRemoteToken = allowRemote ? new Binder() : null;
}
/**
@@ -79,18 +83,10 @@ public class Ringtone {
*/
public void setStreamType(int streamType) {
mStreamType = streamType;
if (mAudio != null) {
/*
* The stream type has to be set before the media player is
* prepared. Re-initialize it.
*/
try {
openMediaPlayer();
} catch (IOException e) {
Log.w(TAG, "Couldn't set the stream type", e);
}
}
// The stream type has to be set before the media player is prepared.
// Re-initialize it.
setUri(mUri);
}
/**
@@ -164,67 +160,75 @@ public class Ringtone {
return title;
}
private void openMediaPlayer() throws IOException {
if (mAudio != null) {
mAudio.release();
}
mAudio = new MediaPlayer();
if (mUri != null) {
mAudio.setDataSource(mContext, mUri);
} else if (mFileDescriptor != null) {
mAudio.setDataSource(mFileDescriptor);
} else if (mAssetFileDescriptor != null) {
// Note: using getDeclaredLength so that our behavior is the same
// as previous versions when the content provider is returning
// a full file.
if (mAssetFileDescriptor.getDeclaredLength() < 0) {
mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor());
} else {
mAudio.setDataSource(mAssetFileDescriptor.getFileDescriptor(),
mAssetFileDescriptor.getStartOffset(),
mAssetFileDescriptor.getDeclaredLength());
}
} else {
throw new IOException("No data source set.");
}
mAudio.setAudioStreamType(mStreamType);
mAudio.prepare();
}
void open(FileDescriptor fd) throws IOException {
mFileDescriptor = fd;
openMediaPlayer();
}
/**
* Set {@link Uri} to be used for ringtone playback. Attempts to open
* locally, otherwise will delegate playback to remote
* {@link IRingtonePlayer}.
*
* @hide
*/
public void setUri(Uri uri) {
destroyLocalPlayer();
void open(AssetFileDescriptor fd) throws IOException {
mAssetFileDescriptor = fd;
openMediaPlayer();
}
void open(Uri uri) throws IOException {
mUri = uri;
openMediaPlayer();
if (mUri == null) {
return;
}
// TODO: detect READ_EXTERNAL and specific content provider case, instead of relying on throwing
// try opening uri locally before delegating to remote player
mLocalPlayer = new MediaPlayer();
try {
mLocalPlayer.setDataSource(mContext, mUri);
mLocalPlayer.setAudioStreamType(mStreamType);
mLocalPlayer.prepare();
} catch (SecurityException e) {
destroyLocalPlayer();
if (!mAllowRemote) {
throw new IllegalStateException("Remote playback not allowed", e);
}
} catch (IOException e) {
destroyLocalPlayer();
if (!mAllowRemote) {
throw new IllegalStateException("Remote playback not allowed", e);
}
}
if (LOGD) {
if (mLocalPlayer != null) {
Log.d(TAG, "Successfully created local player");
} else {
Log.d(TAG, "Problem opening; delegating to remote player");
}
}
}
/** {@hide} */
public Uri getUri() {
return mUri;
}
/**
* Plays the ringtone.
*/
public void play() {
if (mAudio == null) {
try {
openMediaPlayer();
} catch (Exception ex) {
Log.e(TAG, "play() caught ", ex);
mAudio = null;
}
}
if (mAudio != null) {
// do not ringtones if stream volume is 0
if (mLocalPlayer != null) {
// do not play ringtones if stream volume is 0
// (typically because ringer mode is silent).
if (mAudioManager.getStreamVolume(mStreamType) != 0) {
mAudio.start();
mLocalPlayer.start();
}
} else if (mAllowRemote) {
try {
mRemotePlayer.play(mRemoteToken, mUri, mStreamType);
} catch (RemoteException e) {
Log.w(TAG, "Problem playing ringtone: " + e);
}
} else {
throw new IllegalStateException("Neither local nor remote playback available");
}
}
@@ -232,10 +236,22 @@ public class Ringtone {
* Stops a playing ringtone.
*/
public void stop() {
if (mAudio != null) {
mAudio.reset();
mAudio.release();
mAudio = null;
if (mLocalPlayer != null) {
destroyLocalPlayer();
} else if (mAllowRemote) {
try {
mRemotePlayer.stop(mRemoteToken);
} catch (RemoteException e) {
Log.w(TAG, "Problem stopping ringtone: " + e);
}
}
}
private void destroyLocalPlayer() {
if (mLocalPlayer != null) {
mLocalPlayer.reset();
mLocalPlayer.release();
mLocalPlayer = null;
}
}
@@ -245,7 +261,18 @@ public class Ringtone {
* @return True if playing, false otherwise.
*/
public boolean isPlaying() {
return mAudio != null && mAudio.isPlaying();
if (mLocalPlayer != null) {
return mLocalPlayer.isPlaying();
} else if (mAllowRemote) {
try {
return mRemotePlayer.isPlaying(mRemoteToken);
} catch (RemoteException e) {
Log.w(TAG, "Problem checking ringtone: " + e);
return false;
}
} else {
throw new IllegalStateException("Neither local nor remote playback available");
}
}
void setTitle(String title) {

View File

@@ -606,16 +606,15 @@ public class RingtoneManager {
* @see #getRingtone(Context, Uri)
*/
private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType) {
try {
Ringtone r = new Ringtone(context);
final Ringtone r = new Ringtone(context, true);
if (streamType >= 0) {
r.setStreamType(streamType);
}
r.open(ringtoneUri);
r.setUri(ringtoneUri);
return r;
} catch (Exception ex) {
Log.e(TAG, "Failed to open ringtone " + ringtoneUri);
Log.e(TAG, "Failed to open ringtone " + ringtoneUri + ": " + ex);
}
return null;

View File

@@ -5,6 +5,7 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INJECT_EVENTS" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
@@ -12,6 +13,7 @@
<uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
<uses-permission android:name="android.permission.STATUS_BAR" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<uses-permission android:name="android.permission.REMOTE_AUDIO_PLAYBACK" />
<!-- Networking and telephony -->
<uses-permission android:name="android.permission.BLUETOOTH" />

View File

@@ -41,6 +41,7 @@ public class SystemUIService extends Service {
final Object[] SERVICES = new Object[] {
0, // system bar or status bar, filled in below.
com.android.systemui.power.PowerUI.class,
com.android.systemui.media.RingtonePlayer.class,
};
/**

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.server;
package com.android.systemui.media;
import android.content.Context;
import android.media.AudioManager;
@@ -36,7 +36,7 @@ import java.util.LinkedList;
/**
* @hide
* This class is provides the same interface and functionality as android.media.AsyncPlayer
* with the following differences:
* with the following differences:
* - whenever audio is played, audio focus is requested,
* - whenever audio playback is stopped or the playback completed, audio focus is abandoned.
*/
@@ -338,4 +338,3 @@ public class NotificationPlayer implements OnCompletionListener {
}
}
}

View File

@@ -0,0 +1,164 @@
/*
* Copyright (C) 2012 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.systemui.media;
import android.content.Context;
import android.media.IAudioService;
import android.media.IRingtonePlayer;
import android.media.Ringtone;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Slog;
import com.android.systemui.SystemUI;
import com.google.android.collect.Maps;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;
/**
* Service that offers to play ringtones by {@link Uri}, since our process has
* {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}.
*/
public class RingtonePlayer extends SystemUI {
private static final String TAG = "RingtonePlayer";
private static final boolean LOGD = true;
// TODO: support Uri switching under same IBinder
private IAudioService mAudioService;
private final NotificationPlayer mAsyncPlayer = new NotificationPlayer(TAG);
private final HashMap<IBinder, Client> mClients = Maps.newHashMap();
@Override
public void start() {
mAsyncPlayer.setUsesWakeLock(mContext);
mAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE));
try {
mAudioService.setRingtonePlayer(mCallback);
} catch (RemoteException e) {
Slog.e(TAG, "Problem registering RingtonePlayer: " + e);
}
}
/**
* Represents an active remote {@link Ringtone} client.
*/
private class Client implements IBinder.DeathRecipient {
private final IBinder mToken;
private final Ringtone mRingtone;
public Client(IBinder token, Uri uri, int streamType) {
mToken = token;
mRingtone = new Ringtone(mContext, false);
mRingtone.setStreamType(streamType);
mRingtone.setUri(uri);
}
@Override
public void binderDied() {
if (LOGD) Slog.d(TAG, "binderDied() token=" + mToken);
synchronized (mClients) {
mClients.remove(mToken);
}
mRingtone.stop();
}
}
private IRingtonePlayer mCallback = new IRingtonePlayer.Stub() {
@Override
public void play(IBinder token, Uri uri, int streamType) throws RemoteException {
if (LOGD) Slog.d(TAG, "play(token=" + token + ", uri=" + uri + ")");
Client client;
synchronized (mClients) {
client = mClients.get(token);
if (client == null) {
client = new Client(token, uri, streamType);
token.linkToDeath(client, 0);
mClients.put(token, client);
}
}
client.mRingtone.play();
}
@Override
public void stop(IBinder token) {
if (LOGD) Slog.d(TAG, "stop(token=" + token + ")");
Client client;
synchronized (mClients) {
client = mClients.remove(token);
}
if (client != null) {
client.mToken.unlinkToDeath(client, 0);
client.mRingtone.stop();
}
}
@Override
public boolean isPlaying(IBinder token) {
if (LOGD) Slog.d(TAG, "isPlaying(token=" + token + ")");
Client client;
synchronized (mClients) {
client = mClients.get(token);
}
if (client != null) {
return client.mRingtone.isPlaying();
} else {
return false;
}
}
@Override
public void playAsync(Uri uri, boolean looping, int streamType) {
if (LOGD) Slog.d(TAG, "playAsync(uri=" + uri + ")");
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Async playback only available from system UID.");
}
mAsyncPlayer.play(mContext, uri, looping, streamType);
}
@Override
public void stopAsync() {
if (LOGD) Slog.d(TAG, "stopAsync()");
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
throw new SecurityException("Async playback only available from system UID.");
}
mAsyncPlayer.stop();
}
};
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("Clients:");
synchronized (mClients) {
for (Client client : mClients.values()) {
pw.print(" mToken=");
pw.print(client.mToken);
pw.print(" mUri=");
pw.println(client.mRingtone.getUri());
}
}
}
}

View File

@@ -16,16 +16,15 @@
package com.android.server;
import com.android.internal.os.AtomicFile;
import com.android.internal.statusbar.StatusBarNotification;
import com.android.internal.util.FastXmlSerializer;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.app.INotificationManager;
import android.app.ITransientNotification;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
@@ -39,8 +38,8 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.media.AudioManager;
import android.net.NetworkPolicy;
import android.net.NetworkTemplate;
import android.media.IAudioService;
import android.media.IRingtonePlayer;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
@@ -48,6 +47,7 @@ import android.os.IBinder;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserId;
import android.os.Vibrator;
import android.provider.Settings;
@@ -61,6 +61,14 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
import com.android.internal.os.AtomicFile;
import com.android.internal.statusbar.StatusBarNotification;
import com.android.internal.util.FastXmlSerializer;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -74,18 +82,6 @@ import java.util.HashSet;
import libcore.io.IoUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeBooleanAttribute;
import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeIntAttribute;
import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeLongAttribute;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
/** {@hide} */
public class NotificationManagerService extends INotificationManager.Stub
@@ -126,12 +122,13 @@ public class NotificationManagerService extends INotificationManager.Stub
private int mDefaultNotificationLedOn;
private int mDefaultNotificationLedOff;
private NotificationRecord mSoundNotification;
private NotificationPlayer mSound;
private boolean mSystemReady;
private int mDisabledNotifications;
private NotificationRecord mSoundNotification;
private NotificationRecord mVibrateNotification;
private IAudioService mAudioService;
private Vibrator mVibrator;
// for enabling and disabling notification pulse behavior
@@ -409,17 +406,19 @@ public class NotificationManagerService extends INotificationManager.Stub
// cancel whatever's going on
long identity = Binder.clearCallingIdentity();
try {
mSound.stop();
}
finally {
final IRingtonePlayer player = mAudioService.getRingtonePlayer();
if (player != null) {
player.stopAsync();
}
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(identity);
}
identity = Binder.clearCallingIdentity();
try {
mVibrator.cancel();
}
finally {
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@@ -445,11 +444,15 @@ public class NotificationManagerService extends INotificationManager.Stub
synchronized (mNotificationList) {
// sound
mSoundNotification = null;
long identity = Binder.clearCallingIdentity();
try {
mSound.stop();
}
finally {
final IRingtonePlayer player = mAudioService.getRingtonePlayer();
if (player != null) {
player.stopAsync();
}
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -458,8 +461,7 @@ public class NotificationManagerService extends INotificationManager.Stub
identity = Binder.clearCallingIdentity();
try {
mVibrator.cancel();
}
finally {
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -570,8 +572,6 @@ public class NotificationManagerService extends INotificationManager.Stub
mContext = context;
mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
mAm = ActivityManagerNative.getDefault();
mSound = new NotificationPlayer(TAG);
mSound.setUsesWakeLock(context);
mToastQueue = new ArrayList<ToastRecord>();
mHandler = new WorkerHandler();
@@ -622,6 +622,9 @@ public class NotificationManagerService extends INotificationManager.Stub
}
void systemReady() {
mAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE));
// no beeping until we're basically done booting
mSystemReady = true;
}
@@ -1026,11 +1029,14 @@ public class NotificationManagerService extends INotificationManager.Stub
// do not play notifications if stream volume is 0
// (typically because ringer mode is silent).
if (audioManager.getStreamVolume(audioStreamType) != 0) {
long identity = Binder.clearCallingIdentity();
final long identity = Binder.clearCallingIdentity();
try {
mSound.play(mContext, uri, looping, audioStreamType);
}
finally {
final IRingtonePlayer player = mAudioService.getRingtonePlayer();
if (player != null) {
player.playAsync(uri, looping, audioStreamType);
}
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@@ -1121,11 +1127,14 @@ public class NotificationManagerService extends INotificationManager.Stub
// sound
if (mSoundNotification == r) {
mSoundNotification = null;
long identity = Binder.clearCallingIdentity();
final long identity = Binder.clearCallingIdentity();
try {
mSound.stop();
}
finally {
final IRingtonePlayer player = mAudioService.getRingtonePlayer();
if (player != null) {
player.stopAsync();
}
} catch (RemoteException e) {
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@@ -1386,7 +1395,6 @@ public class NotificationManagerService extends INotificationManager.Stub
}
pw.println(" mSoundNotification=" + mSoundNotification);
pw.println(" mSound=" + mSound);
pw.println(" mVibrateNotification=" + mVibrateNotification);
pw.println(" mDisabledNotifications=0x" + Integer.toHexString(mDisabledNotifications));
pw.println(" mSystemReady=" + mSystemReady);