Files
frameworks_base/services/java/com/android/server/CountryDetectorService.java
Bai Tao a58a8751b4 Add new system service CountryDetector
a. The CountryDetector detects the country the user is in
   in order of mobile network, location, sim card or locale.
   It will be used by contact and contact provider.

b. All added APIs are hidden at this stage.

Change-Id: I4ba278571ffb6ab6ded0996d4f440a18534f8ed4
2010-07-28 09:45:57 +08:00

205 lines
6.0 KiB
Java

/*
* Copyright (C) 2010 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.server;
import java.util.HashMap;
import com.android.server.location.ComprehensiveCountryDetector;
import android.content.Context;
import android.location.Country;
import android.location.CountryListener;
import android.location.ICountryDetector;
import android.location.ICountryListener;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Process;
import android.os.RemoteException;
import android.util.Slog;
/**
* This class detects the country that the user is in through
* {@link ComprehensiveCountryDetector}.
*
* @hide
*/
public class CountryDetectorService extends ICountryDetector.Stub implements Runnable {
/**
* The class represents the remote listener, it will also removes itself
* from listener list when the remote process was died.
*/
private final class Receiver implements IBinder.DeathRecipient {
private final ICountryListener mListener;
private final IBinder mKey;
public Receiver(ICountryListener listener) {
mListener = listener;
mKey = listener.asBinder();
}
public void binderDied() {
removeListener(mKey);
}
@Override
public boolean equals(Object otherObj) {
if (otherObj instanceof Receiver) {
return mKey.equals(((Receiver) otherObj).mKey);
}
return false;
}
@Override
public int hashCode() {
return mKey.hashCode();
}
public ICountryListener getListener() {
return mListener;
}
}
private final static String TAG = "CountryDetectorService";
private final HashMap<IBinder, Receiver> mReceivers;
private final Context mContext;
private ComprehensiveCountryDetector mCountryDetector;
private boolean mSystemReady;
private Handler mHandler;
private CountryListener mLocationBasedDetectorListener;
public CountryDetectorService(Context context) {
super();
mReceivers = new HashMap<IBinder, Receiver>();
mContext = context;
}
@Override
public Country detectCountry() throws RemoteException {
if (!mSystemReady) {
throw new RemoteException();
}
return mCountryDetector.detectCountry();
}
/**
* Add the ICountryListener into the listener list.
*/
@Override
public void addCountryListener(ICountryListener listener) throws RemoteException {
if (!mSystemReady) {
throw new RemoteException();
}
addListener(listener);
}
/**
* Remove the ICountryListener from the listener list.
*/
@Override
public void removeCountryListener(ICountryListener listener) throws RemoteException {
if (!mSystemReady) {
throw new RemoteException();
}
removeListener(listener.asBinder());
}
private void addListener(ICountryListener listener) {
synchronized (mReceivers) {
Receiver r = new Receiver(listener);
try {
listener.asBinder().linkToDeath(r, 0);
mReceivers.put(listener.asBinder(), r);
if (mReceivers.size() == 1) {
Slog.d(TAG, "The first listener is added");
setCountryListener(mLocationBasedDetectorListener);
}
} catch (RemoteException e) {
Slog.e(TAG, "linkToDeath failed:", e);
}
}
}
private void removeListener(IBinder key) {
synchronized (mReceivers) {
mReceivers.remove(key);
if (mReceivers.isEmpty()) {
setCountryListener(null);
Slog.d(TAG, "No listener is left");
}
}
}
protected void notifyReceivers(Country country) {
synchronized(mReceivers) {
for (Receiver receiver : mReceivers.values()) {
try {
receiver.getListener().onCountryDetected(country);
} catch (RemoteException e) {
// TODO: Shall we remove the receiver?
Slog.e(TAG, "notifyReceivers failed:", e);
}
}
}
}
void systemReady() {
// Shall we wait for the initialization finish.
Thread thread = new Thread(this, "CountryDetectorService");
thread.start();
}
private void initialize() {
mCountryDetector = new ComprehensiveCountryDetector(mContext);
mLocationBasedDetectorListener = new CountryListener() {
public void onCountryDetected(final Country country) {
mHandler.post(new Runnable() {
public void run() {
notifyReceivers(country);
}
});
}
};
}
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
Looper.prepare();
mHandler = new Handler();
initialize();
mSystemReady = true;
Looper.loop();
}
protected void setCountryListener(final CountryListener listener) {
mHandler.post(new Runnable() {
@Override
public void run() {
mCountryDetector.setCountryListener(listener);
}
});
}
// For testing
boolean isSystemReady() {
return mSystemReady;
}
}