FM上层学习记录

来源:互联网 发布:海思3536 数据手册 编辑:程序博客网 时间:2024/04/30 04:24


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);   ------------------10.1----------------  此处模糊,根据api 此时prefs应该应该时没有数据,所以猜返回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;
        }


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


public boolean routeAudio(int device) {              -----------------------13.2----------------------
            return mService.get().routeAudio(device);
        }
    }
    
    
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();  ------------10.1-----mIsSpeaker=false------------
                    mService.routeAudio(mIsSpeaker ? FMplayService.RADIO_AUDIO_DEVICE_SPEAKER                    -----------12--------------
                            : 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  =true                   
                    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) {     //NO_DIALOG
                                    closeAlertDialog(HEADSET_DIALOG);
                                }


                                if (mOver == true) {   //mOver = true;
                                    Log.d(LOGTAG, "showAlertDialog:STARTUP_DIALOG");
                                    showAlertDialog(STARTUP_DIALOG);   //mCurrentDialog = STARTUP_DIALOG
                                    mOpenThread = createOpenThread();   ------------------- 8
                                    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;
case MSG_PROGRESS:
                removeMessages(MSG_PROGRESS);
                if (!mOver) {  //mOver = false  ---------9.2
                    sendMessageDelayed(obtainMessage(MSG_PROGRESS), PROGRESS_DELAY);
                } else {
                    closeAlertDialog(STARTUP_DIALOG);            -------------9.4 
                    if (!SystemProperties.getBoolean("ro.device.support.antenna", false)) {
                        if (isHeadsetExists()) {
                            if (!mOpenResult) {   //mOpenResult=true
                                showAlertDialog(OPENERROR_DIALOG);
                            } else {           --------------------------9.5
                                Message message = mHandler.obtainMessage(MSG_ROUTE);
                                mHandler.sendMessage(message);


                                if (FMPlaySharedPreferences.getStationCount(0) <= 0) {
                                    Intent req = new Intent(FMPlay.this, StationSearch.class);
                                    startActivity(req);
                                } else {
                                    message = mHandler.obtainMessage(MSG_UPDATE);
                                    mHandler.sendMessage(message);
                                }
                                setUiPower(true, false);
                                setUiEnabled(true); // Users can do whatever
                                                    // they want once we are
                                                    // prepared.
                            }
                        } else {
                            Intent intent = new Intent(FMplayService.ACTION_SHUTDOWN);
                            sendBroadcast(intent);
                        }
                    }
                }
                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);
            }clmps
            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




FMPlayer.java
private Thread createOpenThread() {
        return new Thread(new Runnable() {
            public void run() {
                Log.d(LOGTAG, "tring open fm");
                mOver = false;
                mHandler.sendMessage(mHandler.obtainMessage(MSG_PROGRESS));              ------9.1
                mOpenResult = mService.fmOn();    //true
                Log.d(LOGTAG, "tring open fm result = " + mOpenResult);
                mOver = true;          -----------9.3
            }
       });
    }


protected void showAlertDialog(int id) {
        if(!FMPlay.this.isFinishing()){
            showDialog(id);
            mCurrentDialog = id;
        }
    }


private void showAudioDevice() {
        mHeadsetToggle.setChecked(!mIsSpeaker, false);     //mIsSpeaker=false  ----------------11.1-------------------
        if(mIsSpeaker){
        mHeadsetIndicator.setImageResource(R.drawable.headset_indicator_spk);
        }else {
        mHeadsetIndicator.setImageResource(R.drawable.headset_indicator);
        }
    }


PreferenceManager.java
public static SharedPreferences getDefaultSharedPreferences(Context context) {           ----------------------10.2---------------
        return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
                getDefaultSharedPreferencesMode());
    }


Context.java
public abstract SharedPreferences getSharedPreferences(String name,
            int mode);            ----------------10.3------------------ 没有找到实现这个函数的地方


PreferenceManager.java
public SharedPreferences getSharedPreferences() {
        if (mSharedPreferences == null) {
            mSharedPreferences = mContext.getSharedPreferences(mSharedPreferencesName,
                    mSharedPreferencesMode);
        }
        
        return mSharedPreferences;
    }




CheckableImageButton.java
  public void setChecked(boolean checked, boolean notifyToListener) {         // checked=true  notifyToListener=false -----------------11.2-------------------
        if (checked != mChecked) {
            boolean isAllowed = true;
            if (mListener != null && notifyToListener) {
                isAllowed = mListener.onCheckedChanged(this, checked);
            }
            if (isAllowed) {
                mChecked = checked;
                updateImageSource();
            }
        }
    }


RadioServiceStub.java
 public boolean routeAudio(int device) {      //FMplayService.RADIO_AUDIO_DEVICE_WIRED_HEADSET
        boolean value = false;
        try {
            value = mService.routeAudio(device);                 -------------------------13.1---------------------
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        return value;
    }


FMplayService.java
 public boolean routeAudio(int device) {                ----------------------13.3----------------------
        return routeAudio(device, true);
    }


public boolean routeAudio(int device, boolean audioFocus) {  //FMplayService.RADIO_AUDIO_DEVICE_WIRED_HEADSET , true


        if (audioFocus && device != RADIO_AUDIO_DEVICE_NONE && !requestAudioFocus()) {
            return false;
        }
        if (device == RADIO_AUDIO_DEVICE_SPEAKER || device == RADIO_AUDIO_DEVICE_WIRED_HEADSET) {
            mAudioDevice = device;
            mFmOn = true;//mFmOn should be set before setVolume().


            // add for bug158083 start
            if (device == RADIO_AUDIO_DEVICE_SPEAKER) {
                AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM, AudioSystem.DEVICE_STATE_UNAVAILABLE, "");
                AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_SPEAKER, AudioSystem.DEVICE_STATE_AVAILABLE, "");
            } else if (device == RADIO_AUDIO_DEVICE_WIRED_HEADSET) {                 ----------------13.4-----------------------
                AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_SPEAKER, AudioSystem.DEVICE_STATE_UNAVAILABLE, "");
                AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM, AudioSystem.DEVICE_STATE_AVAILABLE, "");
            }
            // add for bug158083 end




            setVolume();


            Log.d(LOGTAG, "route audio:" + device);
            Intent intent = new Intent(Intent.ACTION_FM);
            intent.putExtra("state", 1);
            intent.putExtra("speaker", device);
            sendBroadcast(intent);
        } else if (mFmOn ==true && device == RADIO_AUDIO_DEVICE_NONE){
            mFmOn = false;
            // add for bug158083 start
            AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM_SPEAKER,AudioSystem.DEVICE_STATE_UNAVAILABLE,"");
            AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM,AudioSystem.DEVICE_STATE_UNAVAILABLE,"");
            // add for bug158083 end


            Log.d(LOGTAG, "route audio:" + device);
            Intent intentaudio = new Intent(Intent.ACTION_FM);
            intentaudio.putExtra("FM", 0);
            intentaudio.putExtra("state", 0);
            sendBroadcast(intentaudio);
        } else {
            Log.e(LOGTAG, "ignore device: " + device);
        }
        return true;
    }