FM上層

來源:互聯網
上載者:User

FMPlay.java
public void onCreate(Bundle savedInstanceState) {
        Log.d(LOGTAG,"onCreate");
        super.onCreate(savedInstanceState);
//設定全螢幕模式
        setVolumeControlStream(AudioManager.STREAM_FM);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN
                , WindowManager.LayoutParams.FLAG_FULLSCREEN);

        setContentView(R.layout.radio);

//得到FM台列表
        mStationList = FMPlaySharedPreferences.getInstance(this);

        if (!getComponents()) {
            return;
        }

        setUiPower(false, true);

//new 一個Service的作用? 普通的類
        mService = new RadioServiceStub(this, this);   --------important4  

//設定FM儲存位置,SDcard首先
        m_recorder = new Recorder();
        m_recorder.setOnStateChangedListener(mOnStateChangedListener);
        registerExternalStorageListener();

        /* changed by qiaozw begin*/ //定義一個輕量級儲存perfs?
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        mIsSpeaker = prefs.getBoolean("mIsSpeaker", false);
        /* changed by qiaozw end */

        mReady = false;
        mOver = true;
        mOpenResult = true;
        mDialogs = new Dialog[DIALOG_COUNT];
        mCurrentDialog = NO_DIALOG;

        IntentFilter filter = new IntentFilter();
        filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        filter.addAction(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
        filter.addAction(Intent.ACTION_FM);
        filter.addAction(Intent.ACTION_HEADSET_PLUG);
        filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
        filter.addAction("android.intent.action.TIME_SET");
//註冊廣播
        registerReceiver(mReceiver, filter);

        //mm04 fix bug 2706
        tmgr = (TelephonyManager) getSystemService("phone");
        tmgr.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
    }

 protected void onStart() {
        Log.d(LOGTAG,"onStart");
        super.onStart();
//onCreate -> onStart
        if (!mService.bindToService()) {                   -----------------important6
            Log.d(LOGTAG, "fail to bindToService");
            mService = null;
            return;
        }
//判斷FM是否已經開啟
        if(mPowerChecked && !isFmOn()){         
            mHandler.sendMessage(mHandler.obtainMessage(MSG_OPEN));    --------important1
        }

        //mm04 fix bug 3183
        Intent i = new Intent("com.android.fm.stopmusicservice");
        i.putExtra("playingfm", true);
        this.sendBroadcast(i);
    }
    
    
    FMPlay.java
    private boolean isFmOn(){
        boolean value = false;
        try {
            value = mService.isFmOn();
        } catch (NullPointerException e){
            Log.d(LOGTAG,"mService NullPointerException");
            mService = new RadioServiceStub(this, this);
            if (!mService.bindToService()) {
                Log.d(LOGTAG, "resetMService fail to bindToService");
                mService = null;
                return true;
            }
            isFmOn();
            Log.d(LOGTAG,"mService ok");
        }  catch (Exception e) {
            // TODO Auto-generated catch block
            Log.d(LOGTAG,"mService Exception");
            e.printStackTrace();
            return true;
        }

        return value;
    }
    
    
    RadioServiceStub.java
     public boolean isFmOn() {
        boolean value = false;
        if (mService != null) {
            try {
                value = mService.isFmOn();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        return value;
    }
    
    
    IRadioService.aidl
    interface IRadioService
{
    -------------------
    boolean isFmOn();             
    -------------------
}

FMplayService.java
static class ServiceStub extends IRadioService.Stub{
        WeakReference<FMplayService> mService;

        public ServiceStub(FMplayService service) {
            mService = new WeakReference<FMplayService>(service);
        }

        public boolean fmOn() throws RemoteException {
            if(mService != null){
                if(mService.get() != null){
                    return mService.get().fmOn();
                }
            }
            return false;
        }

        -------------------------------------

        public boolean isFmOn() throws RemoteException {                 
            if(mService != null){
                if(mService.get() != null){
                    return mService.get().isFmOn();
                }
            }
            return false;
        }

----------------------------------------
    }
    
    
WeakReference<FMplayService> mService;

WeakReference.java
public class WeakReference<T> extends Reference<T> {}

Reference.java
    /**
     * Returns the referent of the reference object.
     *
     * @return the referent to which reference refers, or {@code null} if the
     *         object has been cleared.
     */
    public T get() {
        return referent;
    }

FMplayService.java
public boolean isFmOn() {
        Log.d(LOGTAG, "isFmOn" + mFmOn);
        return (mReceiver != null) && mFmOn;
    }
    

接-----------important1
frameworks\base\core\java\anrdoid\os\Handler.java
/**
     * Same as {@link #obtainMessage()}, except that it also sets the what member of the returned Message.
     * 
     * @param what Value to assign to the returned Message.what field.
     * @return A Message from the global message pool.
     */
    public final Message obtainMessage(int what)    //what = MSG_OPEN
    {
        return Message.obtain(this, what);
    }

 public final boolean sendMessage(Message msg)
    {
        return sendMessageDelayed(msg, 0);  //msg.what = MSG_OPEN
    }

frameworks\base\core\java\anrdoid\os\Message.java
public static Message obtain(Handler h, int what) {
        Message m = obtain();
        m.target = h;
        m.what = what;

        return m;
    }

FMPlay.java
private Handler mHandler = new Handler(){                   ------------------------important2  mHandler.sendMessage - > handleMessage
        public void handleMessage(Message msg) {
            Log.d(LOGTAG, "msg.what: " +msg.what+" mOver: "+mOver);
            switch(msg.what) {      //msg.what = MSG_OPEN
            case MSG_ROUTE:
                removeMessages(MSG_ROUTE);
                if (mReady) {
                    showAudioDevice();
                    mService.routeAudio(mIsSpeaker ? FMplayService.RADIO_AUDIO_DEVICE_SPEAKER
                            : FMplayService.RADIO_AUDIO_DEVICE_WIRED_HEADSET);
                } else {
                    Message message = mHandler.obtainMessage(MSG_ROUTE);
                    sendMessageDelayed(message, CHECK_DELAY);
                }
                break;
          ...........................................
            case MSG_OPEN:
                removeMessages(MSG_OPEN);
                if (!mReady) {   //mReady  =false                   
                    sendMessageDelayed(obtainMessage(MSG_OPEN), OPEN_DELAY);
                } else {            ----------------important7

                    if (!isFmOn()) {//fix bug 11354,11420
                        if (System.getInt(getContentResolver(), System.AIRPLANE_MODE_ON, 0) != 0) {
                            showAlertDialog(AIRPLANE_DIALOG);
                            return;
                        }

                        TelephonyManager pm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
                        if (pm.getCallState() == TelephonyManager.CALL_STATE_RINGING || pm.getCallState() == TelephonyManager.CALL_STATE_OFFHOOK) {
                            showAlertDialog(PHONE_DIALOG);
                            return;
                        }

                        if (!SystemProperties.getBoolean("ro.device.support.antenna", false)) {
                            if (isHeadsetExists()) {
                                if (mCurrentDialog == HEADSET_DIALOG) {
                                    closeAlertDialog(HEADSET_DIALOG);
                                }

                                if (mOver == true) {
                                    Log.d(LOGTAG, "showAlertDialog:STARTUP_DIALOG");
                                    showAlertDialog(STARTUP_DIALOG);
                                    mOpenThread = createOpenThread();
                                    Log.d(LOGTAG, " create thread when use ");
                                    mOpenThread.start();
                                }
                            } else {
                                if (mCurrentDialog != HEADSET_DIALOG) {
                                    if (mCurrentDialog != NO_DIALOG) {
                                        closeAlertDialog(mCurrentDialog);
                                    }
                                    showAlertDialog(HEADSET_DIALOG);
                                }
                                return;
                            }
                        }
                    } else {
                        setUiPower(true, false);
                    }
                }
                break;
           ...................................................
           
            default:
            }
        }
    };

frameworks\base\core\java\anrdoid\os\Handler.java
 public final boolean sendMessageDelayed(Message msg, long delayMillis)
    {
        if (delayMillis < 0) {
            delayMillis = 0;
        }
        return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
    }

public boolean sendMessageAtTime(Message msg, long uptimeMillis)   -----------------------important3
    {
        boolean sent = false;
        MessageQueue queue = mQueue;     
        if (queue != null) {
            msg.target = this;           ----------------走這邊
            sent = queue.enqueueMessage(msg, uptimeMillis);
        }
        else {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
        }
        return sent;
    }

public Handler() {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = null;
    }

frameworks\base\core\java\anrdoid\os\Looper.java
/**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    public static Looper myLooper() {
        return sThreadLocal.get();
    }
具體看Looper.java,
 public static void prepareMainLooper() {
        prepare();
        setMainLooper(myLooper());
        myLooper().mQueue.mQuitAllowed = false;
    }

 public static void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }
.............................
所以important3中queue != null

在onCeate()時important4 
mService = new RadioServiceStub(this, this);            ----------------------5
if (!mService.bindToService()) {                   -----------------6
public boolean bindToService() {
        mContext.startService(new Intent(mContext, FMplayService.class));
        mBinder = new BinderCallback(mCallback);
        return mContext.bindService((new Intent()).setClass(mContext, FMplayService.class), mBinder,
                Context.BIND_AUTO_CREATE);
    }

    private class BinderCallback implements ServiceConnection {
        private ServiceConnection mCallback;

        public void onServiceDisconnected(ComponentName name) {
            if (mCallback != null) {
                mCallback.onServiceDisconnected(name);
            }
            mService = null;
        }
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = IRadioService.Stub.asInterface(service);
            if (mCallback != null) {
                mCallback.onServiceConnected(name, service);             -------------------------????
            }
        }
        public BinderCallback(ServiceConnection callback) {
            mCallback = callback;
        }
    }

public RadioServiceStub(Context context, ServiceConnection callback) {
        mContext = context;
        mCallback = callback;           ---------------------important5迴歸 -> 5
        mService = null;
        mBinder = null;
    }

public void onServiceConnected(ComponentName name, IBinder service) {
        mReady = true;
        Log.d(LOGTAG, "mReady = true");
    }

所以此時mReady = true;

case MSG_OPEN:
    走 -> ----------------important7

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.