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

Commit 9751190b authored by Katherine Kuan's avatar Katherine Kuan Committed by Android (Google) Code Review
Browse files

Merge "Add logging to country detector logic"

parents acd5f963 da123492
Loading
Loading
Loading
Loading
+43 −4
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.location;

import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;

import java.util.Locale;

@@ -58,8 +59,14 @@ public class Country implements Parcelable {
    private final int mSource;

    private int mHashCode;

    /**
     * Time that this object was created (which we assume to be the time that the source was
     * consulted). This time is in milliseconds since boot up.
     */
    private final long mTimestamp;

    /**
     *
     * @param countryIso the ISO 3166-1 two letters country code.
     * @param source where the countryIso came from, could be one of below
     *        values
@@ -78,11 +85,23 @@ public class Country implements Parcelable {
        }
        mCountryIso = countryIso.toUpperCase(Locale.US);
        mSource = source;
        mTimestamp = SystemClock.elapsedRealtime();
    }

    private Country(final String countryIso, final int source, long timestamp) {
        if (countryIso == null || source < COUNTRY_SOURCE_NETWORK
                || source > COUNTRY_SOURCE_LOCALE) {
            throw new IllegalArgumentException();
        }
        mCountryIso = countryIso.toUpperCase(Locale.US);
        mSource = source;
        mTimestamp = timestamp;
    }

    public Country(Country country) {
        mCountryIso = country.mCountryIso;
        mSource = country.mSource;
        mTimestamp = country.mTimestamp;
    }

    /**
@@ -106,9 +125,17 @@ public class Country implements Parcelable {
        return mSource;
    }

    /**
     * Returns the time that this object was created (which we assume to be the time that the source
     * was consulted).
     */
    public final long getTimestamp() {
        return mTimestamp;
    }

    public static final Parcelable.Creator<Country> CREATOR = new Parcelable.Creator<Country>() {
        public Country createFromParcel(Parcel in) {
            return new Country(in.readString(), in.readInt());
            return new Country(in.readString(), in.readInt(), in.readLong());
        }

        public Country[] newArray(int size) {
@@ -123,8 +150,14 @@ public class Country implements Parcelable {
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeString(mCountryIso);
        parcel.writeInt(mSource);
        parcel.writeLong(mTimestamp);
    }

    /**
     * Returns true if this {@link Country} is equivalent to the given object. This ignores
     * the timestamp value and just checks for equivalence of countryIso and source values.
     * Returns false otherwise.
     */
    @Override
    public boolean equals(Object object) {
        if (object == this) {
@@ -132,6 +165,7 @@ public class Country implements Parcelable {
        }
        if (object instanceof Country) {
            Country c = (Country) object;
            // No need to check the equivalence of the timestamp
            return mCountryIso.equals(c.getCountryIso()) && mSource == c.getSource();
        }
        return false;
@@ -150,8 +184,8 @@ public class Country implements Parcelable {
    }

    /**
     * Compare the specified country to this country object ignoring the mSource
     * field, return true if the countryIso fields are equal
     * Compare the specified country to this country object ignoring the source
     * and timestamp fields, return true if the countryIso fields are equal
     *
     * @param country the country to compare
     * @return true if the specified country's countryIso field is equal to this
@@ -160,4 +194,9 @@ public class Country implements Parcelable {
    public boolean equalsIgnoreSource(Country country) {
        return country != null && mCountryIso.equals(country.getCountryIso());
    }

    @Override
    public String toString() {
        return "Country {ISO=" + mCountryIso + ", source=" + mSource + ", time=" + mTimestamp + "}";
    }
}
+21 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.HashMap;

import com.android.server.location.ComprehensiveCountryDetector;
@@ -30,6 +32,8 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.Slog;

/**
@@ -75,7 +79,7 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run
        }
    }

    private final static String TAG = "CountryDetectorService";
    private final static String TAG = "CountryDetector";

    private final HashMap<IBinder, Receiver> mReceivers;
    private final Context mContext;
@@ -201,4 +205,20 @@ public class CountryDetectorService extends ICountryDetector.Stub implements Run
    boolean isSystemReady() {
        return mSystemReady;
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
        try {
            final Printer p = new PrintWriterPrinter(fout);
            p.println("CountryDetectorService state:");
            p.println("  Number of listeners=" + mReceivers.keySet().size());
            if (mCountryDetector == null) {
                p.println("  ComprehensiveCountryDetector not initialized");
            } else {
                p.println("  " + mCountryDetector.toString());
            }
        } catch (Exception e) {
            Slog.e(TAG, "Failed to dump CountryDetectorService: ", e);
        }
    }
}
+119 −4
Original line number Diff line number Diff line
@@ -20,16 +20,19 @@ import android.content.Context;
import android.location.Country;
import android.location.CountryListener;
import android.location.Geocoder;
import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;

import java.util.Locale;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * This class is used to detect the country where the user is. The sources of
@@ -55,9 +58,14 @@ import java.util.TimerTask;
 */
public class ComprehensiveCountryDetector extends CountryDetectorBase {

    private final static String TAG = "ComprehensiveCountryDetector";
    private final static String TAG = "CountryDetector";
    /* package */ static final boolean DEBUG = false;

    /**
     * Max length of logs to maintain for debugging.
     */
    private static final int MAX_LENGTH_DEBUG_LOGS = 20;

    /**
     * The refresh interval when the location based country was used
     */
@@ -73,6 +81,52 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {

    private PhoneStateListener mPhoneStateListener;

    /**
     * List of the most recent country state changes for debugging. This should have
     * a max length of MAX_LENGTH_LOGS.
     */
    private final ConcurrentLinkedQueue<Country> mDebugLogs = new ConcurrentLinkedQueue<Country>();

    /**
     * Most recent {@link Country} result that was added to the debug logs {@link #mDebugLogs}.
     * We keep track of this value to help prevent adding many of the same {@link Country} objects
     * to the logs.
     */
    private Country mLastCountryAddedToLogs;

    /**
     * Object used to synchronize access to {@link #mLastCountryAddedToLogs}. Be careful if
     * using it to synchronize anything else in this file.
     */
    private final Object mObject = new Object();

    /**
     * Start time of the current session for which the detector has been active.
     */
    private long mStartTime;

    /**
     * Stop time of the most recent session for which the detector was active.
     */
    private long mStopTime;

    /**
     * The sum of all the time intervals in which the detector was active.
     */
    private long mTotalTime;

    /**
     * Number of {@link PhoneStateListener#onServiceStateChanged(ServiceState state)} events that
     * have occurred for the current session for which the detector has been active.
     */
    private int mCountServiceStateChanges;

    /**
     * Total number of {@link PhoneStateListener#onServiceStateChanged(ServiceState state)} events
     * that have occurred for all time intervals in which the detector has been active.
     */
    private int mTotalCountServiceStateChanges;

    /**
     * The listener for receiving the notification from LocationBasedCountryDetector.
     */
@@ -124,9 +178,36 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
        if (result == null) {
            result = getLocaleCountry();
        }
        addToLogs(result);
        return result;
    }

    /**
     * Attempt to add this {@link Country} to the debug logs.
     */
    private void addToLogs(Country country) {
        if (country == null) {
            return;
        }
        // If the country (ISO and source) are the same as before, then there is no
        // need to add this country as another entry in the logs. Synchronize access to this
        // variable since multiple threads could be calling this method.
        synchronized (mObject) {
            if (mLastCountryAddedToLogs != null && mLastCountryAddedToLogs.equals(country)) {
                return;
            }
            mLastCountryAddedToLogs = country;
        }
        // Manually maintain a max limit for the list of logs
        if (mDebugLogs.size() >= MAX_LENGTH_DEBUG_LOGS) {
            mDebugLogs.poll();
        }
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Slog.d(TAG, country.toString());
        }
        mDebugLogs.add(country);
    }

    private boolean isNetworkCountryCodeAvailable() {
        // On CDMA TelephonyManager.getNetworkCountryIso() just returns SIM country.  We don't want
        // to prioritize it over location based country, so ignore it.
@@ -218,9 +299,14 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
            removePhoneStateListener();
            stopLocationBasedDetector();
            cancelLocationRefresh();
            mStopTime = SystemClock.elapsedRealtime();
            mTotalTime += mStopTime;
        } else if (prevListener == null) {
            addPhoneStateListener();
            detectCountry(false, true);
            mStartTime = SystemClock.elapsedRealtime();
            mStopTime = 0;
            mCountServiceStateChanges = 0;
        }
    }

@@ -308,9 +394,9 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
    private void notifyIfCountryChanged(final Country country, final Country detectedCountry) {
        if (detectedCountry != null && mListener != null
                && (country == null || !country.equals(detectedCountry))) {
            Slog.d(TAG,
                    "The country was changed from " + country != null ? country.getCountryIso() :
                        country + " to " + detectedCountry.getCountryIso());
            if (Log.isLoggable(TAG, Log.DEBUG)) {
                Slog.d(TAG, "" + country + " --> " + detectedCountry);
            }
            notifyListener(detectedCountry);
        }
    }
@@ -352,6 +438,9 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
            mPhoneStateListener = new PhoneStateListener() {
                @Override
                public void onServiceStateChanged(ServiceState serviceState) {
                    mCountServiceStateChanges++;
                    mTotalCountServiceStateChanges++;

                    if (!isNetworkCountryCodeAvailable()) {
                        return;
                    }
@@ -374,4 +463,30 @@ public class ComprehensiveCountryDetector extends CountryDetectorBase {
    protected boolean isGeoCoderImplemented() {
        return Geocoder.isPresent();
    }

    @Override
    public String toString() {
        long currentTime = SystemClock.elapsedRealtime();
        long currentSessionLength = 0;
        StringBuilder sb = new StringBuilder();
        sb.append("ComprehensiveCountryDetector{");
        // The detector hasn't stopped yet --> still running
        if (mStopTime == 0) {
            currentSessionLength = currentTime - mStartTime;
            sb.append("timeRunning=" + currentSessionLength + ", ");
        } else {
            // Otherwise, it has already stopped, so take the last session
            sb.append("lastRunTimeLength=" + (mStopTime - mStartTime) + ", ");
        }
        sb.append("totalCountServiceStateChanges=" + mTotalCountServiceStateChanges + ", ");
        sb.append("currentCountServiceStateChanges=" + mCountServiceStateChanges + ", ");
        sb.append("totalTime=" + (mTotalTime + currentSessionLength) + ", ");
        sb.append("currentTime=" + currentTime + ", ");
        sb.append("countries=");
        for (Country country : mDebugLogs) {
            sb.append("\n   " + country.toString());
        }
        sb.append("}");
        return sb.toString();
    }
}