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

Commit 8ec56249 authored by yongnamcha's avatar yongnamcha
Browse files

Location Query for OTT Emergency Calls (frameworks)

This commit implements Location Query for OTT Emergency Calls
in frameworks.

Bug: 236748912
Test: cts test
Change-Id: Id1fbd33e7027146bca9d3a723977d1f63b077696
parent ccb92936
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -41314,6 +41314,7 @@ package android.telecom {
    method public void onUsingAlternativeUi(boolean);
    method public static String propertiesToString(int);
    method public final void putExtras(@NonNull android.os.Bundle);
    method public final void queryLocationForEmergency(@IntRange(from=100, to=5000) long, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.location.Location,android.telecom.QueryLocationException>);
    method public final void removeExtras(java.util.List<java.lang.String>);
    method public final void removeExtras(java.lang.String...);
    method @Deprecated public void requestBluetoothAudio(@NonNull android.bluetooth.BluetoothDevice);
@@ -41716,6 +41717,22 @@ package android.telecom {
    field public static final int REASON_USER_SET = 3; // 0x3
  }
  public final class QueryLocationException extends java.lang.RuntimeException implements android.os.Parcelable {
    ctor public QueryLocationException(@Nullable String);
    ctor public QueryLocationException(@Nullable String, int);
    ctor public QueryLocationException(@Nullable String, int, @Nullable Throwable);
    method public int describeContents();
    method public int getCode();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.telecom.QueryLocationException> CREATOR;
    field public static final int ERROR_NOT_ALLOWED_FOR_NON_EMERGENCY_CONNECTIONS = 4; // 0x4
    field public static final int ERROR_NOT_PERMITTED = 3; // 0x3
    field public static final int ERROR_PREVIOUS_REQUEST_EXISTS = 2; // 0x2
    field public static final int ERROR_REQUEST_TIME_OUT = 1; // 0x1
    field public static final int ERROR_SERVICE_UNAVAILABLE = 5; // 0x5
    field public static final int ERROR_UNSPECIFIED = 6; // 0x6
  }
  public final class RemoteConference {
    method public void disconnect();
    method public java.util.List<android.telecom.RemoteConnection> getConferenceableConnections();
+41 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.hardware.camera2.CameraManager;
import android.location.Location;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -1050,6 +1051,13 @@ public abstract class Connection extends Conferenceable {
    public static final String EXTRA_CALL_QUALITY_REPORT =
            "android.telecom.extra.CALL_QUALITY_REPORT";

    /**
     * Key to obtain location as a result of ({@code queryLocationForEmergency} from Bundle
     * @hide
     */
    public static final String EXTRA_KEY_QUERY_LOCATION =
            "android.telecom.extra.KEY_QUERY_LOCATION";

    // Flag controlling whether PII is emitted into the logs
    private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG);

@@ -1285,6 +1293,9 @@ public abstract class Connection extends Conferenceable {
        public void onConnectionTimeReset(Connection c) {}
        public void onEndpointChanged(Connection c, CallEndpoint endpoint, Executor executor,
                OutcomeReceiver<Void, CallEndpointException> callback) {}
        public void onQueryLocation(Connection c, long timeoutMillis, @NonNull String provider,
                @NonNull @CallbackExecutor Executor executor,
                @NonNull OutcomeReceiver<Location, QueryLocationException> callback) {}
    }

    /**
@@ -3232,6 +3243,36 @@ public abstract class Connection extends Conferenceable {
        mListeners.forEach((l) -> l.onRemoteRttRequest(Connection.this));
    }

    /**
     * Query the device's location in order to place an Emergency Call.
     * Only SIM call managers can call this method for Connections representing Emergency calls.
     * If a previous location query request is not completed, the new location query request will
     * be rejected and return a QueryLocationException with
     * {@code QueryLocationException#ERROR_PREVIOUS_REQUEST_EXISTS}
     *
     * @param timeoutMillis long: Timeout in millis waiting for query response (MAX:5000, MIN:100).
     * @param provider String: the location provider name, This value cannot be null.
     *                 It is the caller's responsibility to select an enabled provider. The caller
     *                 can use {@link android.location.LocationManager#getProviders(boolean)}
     *                 to choose one of the enabled providers and pass it in.
     * @param executor The executor of where the callback will execute.
     * @param callback The callback to notify the result of queryLocation.
     */
    public final void queryLocationForEmergency(
            @IntRange(from = 100, to = 5000) long timeoutMillis,
            @NonNull String provider,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OutcomeReceiver<Location, QueryLocationException> callback) {
        if (provider == null || executor == null || callback == null) {
            throw new IllegalArgumentException("There are arguments that must not be null");
        }
        if (timeoutMillis < 100 || timeoutMillis > 5000) {
            throw new IllegalArgumentException("The timeoutMillis should be min 100, max 5000");
        }
        mListeners.forEach((l) ->
                l.onQueryLocation(this, timeoutMillis, provider, executor, callback));
    }

    /**
     * Notifies this Connection that the {@link #getAudioState()} property has a new value.
     *
+12 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package android.telecom;

import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -25,6 +26,7 @@ import android.annotation.TestApi;
import android.app.Service;
import android.content.ComponentName;
import android.content.Intent;
import android.location.Location;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -2020,6 +2022,16 @@ public abstract class ConnectionService extends Service {
                mAdapter.requestCallEndpointChange(id, endpoint, executor, callback);
            }
        }

        @Override
        public void onQueryLocation(Connection c, long timeoutMillis, @NonNull String provider,
                @NonNull @CallbackExecutor Executor executor,
                @NonNull OutcomeReceiver<Location, QueryLocationException> callback) {
            String id = mIdByConnection.get(c);
            if (id != null) {
                mAdapter.queryLocation(id, timeoutMillis, provider, executor, callback);
            }
        }
    };

    /** {@inheritDoc} */
+44 −0
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package android.telecom;

import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.location.Location;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -748,4 +751,45 @@ final class ConnectionServiceAdapter implements DeathRecipient {
            }
        }
    }

    /**
     * Query location information.
     * Only SIM call managers can call this method for Connections representing Emergency calls.
     * If the previous request is not completed, the new request will be rejected.
     *
     * @param timeoutMillis long: Timeout in millis waiting for query response.
     * @param provider String: the location provider name, This value cannot be null.
     * @param executor The executor of where the callback will execute.
     * @param callback The callback to notify the result of queryLocation.
     */
    void queryLocation(String callId, long timeoutMillis, @NonNull String provider,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull OutcomeReceiver<Location, QueryLocationException> callback) {
        Log.v(this, "queryLocation: %s %d", callId, timeoutMillis);
        for (IConnectionServiceAdapter adapter : mAdapters) {
            try {
                adapter.queryLocation(callId, timeoutMillis, provider,
                        new ResultReceiver(null) {
                            @Override
                            protected void onReceiveResult(int resultCode, Bundle result) {
                                super.onReceiveResult(resultCode, result);

                                if (resultCode == 1 /* success */) {
                                    executor.execute(() -> callback.onResult(result.getParcelable(
                                            Connection.EXTRA_KEY_QUERY_LOCATION, Location.class)));
                                } else {
                                    executor.execute(() -> callback.onError(result.getParcelable(
                                            QueryLocationException.QUERY_LOCATION_ERROR,
                                            QueryLocationException.class)));
                                }
                            }
                        },
                        Log.getExternalSession());
            } catch (RemoteException e) {
                Log.d(this, "queryLocation: Exception e : " + e);
                executor.execute(() -> callback.onError(new QueryLocationException(
                        e.getMessage(), QueryLocationException.ERROR_SERVICE_UNAVAILABLE)));
            }
        }
    }
}
+25 −0
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@ final class ConnectionServiceAdapterServant {
    private static final int MSG_SET_CONFERENCE_STATE = 36;
    private static final int MSG_HANDLE_CREATE_CONFERENCE_COMPLETE = 37;
    private static final int MSG_SET_CALL_DIRECTION = 38;
    private static final int MSG_QUERY_LOCATION = 39;

    private final IConnectionServiceAdapter mDelegate;

@@ -373,6 +374,18 @@ final class ConnectionServiceAdapterServant {
                    } finally {
                        args.recycle();
                    }
                    break;
                }
                case MSG_QUERY_LOCATION: {
                    SomeArgs args = (SomeArgs) msg.obj;
                    try {
                        mDelegate.queryLocation((String) args.arg1, (long) args.arg2,
                                (String) args.arg3, (ResultReceiver) args.arg4,
                                (Session.Info) args.arg5);
                    } finally {
                        args.recycle();
                    }
                    break;
                }
            }
        }
@@ -699,6 +712,18 @@ final class ConnectionServiceAdapterServant {
                ResultReceiver callback, Session.Info sessionInfo) {
            // Do nothing
        }

        @Override
        public void queryLocation(String callId, long timeoutMillis, String provider,
                ResultReceiver callback, Session.Info sessionInfo) {
            SomeArgs args = SomeArgs.obtain();
            args.arg1 = callId;
            args.arg2 = timeoutMillis;
            args.arg3 = provider;
            args.arg4 = callback;
            args.arg5 = sessionInfo;
            mHandler.obtainMessage(MSG_QUERY_LOCATION, args).sendToTarget();
        }
    };

    public ConnectionServiceAdapterServant(IConnectionServiceAdapter delegate) {
Loading