FileDocCategorySizeDatePackage
Ringer.javaAPI DocAndroid 1.5 API11496Wed May 06 22:42:46 BST 2009com.android.phone

Ringer

public class Ringer extends Object
Ringer manager for the Phone app.

Fields Summary
private static final String
LOG_TAG
private static final boolean
DBG
private static final int
PLAY_RING_ONCE
private static final int
STOP_RING
private static final int
VIBRATE_LENGTH
private static final int
PAUSE_LENGTH
android.net.Uri
mCustomRingtoneUri
android.media.Ringtone
mRingtone
android.os.Vibrator
mVibrator
android.os.IHardwareService
mHardwareService
volatile boolean
mContinueVibrating
VibratorThread
mVibratorThread
android.content.Context
mContext
private Worker
mRingThread
private android.os.Handler
mRingHandler
private boolean
mRingPending
private long
mFirstRingEventTime
private long
mFirstRingStartTime
Constructors Summary
Ringer(com.android.internal.telephony.Phone phone)


      
        mContext = phone.getContext();
        mHardwareService = IHardwareService.Stub.asInterface(ServiceManager.getService("hardware"));
    
Methods Summary
booleanisRinging()

return
true if we're playing a ringtone and/or vibrating to indicate that there's an incoming call. ("Ringing" here is used in the general sense. If you literally need to know if we're playing a ringtone or vibrating, use isRingtonePlaying() or isVibrating() instead.)
see
isVibrating
see
isRingtonePlaying

        synchronized (this) {
            return (isRingtonePlaying() || isVibrating());
        }
    
private booleanisRingtonePlaying()

return
true if the ringtone is playing
see
isVibrating
see
isRinging

        synchronized (this) {
            return (mRingtone != null && mRingtone.isPlaying()) ||
                    (mRingHandler != null && mRingHandler.hasMessages(PLAY_RING_ONCE));
        }
    
private booleanisVibrating()

return
true if we're vibrating in response to an incoming call
see
isVibrating
see
isRinging

        synchronized (this) {
            return (mVibratorThread != null);
        }
    
private static voidlog(java.lang.String msg)

        Log.d(LOG_TAG, msg);
    
private voidmakeLooper()

        if (mRingThread == null) {
            mRingThread = new Worker("ringer");
            mRingHandler = new Handler(mRingThread.getLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    Ringtone r = null;
                    switch (msg.what) {
                        case PLAY_RING_ONCE:
                            if (DBG) log("mRingHandler: PLAY_RING_ONCE...");
                            if (mRingtone == null && !hasMessages(STOP_RING)) {
                                // create the ringtone with the uri
                                if (DBG) log("creating ringtone: " + mCustomRingtoneUri);
                                r = RingtoneManager.getRingtone(mContext, mCustomRingtoneUri);
                                synchronized (Ringer.this) {
                                    if (!hasMessages(STOP_RING)) {
                                        mRingtone = r;
                                    }
                                }
                            }
                            r = mRingtone;
                            if (r != null && !hasMessages(STOP_RING)) {
                                PhoneUtils.setAudioMode(mContext, AudioManager.MODE_RINGTONE);
                                r.play();
                                synchronized (Ringer.this) {
                                    mRingPending = false;
                                    if (mFirstRingStartTime < 0) {
                                        mFirstRingStartTime = SystemClock.elapsedRealtime();
                                    }
                                }
                            }
                            break;
                        case STOP_RING:
                            if (DBG) log("mRingHandler: STOP_RING...");
                            r = (Ringtone) msg.obj;
                            if (r != null) {
                                r.stop();
                            } else {
                                if (DBG) log("- STOP_RING with null ringtone!  msg = " + msg);
                            }
                            getLooper().quit();
                            break;
                    }
                }
            };
        }
    
voidring()
Starts the ringtone and/or vibrator

        if (DBG) log("ring()...");

        synchronized (this) {
            try {
                mHardwareService.setAttentionLight(true);
            } catch (RemoteException ex) {
                // the other end of this binder call is in the system process.
            }

            if (shouldVibrate() && mVibratorThread == null) {
                mContinueVibrating = true;
                mVibratorThread = new VibratorThread();
                if (DBG) log("- starting vibrator...");
                mVibratorThread.start();
            }
            AudioManager audioManager =
                    (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

            if (audioManager.getStreamVolume(AudioManager.STREAM_RING) == 0) {
                if (DBG) log("skipping ring because volume is zero");
                return;
            }

            if (!isRingtonePlaying() && !mRingPending) {
                makeLooper();
                mRingHandler.removeCallbacksAndMessages(null);
                mRingPending = true;
                if (mFirstRingEventTime < 0) {
                    mFirstRingEventTime = SystemClock.elapsedRealtime();
                    mRingHandler.sendEmptyMessage(PLAY_RING_ONCE);
                } else {
                    // For repeat rings, figure out by how much to delay
                    // the ring so that it happens the correct amount of
                    // time after the previous ring
                    if (mFirstRingStartTime > 0) {
                        // Delay subsequent rings by the delta between event
                        // and play time of the first ring
                        if (DBG) {
                            log("delaying ring by " + (mFirstRingStartTime - mFirstRingEventTime));
                        }
                        mRingHandler.sendEmptyMessageDelayed(PLAY_RING_ONCE,
                                mFirstRingStartTime - mFirstRingEventTime);
                    } else {
                        // We've gotten two ring events so far, but the ring
                        // still hasn't started. Reset the event time to the
                        // time of this event to maintain correct spacing.
                        mFirstRingEventTime = SystemClock.elapsedRealtime();
                    }
                }
            } else {
                if (DBG) log("skipping ring, already playing or pending: "
                             + mRingtone + "/" + mRingHandler);
            }
        }
    
voidsetCustomRingtoneUri(android.net.Uri uri)
Sets the ringtone uri in preparation for ringtone creation in makeLooper(). This uri is defaulted to the phone-wide default ringtone.

        if (uri != null) {
            mCustomRingtoneUri = uri;
        }
    
booleanshouldVibrate()

        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
        return audioManager.shouldVibrate(AudioManager.VIBRATE_TYPE_RINGER);
    
voidstopRing()
Stops the ringtone and/or vibrator if any of these are actually ringing/vibrating.

        synchronized (this) {
            if (DBG) log("stopRing()...");

            try {
                mHardwareService.setAttentionLight(false);
            } catch (RemoteException ex) {
                // the other end of this binder call is in the system process.
            }

            if (mRingHandler != null) {
                mRingHandler.removeCallbacksAndMessages(null);
                Message msg = mRingHandler.obtainMessage(STOP_RING);
                msg.obj = mRingtone;
                mRingHandler.sendMessage(msg);
                PhoneUtils.setAudioMode(mContext, AudioManager.MODE_NORMAL);
                mRingThread = null;
                mRingHandler = null;
                mRingtone = null;
                mFirstRingEventTime = -1;
                mFirstRingStartTime = -1;
                mRingPending = false;
            } else {
                if (DBG) log("- stopRing: null mRingHandler!");
            }

            if (mVibratorThread != null) {
                if (DBG) log("- stopRing: cleaning up vibrator thread...");
                mContinueVibrating = false;
                mVibratorThread = null;
            }
            // Also immediately cancel any vibration in progress.
            mVibrator.cancel();
        }