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

Commit f5e016e5 authored by Yu-Han Yang's avatar Yu-Han Yang
Browse files

Add GnssAssistanceProviderBase

Flag: android.location.flags.gnss_assistance_interface
Bug: 358381377
Bug: 209078566
Test: atest GnssAssistanceProviderBaseTest
Change-Id: Ia36f84ec2bbb6f0482b09845a3505b17d98c7dae
parent 3116d256
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -2161,6 +2161,17 @@
         config_enableGeofenceOverlay is false. -->
    <string name="config_geofenceProviderPackageName" translatable="false">@null</string>

    <!-- Whether to enable GNSS assistance overlay which allows GnssAssistanceProvider to be
     replaced by an app at run-time. When disabled, only the
     config_gnssAssistanceProviderPackageName package will be searched for
     GnssAssistanceProvider, otherwise any system package is eligible. Anyone who wants to
     disable the overlay mechanism can set it to false.
     -->
    <bool name="config_enableGnssAssistanceOverlay" translatable="false">true</bool>
    <!-- Package name providing GNSS assistance API support. Used only when
         config_enableGnssAssistanceOverlay is false. -->
    <string name="config_gnssAssistanceProviderPackageName" translatable="false">@null</string>

    <!-- Whether to enable Hardware Activity-Recognition overlay which allows Hardware
         Activity-Recognition to be replaced by an app at run-time. When disabled, only the
         config_activityRecognitionHardwarePackageName package will be searched for
+2 −0
Original line number Diff line number Diff line
@@ -2040,6 +2040,7 @@
  <java-symbol type="bool" name="config_useGnssHardwareProvider" />
  <java-symbol type="bool" name="config_enableGeocoderOverlay" />
  <java-symbol type="bool" name="config_enableGeofenceOverlay" />
  <java-symbol type="bool" name="config_enableGnssAssistanceOverlay" />
  <java-symbol type="bool" name="config_enableNetworkLocationOverlay" />
  <java-symbol type="bool" name="config_sf_limitedAlpha" />
  <java-symbol type="bool" name="config_unplugTurnsOnScreen" />
@@ -2222,6 +2223,7 @@
  <java-symbol type="string" name="config_gnssLocationProviderPackageName" />
  <java-symbol type="string" name="config_geocoderProviderPackageName" />
  <java-symbol type="string" name="config_geofenceProviderPackageName" />
  <java-symbol type="string" name="config_gnssAssistanceProviderPackageName" />
  <java-symbol type="string" name="config_networkLocationProviderPackageName" />
  <java-symbol type="string" name="config_wimaxManagerClassname" />
  <java-symbol type="string" name="config_wimaxNativeLibLocation" />
+7 −0
Original line number Diff line number Diff line
@@ -1435,6 +1435,13 @@ package android.location.provider {
    field public static final String ACTION_GEOCODE_PROVIDER = "com.android.location.service.GeocodeProvider";
  }

  @FlaggedApi("android.location.flags.gnss_assistance_interface") public abstract class GnssAssistanceProviderBase {
    ctor public GnssAssistanceProviderBase(@NonNull android.content.Context, @NonNull String);
    method @NonNull public final android.os.IBinder getBinder();
    method public abstract void onRequest(@NonNull android.os.OutcomeReceiver<android.location.GnssAssistance,java.lang.Throwable>);
    field public static final String ACTION_GNSS_ASSISTANCE_PROVIDER = "android.location.provider.action.GNSS_ASSISTANCE_PROVIDER";
  }

  public abstract class LocationProviderBase {
    ctor public LocationProviderBase(@NonNull android.content.Context, @NonNull String, @NonNull android.location.provider.ProviderProperties);
    method @Nullable public final android.os.IBinder getBinder();
+152 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 android.location.provider;

import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.location.GnssAssistance;
import android.location.flags.Flags;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.OutcomeReceiver;
import android.os.RemoteException;
import android.util.Log;

import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;


/**
 * Base class for GNSS assistance providers outside the system server.
 *
 * <p>GNSS assistance providers should be wrapped in a non-exported service which returns the result
 * of {@link #getBinder()} from the service's {@link android.app.Service#onBind(Intent)} method. The
 * service should not be exported so that components other than the system server cannot bind to it.
 * Alternatively, the service may be guarded by a permission that only system server can obtain. The
 * service may specify metadata on its capabilities:
 *
 * <ul>
 *   <li>"serviceVersion": An integer version code to help tie break if multiple services are
 *       capable of implementing the geocode provider. All else equal, the service with the highest
 *       version code will be chosen. Assumed to be 0 if not specified.
 *   <li>"serviceIsMultiuser": A boolean property, indicating if the service wishes to take
 *       responsibility for handling changes to the current user on the device. If true, the service
 *       will always be bound from the system user. If false, the service will always be bound from
 *       the current user. If the current user changes, the old binding will be released, and a new
 *       binding established under the new user. Assumed to be false if not specified.
 * </ul>
 *
 * <p>The service should have an intent filter in place for the GNSS assistance provider as
 * specified by the constant in this class.
 *
 * <p>GNSS assistance providers are identified by their UID / package name / attribution tag. Based
 * on this identity, geocode providers may be given some special privileges.
 *
 * @hide
 */
@FlaggedApi(Flags.FLAG_GNSS_ASSISTANCE_INTERFACE)
@SystemApi
public abstract class GnssAssistanceProviderBase {

    /**
     * The action the wrapping service should have in its intent filter to implement the GNSS
     * Assistance provider.
     */
    public static final String ACTION_GNSS_ASSISTANCE_PROVIDER =
            "android.location.provider.action.GNSS_ASSISTANCE_PROVIDER";

    final String mTag;
    @Nullable
    final String mAttributionTag;
    final IBinder mBinder;

    /**
     * Subclasses should pass in a context and an arbitrary tag that may be used for logcat logging
     * of errors, and thus should uniquely identify the class.
     */
    public GnssAssistanceProviderBase(@NonNull Context context, @NonNull String tag) {
        mTag = tag;
        mAttributionTag = context.getAttributionTag();
        mBinder = new GnssAssistanceProviderBase.Service();
    }

    /**
     * Returns the IBinder instance that should be returned from the {@link
     * android.app.Service#onBind(Intent)} method of the wrapping service.
     */
    @NonNull
    public final IBinder getBinder() {
        return mBinder;
    }

    /**
     * Requests GNSS assistance data of the given arguments. The given callback must be invoked
     * once.
     */
    public abstract void onRequest(
            @NonNull OutcomeReceiver<GnssAssistance, Throwable> callback);

    private class Service extends IGnssAssistanceProvider.Stub {
        @Override
        public void request(IGnssAssistanceCallback callback) {
            try {
                onRequest(new GnssAssistanceProviderBase.SingleUseCallback(callback));
            } catch (RuntimeException e) {
                // exceptions on one-way binder threads are dropped - move to a different thread
                Log.w(mTag, e);
                new Handler(Looper.getMainLooper())
                        .post(
                                () -> {
                                    throw new AssertionError(e);
                                });
            }
        }
    }

    private static class SingleUseCallback implements
            OutcomeReceiver<GnssAssistance, Throwable> {

        private final AtomicReference<IGnssAssistanceCallback> mCallback;

        SingleUseCallback(IGnssAssistanceCallback callback) {
            mCallback = new AtomicReference<>(callback);
        }

        @Override
        public void onError(Throwable e) {
            try {
                Objects.requireNonNull(mCallback.getAndSet(null)).onError();
            } catch (RemoteException r) {
                throw r.rethrowFromSystemServer();
            }
        }

        @Override
        public void onResult(GnssAssistance result) {
            try {
                Objects.requireNonNull(mCallback.getAndSet(null)).onResult(result);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
    }
}
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 android.location.provider;

import android.location.GnssAssistance;

/**
 * Binder interface for GNSS assistance callbacks.
 * @hide
 */
oneway interface IGnssAssistanceCallback {
    void onError();
    void onResult(in GnssAssistance result);
}
Loading