Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66eb4acb authored by Mike Lockwood's avatar Mike Lockwood Committed by The Android Open Source Project
Browse files

AI 144599: Location Manager cleanup:

  Move PhoneStateListener for listening to cell location changes from LocationManagerService
  to the NetworkLocationProvider.
  Move CellState class out of the core framework to the NetworkLocationProvider service.
  NetworkLocationManager now notifies the collector of its state, rather than LocationManagerService.
  BUG=1729031

Automated import of CL 144599
parent b9db7c9f
Loading
Loading
Loading
Loading
+0 −11
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package android.location;

import com.android.internal.location.CellState;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
@@ -239,15 +237,6 @@ public abstract class LocationProviderImpl extends LocationProvider {
    public void updateNetworkState(int state) {
    }

    /**
     * Updates the cell state for the given provider. This function must be
     * overwritten if {@link #requiresCell} returns true.
     *
     * @param state cell state
     */
    public void updateCellState(CellState state) {
    }

    /**
     * Implements addditional location provider specific additional commands.
     *
+0 −300
Original line number Diff line number Diff line
/*
 * Copyright (C) 2007 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.internal.location;

import android.telephony.CellLocation;
import android.telephony.TelephonyManager;
import android.telephony.NeighboringCellInfo;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;

import com.android.internal.telephony.TelephonyProperties;

import java.util.List;
import java.util.ArrayList;

import android.os.SystemProperties;

/**
 * Stores the cell tower state
 *
 * {@hide}
 */
public class CellState {
    
    public static String TAG = "CellState";

    public static int RADIO_TYPE_GPRS = 1;
    public static int RADIO_TYPE_CDMA = 2;
    public static int RADIO_TYPE_WCDMA = 3;

    private int mCid = -1;
    private int mLac = -1;
    private int mMcc = -1;
    private int mMnc = -1;
    private int mHomeMcc = -1;
    private int mHomeMnc = -1;
    private String mCarrier = null;
    private int mRadioType = -1;
    private long mTime = 0;
    private int mSignalStrength = -1;

    private List<NeighborCell> mNeighbors;

    public CellState() {
        // constructor for invalid cell location
    }

    public CellState(TelephonyManager telephonyManager, CellLocation location, int signalStrength) {
        if (location instanceof GsmCellLocation) {
            GsmCellLocation loc = (GsmCellLocation)location;
            mLac = loc.getLac(); // example: 6032
            mCid = loc.getCid(); // example: 31792
        }
        mTime = System.currentTimeMillis();

        // Get radio type
        int radioType = telephonyManager.getNetworkType();
        if (radioType == TelephonyManager.NETWORK_TYPE_GPRS ||
            radioType == TelephonyManager.NETWORK_TYPE_EDGE) {
            mRadioType = RADIO_TYPE_GPRS;
        } else if (radioType == TelephonyManager.NETWORK_TYPE_UMTS) {
            mRadioType = RADIO_TYPE_WCDMA;
        } else if (radioType == TelephonyManager.NETWORK_TYPE_CDMA ||
                radioType == TelephonyManager.NETWORK_TYPE_EVDO_0 ||
                radioType == TelephonyManager.NETWORK_TYPE_EVDO_A ||
                radioType == TelephonyManager.NETWORK_TYPE_1xRTT) {
            mRadioType = RADIO_TYPE_CDMA;
        }

        // Get neighboring cells
        mNeighbors = new ArrayList<NeighborCell>();
        List<NeighboringCellInfo> neighboringCells = telephonyManager.getNeighboringCellInfo();
        if (neighboringCells != null) {
            for (NeighboringCellInfo n : neighboringCells) {
                if (n.getCid() == NeighboringCellInfo.UNKNOWN_CID) {
                    continue;
                }

                if (mRadioType == RADIO_TYPE_WCDMA) {
                    mNeighbors.add(new NeighborCell(-1, -1, n.getCid(), n.getRssi()));
                } else if (mRadioType == RADIO_TYPE_GPRS) {
                    try {
                        String hexCidLac = Integer.toHexString(n.getCid());
                        int l = hexCidLac.length();
                        if (l > 8) {
                            Log.w(TAG, "Unable to parse 2G Cell \"" + hexCidLac + "\"");
                            continue;
                        }
                        if (l < 8) {
                            for (int i = 0; i < (8-l); i++) {
                                hexCidLac = "0" + hexCidLac;
                            }
                        }
                        int lac = Integer.valueOf(hexCidLac.substring(0, 4), 16);
                        int cid  = Integer.valueOf(hexCidLac.substring(4), 16);
                        mNeighbors.add(new NeighborCell(cid, lac, -1, n.getRssi()));

                    } catch (Exception e) {
                        Log.e(TAG, "Error parsing 2G Cell \"" + n.getCid() + "\"", e);
                    }
                }
            }
        }

        // Get MCC/MNC
        String operator = telephonyManager.getNetworkOperator();
        if (operator != null && !operator.equals("")) {
            // Use a try/catch block to detect index out of bounds or number format exceptions.
            // If an error occurs, both mMcc and mMnc will be equal to -1.
            try {
                String mcc = operator.substring(0, 3);
                String mnc = operator.substring(3);
                int mccTmp = Integer.parseInt(mcc);
                int mncTmp = Integer.parseInt(mnc);
                
                // Parsing succeeded, update the instance variables together
                mMcc = mccTmp;
                mMnc = mncTmp;
            } catch (Exception e) {
                Log.e(TAG, "Error parsing MCC/MNC from operator \"" + operator + "\"", e);
            }
        }

        // Get Home MCC/MNC
        String homeOperator = telephonyManager.getSimOperator();
        if (homeOperator != null && !homeOperator.equals("")) {
            // Use a try/catch block to detect index out of bounds or number format exceptions.
            // If an error occurs, both mHomeMcc and mHomeMnc will be equal to -1.
            try {
                String mcc = homeOperator.substring(0, 3);
                String mnc = homeOperator.substring(3);
                int mccTmp = Integer.parseInt(mcc);
                int mncTmp = Integer.parseInt(mnc);
                
                // Parsing succeeded, update the instance variables together
                mHomeMcc = mccTmp;
                mHomeMnc = mncTmp;
            } catch (Exception e) {
                Log.e(TAG, "Error parsing MCC/MNC from home operator \"" + homeOperator + "\"", e);
            }
        }

        // Get Carrier
        String carrier = telephonyManager.getNetworkOperatorName();
        if (carrier != null && !carrier.equals("")) {
            mCarrier = carrier;
        }

        // Initial signal strength
        mSignalStrength = signalStrength;

        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            String neighbors = "[";
            for (NeighborCell n : mNeighbors) {
                neighbors += n.toString() + ",";
            }
            neighbors += "]";
            Log.d(TAG, "CellState(): " + mLac +"," + mCid + "," + mMnc +"," + mMcc + "," +
                mHomeMcc + "," + mHomeMnc + "," + mCarrier + "," + mRadioType + "," +
                mSignalStrength + "," + neighbors);
        }
    }

    public void updateRadioType(int radioType) {
        mRadioType = radioType;

        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.d(TAG, "updateRadioType(): " + mLac +"," + mCid + "," + mMnc +"," + mMcc + "," +
                mHomeMcc + "," + mHomeMnc + "," + mCarrier + "," + mRadioType + "," +
                mSignalStrength);
        }
    }

    public void updateSignalStrength(int signalStrength) {
        mSignalStrength = signalStrength;

        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.d(TAG, "updateSignal(): " + mLac +"," + mCid + "," + mMnc +"," + mMcc + "," + 
                mHomeMcc + "," + mHomeMnc + "," + mCarrier + "," + mRadioType + "," +
                mSignalStrength);
        }
    }

    public int getCid() {
        return mCid;
    }

    public int getLac() {
        return mLac;
    }

    public int getMcc() {
        return mMcc;
    }

    public int getMnc() {
        return mMnc;
    }

    public int getHomeMcc() {
        return mHomeMcc;
    }

    public void setHomeMcc(int homeMcc) {
        this.mHomeMcc = homeMcc;
    }

    public int getHomeMnc() {
        return mHomeMnc;
    }

    public void setHomeMnc(int homeMnc) {
        this.mHomeMnc = homeMnc;
    }

    public String getCarrier() {
        return mCarrier;
    }

    public void setCarrier(String carrier) {
        this.mCarrier = carrier;
    }

    public int getRadioType() {
        return mRadioType;
    }

    public long getTime() {
        return mTime;
    }

    public int getSignalStrength() {
        return mSignalStrength;
    }

    public List<NeighborCell> getNeighbors() {
        return mNeighbors;
    }

    public boolean equals(CellState other) {
        return (mCid == other.mCid && mLac == other.mLac);
    }

    public boolean isValid() {
        return (mCid != -1 && mLac != -1);
    }

    public static class NeighborCell {
        private int mCid = -1;
        private int mLac = -1;
        private int mPsc = -1;
        private int mRssi = -1;

        NeighborCell(int cid, int lac, int psc, int rssi) {
            mCid = cid;
            mLac = lac;
            mPsc = psc;
            mRssi = rssi;
        }

        public int getCid() {
            return mCid;
        }

        public int getLac() {
            return mLac;
        }

        public int getPsc() {
            return mPsc;
        }

        public int getRssi() {
            return mRssi;
        }

        public String toString() {
            if (mPsc != -1) {
                return String.valueOf(mPsc) + "@" + mRssi;
            } else {
                return mCid + ":" + mLac + "@" + mRssi;
            }
        }
    }
}
+0 −18
Original line number Diff line number Diff line
@@ -19,8 +19,6 @@ package com.android.internal.location;
import android.location.Location;
import android.net.wifi.ScanResult;

import com.android.internal.location.CellState;

import java.util.List;

/**
@@ -45,22 +43,6 @@ public interface ILocationCollector {
     */
    abstract public void updateWifiScanResults(List<ScanResult> currentScanResults);

    /**
     * Updates the status of the network location provider.
     *
     * @param enabled true if user has enabled network location based on Google's database
     * of wifi points and cell towers.
     */
    abstract public void updateNetworkProviderStatus(boolean enabled);

    /**
     * Updates cell tower state. This is usually always up to date so should be uploaded
     * each time a new location is available.
     *
     * @param newState cell state
     */
    abstract public void updateCellState(CellState newState);

    /**
     * Updates the battery health. Battery level is healthy if there is greater than
     * {@link #MIN_BATTERY_LEVEL} percentage left or if the device is plugged in
+0 −135
Original line number Diff line number Diff line
@@ -64,8 +64,6 @@ import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.CellLocation;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Config;
import android.util.Log;
@@ -73,7 +71,6 @@ import android.util.PrintWriterPrinter;
import android.util.SparseIntArray;

import com.android.internal.app.IBatteryStats;
import com.android.internal.location.CellState;
import com.android.internal.location.GpsLocationProvider;
import com.android.internal.location.ILocationCollector;
import com.android.internal.location.INetworkLocationManager;
@@ -576,10 +573,6 @@ public class LocationManagerService extends ILocationManager.Stub

        // Listen for Radio changes
        mTelephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
        mTelephonyManager.listen(mPhoneStateListener,
                PhoneStateListener.LISTEN_CELL_LOCATION |
                PhoneStateListener.LISTEN_SIGNAL_STRENGTH |
                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);

        // Register for Network (Wifi or Mobile) updates
        NetworkStateBroadcastReceiver networkReceiver = new NetworkStateBroadcastReceiver();
@@ -641,13 +634,6 @@ public class LocationManagerService extends ILocationManager.Stub
                mNetworkLocationInterface.updateWifiEnabledState(mWifiEnabled);
                mNetworkLocationInterface.updateCellLockStatus(mCellWakeLockAcquired);

                if (mLastCellState != null) {
                    if (mCollector != null) {
                        mCollector.updateCellState(mLastCellState);
                    }
                    mNetworkLocationProvider.updateCellState(mLastCellState);
                }

                // There might be an existing wifi scan available
                if (mWifiManager != null) {
                    List<ScanResult> wifiScanResults = mWifiManager.getScanResults();
@@ -797,12 +783,6 @@ public class LocationManagerService extends ILocationManager.Stub
            String name = p.getName();
            boolean shouldBeEnabled = isAllowedBySettingsLocked(name);

            // Collection is only allowed when network provider is being used
            if (mCollector != null &&
                    p.getName().equals(LocationManager.NETWORK_PROVIDER)) {
                mCollector.updateNetworkProviderStatus(shouldBeEnabled);
            }

            if (isEnabled && !shouldBeEnabled) {
                updateProviderListenersLocked(name, false);
            } else if (!isEnabled && shouldBeEnabled) {
@@ -1745,117 +1725,6 @@ public class LocationManagerService extends ILocationManager.Stub
        }
    }

    class CellLocationUpdater extends Thread {
        CellLocation mNextLocation;
        
        CellLocationUpdater() {
            super("CellLocationUpdater");
        }
        
        @Override
        public void run() {
            int curAsu = -1;
            CellLocation curLocation = null;
            
            while (true) {
                // See if there is more work to do...
                synchronized (mLocationListeners) {
                    if (curLocation == mNextLocation) {
                        mCellLocationUpdater = null;
                        break;
                    }
                    
                    curLocation = mNextLocation;
                    if (curLocation == null) {
                        mCellLocationUpdater = null;
                        break;
                    }
                    
                    curAsu = mLastSignalStrength;
                    
                    mNextLocation = null;
                }
                
                try {
                    // Gets cell state.  This can block so must be done without
                    // locks held.
                    CellState cs = new CellState(mTelephonyManager, curLocation, curAsu);
                    
                    synchronized (mLocationListeners) {
                        mLastCellState = cs;
        
                        cs.updateSignalStrength(mLastSignalStrength);
                        cs.updateRadioType(mLastRadioType);
                        
                        // Notify collector
                        if (mCollector != null) {
                            mCollector.updateCellState(cs);
                        }
    
                        // Updates providers
                        List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
                        for (LocationProviderImpl provider : providers) {
                            if (provider.requiresCell()) {
                                provider.updateCellState(cs);
                            }
                        }
                    }
                } catch (RuntimeException e) {
                    Log.e(TAG, "Exception in PhoneStateListener.onCellLocationChanged:", e);
                }
            }
        }
    }
    
    CellLocationUpdater mCellLocationUpdater = null;
    CellState mLastCellState = null;
    int mLastSignalStrength = -1;
    int mLastRadioType = -1;
    
    PhoneStateListener mPhoneStateListener = new PhoneStateListener() {

        @Override
        public void onCellLocationChanged(CellLocation cellLocation) {
            synchronized (mLocationListeners) {
                if (mCellLocationUpdater == null) {
                    mCellLocationUpdater = new CellLocationUpdater();
                    mCellLocationUpdater.start();
                }
                mCellLocationUpdater.mNextLocation = cellLocation;
            }
        }

        @Override
        public void onSignalStrengthChanged(int asu) {
            synchronized (mLocationListeners) {
                mLastSignalStrength = asu;
    
                if (mLastCellState != null) {
                    mLastCellState.updateSignalStrength(asu);
                }
            }
        }

        @Override
        public void onDataConnectionStateChanged(int state) {
            synchronized (mLocationListeners) {
                // Get radio type
                int radioType = mTelephonyManager.getNetworkType();
                if (radioType == TelephonyManager.NETWORK_TYPE_GPRS ||
                    radioType == TelephonyManager.NETWORK_TYPE_EDGE) {
                    radioType = CellState.RADIO_TYPE_GPRS;
                } else if (radioType == TelephonyManager.NETWORK_TYPE_UMTS) {
                    radioType = CellState.RADIO_TYPE_WCDMA;
                }
                mLastRadioType = radioType;

                if (mLastCellState != null) {
                    mLastCellState.updateRadioType(radioType);
                }
            }
        }
    };

    private class PowerStateBroadcastReceiver extends BroadcastReceiver {
        @Override public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
@@ -2460,10 +2329,6 @@ public class LocationManagerService extends ILocationManager.Stub
            pw.println("  mGpsNavigating=" + mGpsNavigating);
            pw.println("  mNetworkLocationProvider=" + mNetworkLocationProvider);
            pw.println("  mNetworkLocationInterface=" + mNetworkLocationInterface);
            pw.println("  mLastSignalStrength=" + mLastSignalStrength
                    + "  mLastRadioType=" + mLastRadioType);
            pw.println("  mCellLocationUpdater=" + mCellLocationUpdater);
            pw.println("  mLastCellState=" + mLastCellState);
            pw.println("  mCollector=" + mCollector);
            pw.println("  mAlarmInterval=" + mAlarmInterval
                    + " mScreenOn=" + mScreenOn