Merge "Location Query for OTT Emergency Calls (frameworks)"
This commit is contained in:
committed by
Android (Google) Code Review
commit
b796b9e479
@@ -41609,6 +41609,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);
|
||||
@@ -42012,6 +42013,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();
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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} */
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
22
telecomm/java/android/telecom/QueryLocationException.aidl
Normal file
22
telecomm/java/android/telecom/QueryLocationException.aidl
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2022, 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.telecom;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
parcelable QueryLocationException;
|
||||
129
telecomm/java/android/telecom/QueryLocationException.java
Normal file
129
telecomm/java/android/telecom/QueryLocationException.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.telecom;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.OutcomeReceiver;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* This class represents a set of exceptions that can occur when requesting a
|
||||
* {@link Connection#queryLocationForEmergency(long, String, Executor, OutcomeReceiver)}
|
||||
*/
|
||||
public final class QueryLocationException extends RuntimeException implements Parcelable {
|
||||
/** @hide */
|
||||
public static final String QUERY_LOCATION_ERROR = "QueryLocationErrorKey";
|
||||
|
||||
/**
|
||||
* The operation was not completed on time.
|
||||
*/
|
||||
public static final int ERROR_REQUEST_TIME_OUT = 1;
|
||||
/**
|
||||
* The operation was rejected due to an existing request.
|
||||
*/
|
||||
public static final int ERROR_PREVIOUS_REQUEST_EXISTS = 2;
|
||||
/**
|
||||
* The operation has failed because it is not permitted.
|
||||
*/
|
||||
public static final int ERROR_NOT_PERMITTED = 3;
|
||||
/**
|
||||
* The operation has failed due to a location query being requested for a non-emergency
|
||||
* connection.
|
||||
*/
|
||||
public static final int ERROR_NOT_ALLOWED_FOR_NON_EMERGENCY_CONNECTIONS = 4;
|
||||
/**
|
||||
* The operation has failed due to the service is not available.
|
||||
*/
|
||||
public static final int ERROR_SERVICE_UNAVAILABLE = 5;
|
||||
/**
|
||||
* The operation has failed due to an unknown or unspecified error.
|
||||
*/
|
||||
public static final int ERROR_UNSPECIFIED = 6;
|
||||
|
||||
private int mCode = ERROR_UNSPECIFIED;
|
||||
private final String mMessage;
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeString8(mMessage);
|
||||
dest.writeInt(mCode);
|
||||
}
|
||||
/**
|
||||
* Responsible for creating QueryLocationException objects for deserialized Parcels.
|
||||
*/
|
||||
public static final
|
||||
@android.annotation.NonNull Parcelable.Creator<QueryLocationException> CREATOR =
|
||||
new Parcelable.Creator<>() {
|
||||
@Override
|
||||
public QueryLocationException createFromParcel(Parcel source) {
|
||||
return new QueryLocationException(source.readString8(), source.readInt());
|
||||
}
|
||||
@Override
|
||||
public QueryLocationException[] newArray(int size) {
|
||||
return new QueryLocationException[size];
|
||||
}
|
||||
};
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({ERROR_REQUEST_TIME_OUT,
|
||||
ERROR_PREVIOUS_REQUEST_EXISTS,
|
||||
ERROR_NOT_PERMITTED,
|
||||
ERROR_NOT_ALLOWED_FOR_NON_EMERGENCY_CONNECTIONS,
|
||||
ERROR_SERVICE_UNAVAILABLE,
|
||||
ERROR_UNSPECIFIED})
|
||||
public @interface QueryLocationErrorCode {}
|
||||
public QueryLocationException(@Nullable String message) {
|
||||
super(getMessage(message, ERROR_UNSPECIFIED));
|
||||
mMessage = message;
|
||||
}
|
||||
public QueryLocationException(@Nullable String message, @QueryLocationErrorCode int code) {
|
||||
super(getMessage(message, code));
|
||||
mCode = code;
|
||||
mMessage = message;
|
||||
}
|
||||
public QueryLocationException(
|
||||
@Nullable String message, @QueryLocationErrorCode int code, @Nullable Throwable cause) {
|
||||
super(getMessage(message, code), cause);
|
||||
mCode = code;
|
||||
mMessage = message;
|
||||
}
|
||||
public @QueryLocationErrorCode int getCode() {
|
||||
return mCode;
|
||||
}
|
||||
private static String getMessage(String message, int code) {
|
||||
StringBuilder builder;
|
||||
if (!TextUtils.isEmpty(message)) {
|
||||
builder = new StringBuilder(message);
|
||||
builder.append(" (code: ");
|
||||
builder.append(code);
|
||||
builder.append(")");
|
||||
return builder.toString();
|
||||
} else {
|
||||
return "code: " + code;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -517,6 +517,12 @@ final class RemoteConnectionService {
|
||||
ResultReceiver callback, Session.Info sessionInfo) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryLocation(String callId, long timeoutMillis, String provider,
|
||||
ResultReceiver callback, Session.Info sessionInfo) {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
|
||||
private final ConnectionServiceAdapterServant mServant =
|
||||
|
||||
@@ -139,4 +139,7 @@ oneway interface IConnectionServiceAdapter {
|
||||
void setConferenceState(String callId, boolean isConference, in Session.Info sessionInfo);
|
||||
|
||||
void setCallDirection(String callId, int direction, in Session.Info sessionInfo);
|
||||
|
||||
void queryLocation(String callId, long timeoutMillis, String provider,
|
||||
in ResultReceiver callback, in Session.Info sessionInfo);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user