OSDN Git Service

resolved conflicts for merge of f0c4f0dd to mnc-dev
authorWei Liu <luciferleo@google.com>
Wed, 13 May 2015 16:57:33 +0000 (09:57 -0700)
committerWei Liu <luciferleo@google.com>
Wed, 13 May 2015 16:57:33 +0000 (09:57 -0700)
Change-Id: I16df088016c010aa25ee73ea8e68b3db8c0449e3

1  2 
services/core/java/com/android/server/LocationManagerService.java
services/core/java/com/android/server/location/GpsLocationProvider.java

@@@ -60,6 -60,9 +60,7 @@@ import android.location.Address
  import android.location.Criteria;
  import android.location.GeocoderParams;
  import android.location.Geofence;
 -import android.location.GpsMeasurementsEvent;
 -import android.location.GpsNavigationMessageEvent;
+ import android.location.IGpsGeofenceHardware;
  import android.location.IGpsMeasurementsListener;
  import android.location.IGpsNavigationMessageListener;
  import android.location.IGpsStatusListener;
@@@ -162,6 -165,7 +163,7 @@@ public class LocationManagerService ext
      private LocationBlacklist mBlacklist;
      private GpsMeasurementsProvider mGpsMeasurementsProvider;
      private GpsNavigationMessageProvider mGpsNavigationMessageProvider;
+     private IGpsGeofenceHardware mGpsGeofenceProxy;
  
      // --- fields below are protected by mLock ---
      // Set of providers that are explicitly enabled
          addProviderLocked(passiveProvider);
          mEnabledProviders.add(passiveProvider.getName());
          mPassiveProvider = passiveProvider;
-         // Create a gps location provider
-         GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this,
-                 mLocationHandler.getLooper());
  
          if (GpsLocationProvider.isSupported()) {
+             // Create a gps location provider
+             GpsLocationProvider gpsProvider = new GpsLocationProvider(mContext, this,
+                     mLocationHandler.getLooper());
              mGpsStatusProvider = gpsProvider.getGpsStatusProvider();
              mNetInitiatedListener = gpsProvider.getNetInitiatedListener();
              addProviderLocked(gpsProvider);
              mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);
+             mGpsMeasurementsProvider = gpsProvider.getGpsMeasurementsProvider();
+             mGpsNavigationMessageProvider = gpsProvider.getGpsNavigationMessageProvider();
+             mGpsGeofenceProxy = gpsProvider.getGpsGeofenceProxy();
          }
-         mGpsMeasurementsProvider = gpsProvider.getGpsMeasurementsProvider();
-         mGpsNavigationMessageProvider = gpsProvider.getGpsNavigationMessageProvider();
  
          /*
          Load package name(s) containing location provider support.
                  com.android.internal.R.string.config_geofenceProviderPackageName,
                  com.android.internal.R.array.config_locationProviderPackageNames,
                  mLocationHandler,
-                 gpsProvider.getGpsGeofenceProxy(),
+                 mGpsGeofenceProxy,
                  flpHardwareProvider != null ? flpHardwareProvider.getGeofenceHardware() : null);
          if (provider == null) {
              Slog.e(TAG,  "Unable to bind FLP Geofence proxy.");
              Binder.restoreCallingIdentity(identity);
          }
  
-         if (!hasLocationAccess) {
+         if (!hasLocationAccess || mGpsMeasurementsProvider == null) {
              return false;
          }
          return mGpsMeasurementsProvider.addListener(listener);
  
      @Override
      public void removeGpsMeasurementsListener(IGpsMeasurementsListener listener) {
-         mGpsMeasurementsProvider.removeListener(listener);
+         if (mGpsMeasurementsProvider != null) {
+             mGpsMeasurementsProvider.removeListener(listener);
+         }
      }
  
      @Override
              Binder.restoreCallingIdentity(identity);
          }
  
-         if (!hasLocationAccess) {
+         if (!hasLocationAccess || mGpsNavigationMessageProvider == null) {
              return false;
          }
          return mGpsNavigationMessageProvider.addListener(listener);
  
      @Override
      public void removeGpsNavigationMessageListener(IGpsNavigationMessageListener listener) {
-         mGpsNavigationMessageProvider.removeListener(listener);
+         if (mGpsNavigationMessageProvider != null) {
+             mGpsNavigationMessageProvider.removeListener(listener);
+         }
      }
  
      @Override
@@@ -22,8 -22,10 +22,8 @@@ import com.android.internal.location.Gp
  import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
  import com.android.internal.location.ProviderProperties;
  import com.android.internal.location.ProviderRequest;
 -import com.android.internal.R;
  import com.android.internal.telephony.Phone;
  import com.android.internal.telephony.PhoneConstants;
 -import com.android.internal.telephony.TelephonyIntents;
  
  import android.app.AlarmManager;
  import android.app.AppOpsManager;
@@@ -70,6 -72,7 +70,6 @@@ import android.provider.Settings
  import android.provider.Telephony.Carriers;
  import android.provider.Telephony.Sms.Intents;
  import android.telephony.SmsMessage;
 -import android.telephony.SubscriptionInfo;
  import android.telephony.SubscriptionManager;
  import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
  import android.telephony.TelephonyManager;
@@@ -88,6 -91,7 +88,6 @@@ import java.io.StringReader
  import java.net.InetAddress;
  import java.net.UnknownHostException;
  import java.util.Date;
 -import java.util.List;
  import java.util.Map.Entry;
  import java.util.Properties;
  
@@@ -197,8 -201,6 +197,8 @@@ public class GpsLocationProvider implem
      private static final int REMOVE_LISTENER = 9;
      private static final int INJECT_NTP_TIME_FINISHED = 10;
      private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
 +    private static final int SUBSCRIPTION_OR_SIM_CHANGED = 12;
 +    private static final int INITIALIZE_HANDLER = 13;
  
      // Request setid
      private static final int AGPS_RIL_REQUEST_SETID_IMSI = 1;
      // True if gps should be disabled (used to support battery saver mode in settings).
      private boolean mDisableGps = false;
  
 -    // properties loaded from PROPERTIES_FILE
 +    /**
 +     * Properties loaded from PROPERTIES_FILE.
 +     * It must be accessed only inside {@link #mHandler}.
 +     */
      private Properties mProperties;
 +
      private String mSuplServerHost;
      private int mSuplServerPort = TCP_MIN_PORT;
      private String mC2KServerHost;
  
      private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
          @Override
 -        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
 +        public void addGpsStatusListener(IGpsStatusListener listener) {
              mListenerHelper.addListener(listener);
          }
  
                  checkSmsSuplInit(intent);
              } else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
                  checkWapSuplInit(intent);
 -            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE)) {
 +            } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
                  // retrieve NetworkInfo result for this UID
                  NetworkInfo info =
                          intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
  
                  int networkState;
                  if (intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false) ||
-                     !info.isConnected()) {
+                         !info.isConnected()) {
                      networkState = LocationProvider.TEMPORARILY_UNAVAILABLE;
                  } else {
                      networkState = LocationProvider.AVAILABLE;
                  }
  
                  updateNetworkState(networkState, info);
              } else if (PowerManager.ACTION_POWER_SAVE_MODE_CHANGED.equals(action)
                      || Intent.ACTION_SCREEN_OFF.equals(action)
              new OnSubscriptionsChangedListener() {
          @Override
          public void onSubscriptionsChanged() {
 -            subscriptionOrSimChanged(mContext);
 +            sendMessage(SUBSCRIPTION_OR_SIM_CHANGED, 0, null);
          }
      };
  
              }
          }
  
 -        try {
 -            // Convert properties to string contents and send it to HAL.
 -            ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
 -            properties.store(baos, null);
 -            native_configuration_update(baos.toString());
 -            Log.d(TAG, "final config = " + baos.toString());
 -        } catch (IOException ex) {
 -            Log.w(TAG, "failed to dump properties contents");
 +        if (native_is_gnss_configuration_supported()) {
 +            try {
 +                // Convert properties to string contents and send it to HAL.
 +                ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
 +                properties.store(baos, null);
 +                native_configuration_update(baos.toString());
 +                Log.d(TAG, "final config = " + baos.toString());
 +            } catch (IOException ex) {
 +                Log.w(TAG, "failed to dump properties contents");
 +            }
 +        } else if (DEBUG) {
 +            Log.d(TAG, "Skipped configuration update because GNSS configuration in GPS HAL is not"
 +                    + " supported");
          }
  
          // SUPL_ES configuration.
          mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
                  BatteryStats.SERVICE_NAME));
  
 -        // Load GPS configuration.
 +        // Construct internal handler
 +        mHandler = new ProviderHandler(looper);
 +
 +        // Load GPS configuration and register listeners in the background:
 +        // some operations, such as opening files and registering broadcast receivers, can take a
 +        // relative long time, so the ctor() is kept to create objects needed by this instance,
 +        // while IO initialization and registration is delegated to our internal handler
 +        // this approach is just fine because events are posted to our handler anyway
          mProperties = new Properties();
 -        reloadGpsProperties(mContext, mProperties);
 +        sendMessage(INITIALIZE_HANDLER, 0, null);
  
          // Create a GPS net-initiated handler.
          mNIHandler = new GpsNetInitiatedHandler(context,
                                                  mNetInitiatedListener,
                                                  mSuplEsEnabled);
  
 -        // TODO: When this object "finishes" we should unregister by invoking
 -        // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
 -        // This is not strictly necessary because it will be unregistered if the
 -        // notification fails but it is good form.
 -
 -        // Register for SubscriptionInfo list changes which is guaranteed
 -        // to invoke onSubscriptionsChanged the first time.
 -        SubscriptionManager.from(mContext)
 -            .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
 -
 -        // construct handler, listen for events
 -        mHandler = new ProviderHandler(looper);
 -        listenForBroadcasts();
 -
 -        // also listen for PASSIVE_PROVIDER updates
 -        mHandler.post(new Runnable() {
 -            @Override
 -            public void run() {
 -                LocationManager locManager =
 -                        (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
 -                final long minTime = 0;
 -                final float minDistance = 0;
 -                final boolean oneShot = false;
 -                LocationRequest request = LocationRequest.createFromDeprecatedProvider(
 -                        LocationManager.PASSIVE_PROVIDER,
 -                        minTime,
 -                        minDistance,
 -                        oneShot);
 -                // Don't keep track of this request since it's done on behalf of other clients
 -                // (which are kept track of separately).
 -                request.setHideFromAppOps(true);
 -                locManager.requestLocationUpdates(
 -                        request,
 -                        new NetworkLocationListener(),
 -                        mHandler.getLooper());
 -            }
 -        });
 -
          mListenerHelper = new GpsStatusListenerHelper(mHandler) {
              @Override
              protected boolean isAvailableInPlatform() {
 -                return GpsLocationProvider.isSupported();
 +                return isSupported();
              }
  
              @Override
          };
      }
  
 -    private void listenForBroadcasts() {
 -        IntentFilter intentFilter = new IntentFilter();
 -        intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
 -        intentFilter.addDataScheme("sms");
 -        intentFilter.addDataAuthority("localhost","7275");
 -        mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
 -
 -        intentFilter = new IntentFilter();
 -        intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
 -        try {
 -            intentFilter.addDataType("application/vnd.omaloc-supl-init");
 -        } catch (IntentFilter.MalformedMimeTypeException e) {
 -            Log.w(TAG, "Malformed SUPL init mime type");
 -        }
 -        mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
 -
 -        intentFilter = new IntentFilter();
 -        intentFilter.addAction(ALARM_WAKEUP);
 -        intentFilter.addAction(ALARM_TIMEOUT);
 -        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE);
 -        intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
 -        intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
 -        intentFilter.addAction(Intent.ACTION_SCREEN_ON);
 -        intentFilter.addAction(SIM_STATE_CHANGED);
 -        mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, mHandler);
 -    }
 -
      /**
       * Returns the name of this provider.
       */
          }
  
          if (info != null) {
 -            boolean dataEnabled = TelephonyManager.getDefault().getDataEnabled();
 -            boolean networkAvailable = info.isAvailable() && dataEnabled;
 -            String defaultApn = getSelectedApn();
 -            if (defaultApn == null) {
 -                defaultApn = "dummy-apn";
 -            }
 +            if (native_is_agps_ril_supported()) {
 +                boolean dataEnabled = TelephonyManager.getDefault().getDataEnabled();
 +                boolean networkAvailable = info.isAvailable() && dataEnabled;
 +                String defaultApn = getSelectedApn();
 +                if (defaultApn == null) {
 +                    defaultApn = "dummy-apn";
 +                }
  
 -            native_update_network_state(info.isConnected(), info.getType(),
 -                                        info.isRoaming(), networkAvailable,
 -                                        info.getExtraInfo(), defaultApn);
 +                native_update_network_state(info.isConnected(), info.getType(),
 +                        info.isRoaming(), networkAvailable,
 +                        info.getExtraInfo(), defaultApn);
 +            } else if (DEBUG) {
 +                Log.d(TAG, "Skipped network state update because AGPS-RIL in GPS HAL is not"
 +                        + " supported");
 +            }
          }
  
          if (info != null && info.getType() == ConnectivityManager.TYPE_MOBILE_SUPL
                      return GPS_POSITION_MODE_STANDALONE;
                  }
              }
 +            // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor
 +            // such mode when it is available
 +            if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) {
 +                return GPS_POSITION_MODE_MS_BASED;
 +            }
 +            // for now, just as the legacy code did, we fallback to MS-Assisted if it is available,
 +            // do fallback only for single-shot requests, because it is too expensive to do for
 +            // periodic requests as well
              if (singleShot
                      && hasCapability(GPS_CAPABILITY_MSA)
                      && (suplMode & AGPS_SUPL_MODE_MSA) != 0) {
                  return GPS_POSITION_MODE_MS_ASSISTED;
 -            } else if (hasCapability(GPS_CAPABILITY_MSB)
 -                    && (suplMode & AGPS_SUPL_MODE_MSB) != 0) {
 -                return GPS_POSITION_MODE_MS_BASED;
              }
          }
          return GPS_POSITION_MODE_STANDALONE;
              if (mC2KServerHost != null) {
                  native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
              }
 +
 +            mGpsMeasurementsProvider.onGpsEnabledChanged();
 +            mGpsNavigationMessageProvider.onGpsEnabledChanged();
          } else {
              synchronized (mLock) {
                  mEnabled = false;
  
          // do this before releasing wakelock
          native_cleanup();
 +
 +        mGpsMeasurementsProvider.onGpsEnabledChanged();
 +        mGpsNavigationMessageProvider.onGpsEnabledChanged();
      }
  
      @Override
          }
  
          if (wasNavigating != mNavigating) {
 -            mListenerHelper.onGpsEnabledChanged(mNavigating);
 -            mGpsMeasurementsProvider.onGpsEnabledChanged(mNavigating);
 -            mGpsNavigationMessageProvider.onGpsEnabledChanged(mNavigating);
 +            mListenerHelper.onStatusChanged(mNavigating);
  
              // send an intent to notify that the GPS has been enabled or disabled
              Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
      // NI Client support
      //=============================================================
      private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
 -        // Sends a response for an NI reqeust to HAL.
 +        // Sends a response for an NI request to HAL.
          @Override
          public boolean sendNiResponse(int notificationId, int userResponse)
          {
      private void requestSetID(int flags) {
          TelephonyManager phone = (TelephonyManager)
                  mContext.getSystemService(Context.TELEPHONY_SERVICE);
 -        int    type = AGPS_SETID_TYPE_NONE;
 +        int type = AGPS_SETID_TYPE_NONE;
          String data = "";
  
          if ((flags & AGPS_RIL_REQUEST_SETID_IMSI) == AGPS_RIL_REQUEST_SETID_IMSI) {
                  case UPDATE_LOCATION:
                      handleUpdateLocation((Location)msg.obj);
                      break;
 +                case SUBSCRIPTION_OR_SIM_CHANGED:
 +                    subscriptionOrSimChanged(mContext);
 +                    break;
 +                case INITIALIZE_HANDLER:
 +                    initialize();
 +                    break;
              }
              if (msg.arg2 == 1) {
                  // wakelock was taken for this message, release it
                  mWakeLock.release();
              }
          }
 -    };
 +
 +        /**
 +         * This method is bound to {@link #GpsLocationProvider(Context, ILocationManager, Looper)}.
 +         * It is in charge of loading properties and registering for events that will be posted to
 +         * this handler.
 +         */
 +        private void initialize() {
 +            // load default GPS configuration
 +            // (this configuration might change in the future based on SIM changes)
 +            reloadGpsProperties(mContext, mProperties);
 +
 +            // TODO: When this object "finishes" we should unregister by invoking
 +            // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener);
 +            // This is not strictly necessary because it will be unregistered if the
 +            // notification fails but it is good form.
 +
 +            // Register for SubscriptionInfo list changes which is guaranteed
 +            // to invoke onSubscriptionsChanged the first time.
 +            SubscriptionManager.from(mContext)
 +                    .addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
 +
 +            // listen for events
 +            IntentFilter intentFilter;
 +            if (native_is_agps_ril_supported()) {
 +                intentFilter = new IntentFilter();
 +                intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
 +                intentFilter.addDataScheme("sms");
 +                intentFilter.addDataAuthority("localhost", "7275");
 +                mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
 +
 +                intentFilter = new IntentFilter();
 +                intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
 +                try {
 +                    intentFilter.addDataType("application/vnd.omaloc-supl-init");
 +                } catch (IntentFilter.MalformedMimeTypeException e) {
 +                    Log.w(TAG, "Malformed SUPL init mime type");
 +                }
 +                mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
 +            } else if (DEBUG) {
 +                Log.d(TAG, "Skipped registration for SMS/WAP-PUSH messages because AGPS Ril in GPS"
 +                        + " HAL is not supported");
 +            }
 +
 +            intentFilter = new IntentFilter();
 +            intentFilter.addAction(ALARM_WAKEUP);
 +            intentFilter.addAction(ALARM_TIMEOUT);
 +            intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
 +            intentFilter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
 +            intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
 +            intentFilter.addAction(Intent.ACTION_SCREEN_ON);
 +            intentFilter.addAction(SIM_STATE_CHANGED);
 +            mContext.registerReceiver(mBroadcastReceiver, intentFilter, null, this);
 +
 +            // listen for PASSIVE_PROVIDER updates
 +            LocationManager locManager =
 +                    (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
 +            long minTime = 0;
 +            float minDistance = 0;
 +            boolean oneShot = false;
 +            LocationRequest request = LocationRequest.createFromDeprecatedProvider(
 +                    LocationManager.PASSIVE_PROVIDER,
 +                    minTime,
 +                    minDistance,
 +                    oneShot);
 +            // Don't keep track of this request since it's done on behalf of other clients
 +            // (which are kept track of separately).
 +            request.setHideFromAppOps(true);
 +            locManager.requestLocationUpdates(
 +                    request,
 +                    new NetworkLocationListener(),
 +                    getLooper());
 +        }
 +    }
  
      private final class NetworkLocationListener implements LocationListener {
          @Override
      static { class_init_native(); }
      private static native void class_init_native();
      private static native boolean native_is_supported();
 +    private static native boolean native_is_agps_ril_supported();
 +    private static native boolean native_is_gnss_configuration_supported();
  
      private native boolean native_init();
      private native void native_cleanup();