Merge changes from topic "COUNTRY_DETECTOR_API_ENHANCEMENT"
* changes: API Enhancement CountryDetector Revert CountryDetector changes
This commit is contained in:
committed by
Android (Google) Code Review
commit
32765d94a1
@@ -5804,8 +5804,9 @@ package android.location {
|
||||
}
|
||||
|
||||
public final class Country implements android.os.Parcelable {
|
||||
ctor public Country(@NonNull String, int);
|
||||
method public int describeContents();
|
||||
method @NonNull public String getCountryIso();
|
||||
method @NonNull public String getCountryCode();
|
||||
method public int getSource();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field public static final int COUNTRY_SOURCE_LOCALE = 3; // 0x3
|
||||
@@ -5816,13 +5817,8 @@ package android.location {
|
||||
}
|
||||
|
||||
public class CountryDetector {
|
||||
method public void addCountryListener(@NonNull android.location.CountryListener, @Nullable android.os.Looper);
|
||||
method @Nullable public android.location.Country detectCountry();
|
||||
method public void removeCountryListener(@NonNull android.location.CountryListener);
|
||||
}
|
||||
|
||||
public interface CountryListener {
|
||||
method public void onCountryDetected(@NonNull android.location.Country);
|
||||
method public void registerCountryDetectorCallback(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Country>);
|
||||
method public void unregisterCountryDetectorCallback(@NonNull java.util.function.Consumer<android.location.Country>);
|
||||
}
|
||||
|
||||
public final class GnssCapabilities implements android.os.Parcelable {
|
||||
|
||||
@@ -3,10 +3,6 @@ ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
|
||||
Method should return Collection<CharSequence> (or subclass) instead of raw array; was `java.lang.CharSequence[]`
|
||||
|
||||
|
||||
ExecutorRegistration: android.location.CountryDetector#addCountryListener(android.location.CountryListener, android.os.Looper):
|
||||
Registration methods should have overload that accepts delivery Executor: `addCountryListener`
|
||||
|
||||
|
||||
GenericException: android.app.prediction.AppPredictor#finalize():
|
||||
Methods must not throw generic exceptions (`java.lang.Throwable`)
|
||||
GenericException: android.hardware.location.ContextHubClient#finalize():
|
||||
@@ -131,8 +127,6 @@ SamShouldBeLast: android.content.pm.PackageItemInfo#dumpFront(android.util.Print
|
||||
SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpFront) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
|
||||
SamShouldBeLast: android.content.pm.ResolveInfo#dump(android.util.Printer, String):
|
||||
SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.ResolveInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
|
||||
SamShouldBeLast: android.location.CountryDetector#addCountryListener(android.location.CountryListener, android.os.Looper):
|
||||
SAM-compatible parameters (such as parameter 1, "listener", in android.location.CountryDetector.addCountryListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
|
||||
SamShouldBeLast: android.location.Location#dump(android.util.Printer, String):
|
||||
SAM-compatible parameters (such as parameter 1, "pw", in android.location.Location.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
|
||||
SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.location;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.SystemApi;
|
||||
@@ -24,6 +25,8 @@ import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.SystemClock;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
@@ -54,8 +57,22 @@ public final class Country implements Parcelable {
|
||||
public static final int COUNTRY_SOURCE_LOCALE = 3;
|
||||
|
||||
/**
|
||||
* The ISO 3166-1 two letters country code.
|
||||
* Country source type
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@IntDef(
|
||||
prefix = {"COUNTRY_SOURCE_"},
|
||||
value = {
|
||||
COUNTRY_SOURCE_NETWORK,
|
||||
COUNTRY_SOURCE_LOCATION,
|
||||
COUNTRY_SOURCE_SIM,
|
||||
COUNTRY_SOURCE_LOCALE
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface CountrySource {}
|
||||
|
||||
/** The ISO 3166-1 two letters country code. */
|
||||
private final String mCountryIso;
|
||||
|
||||
/**
|
||||
@@ -73,21 +90,18 @@ public final class Country implements Parcelable {
|
||||
|
||||
/**
|
||||
* @param countryIso the ISO 3166-1 two letters country code.
|
||||
* @param source where the countryIso came from, could be one of below
|
||||
* values
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>{@link #COUNTRY_SOURCE_NETWORK}</li>
|
||||
* <li>{@link #COUNTRY_SOURCE_LOCATION}</li>
|
||||
* <li>{@link #COUNTRY_SOURCE_SIM}</li>
|
||||
* <li>{@link #COUNTRY_SOURCE_LOCALE}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @hide
|
||||
* @param source where the countryIso came from, could be one of below values
|
||||
* <p>
|
||||
* <ul>
|
||||
* <li>{@link #COUNTRY_SOURCE_NETWORK}
|
||||
* <li>{@link #COUNTRY_SOURCE_LOCATION}
|
||||
* <li>{@link #COUNTRY_SOURCE_SIM}
|
||||
* <li>{@link #COUNTRY_SOURCE_LOCALE}
|
||||
* </ul>
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
public Country(final String countryIso, final int source) {
|
||||
if (countryIso == null || source < COUNTRY_SOURCE_NETWORK
|
||||
public Country(@NonNull final String countryIso, @CountrySource final int source) {
|
||||
if (countryIso == null
|
||||
|| source < COUNTRY_SOURCE_NETWORK
|
||||
|| source > COUNTRY_SOURCE_LOCALE) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
@@ -115,9 +129,24 @@ public final class Country implements Parcelable {
|
||||
|
||||
/**
|
||||
* @return the ISO 3166-1 two letters country code
|
||||
*
|
||||
* @hide
|
||||
*
|
||||
* @deprecated clients using getCountryIso should use the {@link #getCountryCode()} API instead.
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
@Deprecated
|
||||
public String getCountryIso() {
|
||||
return mCountryIso;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves country code.
|
||||
*
|
||||
* @return country code in ISO 3166-1:alpha2
|
||||
*/
|
||||
@NonNull
|
||||
public String getCountryIso() {
|
||||
public String getCountryCode() {
|
||||
return mCountryIso;
|
||||
}
|
||||
|
||||
@@ -131,6 +160,7 @@ public final class Country implements Parcelable {
|
||||
* <li>{@link #COUNTRY_SOURCE_LOCALE}</li>
|
||||
* </ul>
|
||||
*/
|
||||
@CountrySource
|
||||
public int getSource() {
|
||||
return mSource;
|
||||
}
|
||||
|
||||
@@ -24,28 +24,32 @@ import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerExecutor;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* This class provides access to the system country detector service. This
|
||||
* service allows applications to obtain the country that the user is in.
|
||||
* <p>
|
||||
* The country will be detected in order of reliability, like
|
||||
* This class provides access to the system country detector service. This service allows
|
||||
* applications to obtain the country that the user is in.
|
||||
*
|
||||
* <p>The country will be detected in order of reliability, like
|
||||
*
|
||||
* <ul>
|
||||
* <li>Mobile network</li>
|
||||
* <li>Location</li>
|
||||
* <li>SIM's country</li>
|
||||
* <li>Phone's locale</li>
|
||||
* <li>Mobile network
|
||||
* <li>Location
|
||||
* <li>SIM's country
|
||||
* <li>Phone's locale
|
||||
* </ul>
|
||||
* <p>
|
||||
* Call the {@link #detectCountry()} to get the available country immediately.
|
||||
* <p>
|
||||
* To be notified of the future country change, use the
|
||||
* {@link #addCountryListener}
|
||||
*
|
||||
* <p>Call the {@link #detectCountry()} to get the available country immediately.
|
||||
*
|
||||
* <p>To be notified of the future country change, use the {@link #addCountryListener}
|
||||
*
|
||||
* <p>
|
||||
*
|
||||
* @hide
|
||||
@@ -55,57 +59,52 @@ import java.util.HashMap;
|
||||
public class CountryDetector {
|
||||
|
||||
/**
|
||||
* The class to wrap the ICountryListener.Stub and CountryListener objects
|
||||
* together. The CountryListener will be notified through the specific
|
||||
* looper once the country changed and detected.
|
||||
* The class to wrap the ICountryListener.Stub , CountryListener & {@code Consumer<Country>}
|
||||
* objects together.
|
||||
*
|
||||
* <p>The CountryListener will be notified through the Handler Executor once the country changed
|
||||
* and detected.
|
||||
*
|
||||
* <p>{@code Consumer<Country>} callback interface is notified through the specific executor
|
||||
* once the country changed and detected.
|
||||
*/
|
||||
private final static class ListenerTransport extends ICountryListener.Stub {
|
||||
private static final class ListenerTransport extends ICountryListener.Stub {
|
||||
|
||||
private final CountryListener mListener;
|
||||
private final Consumer<Country> mListener;
|
||||
private final Executor mExecutor;
|
||||
|
||||
private final Handler mHandler;
|
||||
|
||||
public ListenerTransport(CountryListener listener, Looper looper) {
|
||||
mListener = listener;
|
||||
if (looper != null) {
|
||||
mHandler = new Handler(looper);
|
||||
} else {
|
||||
mHandler = new Handler();
|
||||
}
|
||||
ListenerTransport(Consumer<Country> consumer, Executor executor) {
|
||||
mListener = consumer;
|
||||
mExecutor = executor;
|
||||
}
|
||||
|
||||
public void onCountryDetected(final Country country) {
|
||||
mHandler.post(new Runnable() {
|
||||
public void run() {
|
||||
mListener.onCountryDetected(country);
|
||||
}
|
||||
});
|
||||
mExecutor.execute(() -> mListener.accept(country));
|
||||
}
|
||||
}
|
||||
|
||||
private final static String TAG = "CountryDetector";
|
||||
private static final String TAG = "CountryDetector";
|
||||
private final ICountryDetector mService;
|
||||
private final HashMap<CountryListener, ListenerTransport> mListeners;
|
||||
private final HashMap<Consumer<Country>, ListenerTransport> mListeners;
|
||||
|
||||
/**
|
||||
* @hide - hide this constructor because it has a parameter of type
|
||||
* ICountryDetector, which is a system private class. The right way to
|
||||
* create an instance of this class is using the factory
|
||||
* Context.getSystemService.
|
||||
* @hide - hide this constructor because it has a parameter of type ICountryDetector, which is a
|
||||
* system private class. The right way to create an instance of this class is using the
|
||||
* factory Context.getSystemService.
|
||||
*/
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
||||
public CountryDetector(ICountryDetector service) {
|
||||
mService = service;
|
||||
mListeners = new HashMap<CountryListener, ListenerTransport>();
|
||||
mListeners = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start detecting the country that the user is in.
|
||||
*
|
||||
* @return the country if it is available immediately, otherwise null will
|
||||
* be returned.
|
||||
* @return the country if it is available immediately, otherwise null will be returned.
|
||||
* @hide
|
||||
*/
|
||||
@Nullable
|
||||
@UnsupportedAppUsage
|
||||
public Country detectCountry() {
|
||||
try {
|
||||
return mService.detectCountry();
|
||||
@@ -116,40 +115,64 @@ public class CountryDetector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a listener to receive the notification when the country is detected
|
||||
* or changed.
|
||||
* Add a listener to receive the notification when the country is detected or changed.
|
||||
*
|
||||
* @param listener will be called when the country is detected or changed.
|
||||
* @param looper a Looper object whose message queue will be used to
|
||||
* implement the callback mechanism. If looper is null then the
|
||||
* callbacks will be called on the main thread.
|
||||
* @param looper a Looper object whose message queue will be used to implement the callback
|
||||
* mechanism. If looper is null then the callbacks will be called on the main thread.
|
||||
* @hide
|
||||
* @deprecated client using this api should use {@link
|
||||
* #registerCountryDetectorCallback(Executor, Consumer)} }
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
@Deprecated
|
||||
public void addCountryListener(@NonNull CountryListener listener, @Nullable Looper looper) {
|
||||
synchronized (mListeners) {
|
||||
if (!mListeners.containsKey(listener)) {
|
||||
ListenerTransport transport = new ListenerTransport(listener, looper);
|
||||
try {
|
||||
mService.addCountryListener(transport);
|
||||
mListeners.put(listener, transport);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "addCountryListener: RemoteException", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Handler handler = looper != null ? new Handler(looper) : new Handler();
|
||||
registerCountryDetectorCallback(new HandlerExecutor(handler), listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the listener
|
||||
*
|
||||
* @hide
|
||||
* @deprecated client using this api should use {@link
|
||||
* #unregisterCountryDetectorCallback(Consumer)}
|
||||
*/
|
||||
public void removeCountryListener(@NonNull CountryListener listener) {
|
||||
@UnsupportedAppUsage
|
||||
@Deprecated
|
||||
public void removeCountryListener(CountryListener listener) {
|
||||
unregisterCountryDetectorCallback(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a callback interface, to be notified when country code is added or changes.
|
||||
*
|
||||
* @param executor The callback executor for the response.
|
||||
* @param consumer {@link Consumer} callback to receive the country code when changed/detected
|
||||
*/
|
||||
public void registerCountryDetectorCallback(
|
||||
@NonNull Executor executor, @NonNull Consumer<Country> consumer) {
|
||||
synchronized (mListeners) {
|
||||
ListenerTransport transport = mListeners.get(listener);
|
||||
unregisterCountryDetectorCallback(consumer);
|
||||
ListenerTransport transport = new ListenerTransport(consumer, executor);
|
||||
try {
|
||||
mService.addCountryListener(transport);
|
||||
mListeners.put(consumer, transport);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove the callback subscribed to Update country code */
|
||||
public void unregisterCountryDetectorCallback(@NonNull Consumer<Country> consumer) {
|
||||
synchronized (mListeners) {
|
||||
ListenerTransport transport = mListeners.remove(consumer);
|
||||
if (transport != null) {
|
||||
try {
|
||||
mListeners.remove(listener);
|
||||
mService.removeCountryListener(transport);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "removeCountryListener: RemoteException", e);
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,9 @@
|
||||
|
||||
package android.location;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* The listener for receiving the notification when the country is detected or
|
||||
@@ -25,11 +26,17 @@ import android.annotation.SystemApi;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi(client = SystemApi.Client.PRIVILEGED_APPS)
|
||||
public interface CountryListener {
|
||||
public interface CountryListener extends Consumer<Country> {
|
||||
/**
|
||||
* @param country the changed or detected country.
|
||||
*
|
||||
*/
|
||||
void onCountryDetected(@NonNull Country country);
|
||||
@UnsupportedAppUsage
|
||||
void onCountryDetected(Country country);
|
||||
|
||||
/**
|
||||
* @param country the changed or detected country.
|
||||
*/
|
||||
default void accept(Country country) {
|
||||
onCountryDetected(country);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,6 +148,10 @@ public class CountryDetectorService extends ICountryDetector.Stub {
|
||||
Receiver r = new Receiver(listener);
|
||||
try {
|
||||
listener.asBinder().linkToDeath(r, 0);
|
||||
final Country country = detectCountry();
|
||||
if (country != null) {
|
||||
listener.onCountryDetected(country);
|
||||
}
|
||||
mReceivers.put(listener.asBinder(), r);
|
||||
if (mReceivers.size() == 1) {
|
||||
Slog.d(TAG, "The first listener is added");
|
||||
|
||||
Reference in New Issue
Block a user