android gps驱动 可见/已连接卫星支持北斗

前提:GPS驱动已通,android4.0

其实不加这个也能定位,因为定位信息是模块结合gps和北斗的定位算好一起发上来的,加这个只是能让app能看到北斗的卫星信息(例如gps测试仪)

修改的部分为GSA 和 GSV

GSV -> 可见卫星

GSA -> 已连接卫星

方法是自己拍脑袋想的,测试好用,其他不保证


GSV存下GPGSV和BDGSV的信息后一起上传

else if ( !memcmp(tok.p, "GSV", 3) ) {
 
    Token  tok_noSatellites  = nmea_tokenizer_get(tzer, 3);
    int    noSatellites = str2int(tok_noSatellites.p, tok_noSatellites.end);
    //D("noSatellites=%d\n",noSatellites);
//  if (noSatellites > 0) {

    if( !memcmp(gp, "GP", 2) ) {
//	    D("GPGSV record");	
		if (noSatellites > 0) {
	        Token  tok_noSentences   = nmea_tokenizer_get(tzer, 1);
    		Token  tok_sentence      = nmea_tokenizer_get(tzer, 2);
    	 
    		int sentence = str2int(tok_sentence.p, tok_sentence.end);
    		int totalSentences = str2int(tok_noSentences.p, tok_noSentences.end);
    		int curr;
    		int i;
    		//D("sentence=%d,totalSentences=%d\n",sentence,totalSentences);
    		if (sentence == 1) {
    		    r->sv_status_changed = 0;
    		    save_gps_num_svs = 0;
    		    r->sv_status.num_svs = 0;
	    	}
    	 
    		curr = save_gps_num_svs;
    		i = 0;
    		while (i < 4 && save_gps_num_svs < noSatellites){
                Token  tok_prn = nmea_tokenizer_get(tzer, i * 4 + 4);
                Token  tok_elevation = nmea_tokenizer_get(tzer, i * 4 + 5);
                Token  tok_azimuth = nmea_tokenizer_get(tzer, i * 4 + 6);
                Token  tok_snr = nmea_tokenizer_get(tzer, i * 4 + 7);
    
                save_gps_sv[curr].prn = str2int(tok_prn.p, tok_prn.end);
                save_gps_sv[curr].elevation = str2float(tok_elevation.p, tok_elevation.end);
                save_gps_sv[curr].azimuth = str2float(tok_azimuth.p, tok_azimuth.end);
                save_gps_sv[curr].snr = str2float(tok_snr.p, tok_snr.end);
                //D("GPS:  num=%d,prn=%d:snr=%f  ",r->sv_status.num_svs,\
                                save_gps_sv[curr].prn,save_gps_sv[curr].snr); 
                save_gps_num_svs += 1;
        		r->sv_status.num_svs += 1;
                curr += 1;
                i += 1;   
            }
		}
    } else {
//	    D("BDGSV record");
//	    if (noSatellites > 0) {
	        Token  tok_noSentences   = nmea_tokenizer_get(tzer, 1);
		    Token  tok_sentence      = nmea_tokenizer_get(tzer, 2);
	 
		    int sentence = str2int(tok_sentence.p, tok_sentence.end);
		    int totalSentences = str2int(tok_noSentences.p, tok_noSentences.end);
		    int curr;
            int i;
		    //D("sentence=%d,totalSentences=%d\n",sentence,totalSentences);
		    if (sentence == 1) {
		        r->sv_status_changed = 0;
		        save_bd_num_svs = 0;
		    }
	 
		    curr = save_bd_num_svs;
			i = 0;
			while (i < 4 && save_bd_num_svs < noSatellites){
	            Token  tok_prn = nmea_tokenizer_get(tzer, i * 4 + 4);
        	    Token  tok_elevation = nmea_tokenizer_get(tzer, i * 4 + 5);
             	Token  tok_azimuth = nmea_tokenizer_get(tzer, i * 4 + 6);
	            Token  tok_snr = nmea_tokenizer_get(tzer, i * 4 + 7);
    
                save_bd_sv[curr].prn = str2int(tok_prn.p, tok_prn.end);
                save_bd_sv[curr].elevation = str2float(tok_elevation.p, tok_elevation.end);
                save_bd_sv[curr].azimuth = str2float(tok_azimuth.p, tok_azimuth.end);
	            save_bd_sv[curr].snr = str2float(tok_snr.p, tok_snr.end);
        	    D("BD:  num=%d,prn=%d:snr=%f  ",r->sv_status.num_svs,\
                                                save_bd_sv[curr].prn,save_bd_sv[curr].snr); 
			    //D("%d, %f, %f, %f  curr = %d, %d",save_bd_sv[curr].prn,\
                                                    save_bd_sv[curr].elevation,\
                                                    save_bd_sv[curr].azimuth,\
                                                    save_bd_sv[curr].snr,\
                                                    curr,\
                                                    save_bd_num_svs);
              	save_bd_num_svs += 1;
			    r->sv_status.num_svs +=1;
	            curr += 1;
	            i += 1;   
        	}
		    if (sentence == totalSentences) {
			    int nn=0;
			    int temp_prn;
			    for(i = 0; i < r->sv_status.num_svs ; i++){
			        if(i < save_gps_num_svs){
				        r->sv_status.sv_list[i].prn      	= save_gps_sv[i].prn;
					    r->sv_status.sv_list[i].elevation	= save_gps_sv[i].elevation;
					    r->sv_status.sv_list[i].azimuth	= save_gps_sv[i].azimuth;
					    r->sv_status.sv_list[i].snr		= save_gps_sv[i].snr;
//					    D("%d, %f, %f, %f ",save_gps_sv[i].prn,\
                                            save_gps_sv[i].elevation,\
                                            save_gps_sv[i].azimuth,\
                                            save_gps_sv[i].snr);
					} else {
					    nn = i - save_gps_num_svs;
					    r->sv_status.sv_list[i].prn		= save_bd_sv[nn].prn + 200;
					    r->sv_status.sv_list[i].elevation	= save_bd_sv[nn].elevation;
					    r->sv_status.sv_list[i].azimuth	= save_bd_sv[nn].azimuth;
					    r->sv_status.sv_list[i].snr		= save_bd_sv[nn].snr;
//					    D("%d, %f, %f, %f     %d",save_bd_sv[nn].prn,\
                                                  save_bd_sv[nn].elevation,\
                                                  save_bd_sv[nn].azimuth,\
                                                  save_bd_sv[nn].snr,\
                                                  (i-save_gps_num_svs));
					}					
				}
				r->sv_status_changed = 1;
			}
//		}
    }


GSA取什么传什么

}else if ( !memcmp(tok.p, "GSA", 3) ) {
    // do something ?
    //D(">>>>>>>> GSA string");
    Token  tok_fixStatus   = nmea_tokenizer_get(tzer, 2);
    int i;

	if( !memcmp(gp, "GP", 2) ) {
        r->sv_status.used_in_fix_mask = 0ul;
        if (tok_fixStatus.p[0] != '\0' && tok_fixStatus.p[0] != '1') {
			Token  tok_accuracy      = nmea_tokenizer_get(tzer, 15);
			nmea_reader_update_accuracy(r, tok_accuracy);
			for (i = 3; i <= 14; ++i){
				Token  tok_prn  = nmea_tokenizer_get(tzer, i);
      			r->sv_status.used_in_fix_mask |= (1ul << (str2int(tok_prn.p, tok_prn.end)-1));
			}
			r->sv_status_changed = 1;
		}
    }
	else {
		r->sv_status.used_in_fix_bd = 0ul;
		if (tok_fixStatus.p[0] != '\0' && tok_fixStatus.p[0] != '1') {
			Token  tok_accuracy      = nmea_tokenizer_get(tzer, 15);
			nmea_reader_update_accuracy(r, tok_accuracy);
			for (i = 3; i <= 14; ++i){
				Token  tok_prn  = nmea_tokenizer_get(tzer, i);
      			r->sv_status.used_in_fix_bd |= (1ul <<(str2int(tok_prn.p, tok_prn.end)-1));
			}
			r->sv_status_changed = 1;
		}

       LOGD("used_in_fix_mask : %x",r->sv_status.used_in_fix_mask); 
       LOGD("used_in_fix_mask : %x",r->sv_status.used_in_fix_bd);
    }
}



GSV传的时候没什么问题,为了和GPS卫星区分,prn卫星编号加上200的偏移就可以了

但是GSA中已连接卫星是用used_in_fix_mask表示的,它的定义在hardware/libhardware/include/hardware/gps.h中

typedef struct {
    /** set to sizeof(GpsSvStatus) */
    size_t          size;
    
    /** Number of SVs currently visible. */
    int         num_svs;

    /** Contains an array of SV information. */
    GpsSvInfo   sv_list[GPS_MAX_SVS];

    /** Represents a bit mask indicating which SVs
     * have ephemeris data.
     */
    uint32_t    ephemeris_mask;

    /** Represents a bit mask indicating which SVs
     * have almanac data.
     */
    uint32_t    almanac_mask;

    /** 
     * Represents a bit mask indicating which SVs
     * were used for computing the most recent position fix.
     */     
    uint32_t    used_in_fix_mask;
    
    uint32_t    used_in_fix_bd; // for gps+bd
    
} GpsSvStatus;

32位对应32颗卫星,每一位变成1即表示该卫星已连接

如果想要北斗,需要为北斗加一个 uint32_t used_in_fix_bd;

下一步修改jni   frameworks/base/services/jni/com_android_server_location_GpsLocationProvider.cpp

找到used_in_fix_mask并加一行

    mask[0] = sGpsSvStatus.ephemeris_mask;
    mask[1] = sGpsSvStatus.almanac_mask;
    mask[2] = sGpsSvStatus.used_in_fix_mask;
    mask[3] = sGpsSvStatus.used_in_fix_bd;
这个android_location_GpsLocationProvider_read_sv_status 在java中由  native_read_sv_status 调用

调用native_read_sv_status在  frameworks/base/services/java/com/android/server/location/GpsLocationProvider.java 的reportSvStatus()中

int svCount = native_read_sv_status(mSvs, mSnrs, mSvElevations, mSvAzimuths, mSvMasks);
当然上边加了mask[3],mSvMasks的定义也得加

private int mSvMasks[] = new int[4];
reportSvStatus() 还有两个地方需要修改

1. onSvStatusChanged的参数需要加上北斗的mSvMasks[USED_FOR_FIX_BD]

                try {
                    listener.mListener.onSvStatusChanged(svCount, mSvs, mSnrs,
                            mSvElevations, mSvAzimuths, mSvMasks[EPHEMERIS_MASK],
                            mSvMasks[ALMANAC_MASK], mSvMasks[USED_FOR_FIX_MASK], mSvMasks[USED_FOR_FIX_BD]);
                } catch (RemoteException e) {
                    Log.w(TAG, "RemoteException in reportSvInfo");
                    mListeners.remove(listener);
                    // adjust for size of list changing
                    size--;
                }

2.

        // return number of sets used in fix instead of total
        updateStatus(mStatus, Integer.bitCount(mSvMasks[USED_FOR_FIX_MASK]) + Integer.bitCount(mSvMasks[USED_FOR_FIX_BD]));


onSvStatusChanged加了参数,需要修改定义

定义在frameworks/base/location/java/android/location/LocationManager.java 

        public void onSvStatusChanged(int svCount, int[] prns, float[] snrs,
                float[] elevations, float[] azimuths, int ephemerisMask,
                int almanacMask, int usedInFixMask, int usedInFixBd) {
            if (mListener != null) {
                mGpsStatus.setStatus(svCount, prns, snrs, elevations, azimuths,
                        ephemerisMask, almanacMask, usedInFixMask, usedInFixBd);

                Message msg = Message.obtain();
                msg.what = GpsStatus.GPS_EVENT_SATELLITE_STATUS;
                // remove any SV status messages already in the queue
                mGpsHandler.removeMessages(GpsStatus.GPS_EVENT_SATELLITE_STATUS);
                mGpsHandler.sendMessage(msg);
            }
        }
加上 int usedInFixBd,继续修改setStatus定义

frameworks/base/location/java/android/location/GpsStatus.java

加上针对北斗的判断

    synchronized void setStatus(int svCount, int[] prns, float[] snrs,
            float[] elevations, float[] azimuths, int ephemerisMask,
            int almanacMask, int usedInFixMask, int usedInFixBd) {
        int i;

        for (i = 0; i < mSatellites.length; i++) {
            mSatellites[i].mValid = false;
        }
        
        for (i = 0; i < svCount; i++) {
            int prn = prns[i] - 1;
            int prnShift = (prn >= 200 ? 1 << (prn - 200) : (1 << prn));
            if (prn >= 0 && prn < mSatellites.length) {
                GpsSatellite satellite = mSatellites[prn];
    
                satellite.mValid = true;
                satellite.mSnr = snrs[i];
                satellite.mElevation = elevations[i];
                satellite.mAzimuth = azimuths[i];
                satellite.mHasEphemeris = ((ephemerisMask & prnShift) != 0);
                satellite.mHasAlmanac = ((almanacMask & prnShift) != 0);
                if(prn >= 200){
                satellite.mUsedInFix = ((usedInFixBd & prnShift) != 0);
                }else{
                satellite.mUsedInFix = ((usedInFixMask & prnShift) != 0);
                }
            }
        }
    }

这时编译会提示错误,还需要修改aidl,frameworks/base/location/java/android/location/IGpsStatusListener.aidl

oneway interface IGpsStatusListener
{
    void onGpsStarted();
    void onGpsStopped();
    void onFirstFix(int ttff);
    void onSvStatusChanged(int svCount, in int[] prns, in float[] snrs,
            in float[] elevations, in float[] azimuths,
            int ephemerisMask, int almanacMask, int usedInFixMask, int usedInFixBd);
    void onNmeaReceived(long timestamp, String nmea);
}


-------------android 5.1 ------------------------------------------------------------------------------------------

frameworks/base/services/core/java/com/android/server/location/GpsStatusListenerHelper.java 下修改

    public void onSvStatusChanged(
            final int svCount,
            final int[] prns,
            final float[] snrs,
            final float[] elevations,
            final float[] azimuths,
            final int ephemerisMask,
            final int almanacMask,
            final int usedInFixMask,
            final int usedInFixBd
            ) {
        Operation operation = new Operation() {
            @Override
            public void execute(IGpsStatusListener listener) throws RemoteException {
                listener.onSvStatusChanged(
                        svCount,
                        prns,
                        snrs,
                        elevations,
                        azimuths,
                        ephemerisMask,
                        almanacMask,
                        usedInFixMask,
                        usedInFixBd);
            }
        };


你可能感兴趣的:(android,gps,北斗驱动)