Merge "Add handover permission, fill in some missing API gaps."

am: 1dfa830bb0

Change-Id: Ie07c7031c1411b59bbcd250be9517eda51b58310
This commit is contained in:
Tyler Gunn
2018-01-30 19:32:32 +00:00
committed by android-build-merger
13 changed files with 156 additions and 11 deletions

View File

@@ -6,6 +6,7 @@ package android {
public static final class Manifest.permission {
ctor public Manifest.permission();
field public static final java.lang.String ACCEPT_HANDOVER = "android.permission.ACCEPT_HANDOVER";
field public static final java.lang.String ACCESS_CHECKIN_PROPERTIES = "android.permission.ACCESS_CHECKIN_PROPERTIES";
field public static final java.lang.String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
field public static final java.lang.String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
@@ -39381,6 +39382,7 @@ package android.telecom {
method public void onCallEvent(java.lang.String, android.os.Bundle);
method public void onDisconnect();
method public void onExtrasChanged(android.os.Bundle);
method public void onHandoverComplete();
method public void onHold();
method public void onPlayDtmfTone(char);
method public void onPostDialContinue(boolean);

View File

@@ -252,8 +252,10 @@ public class AppOpsManager {
public static final int OP_INSTANT_APP_START_FOREGROUND = 68;
/** @hide Answer incoming phone calls */
public static final int OP_ANSWER_PHONE_CALLS = 69;
/** @hide Continue handover of a call from another app */
public static final int OP_ACCEPT_HANDOVER = 70;
/** @hide */
public static final int _NUM_OP = 70;
public static final int _NUM_OP = 71;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -365,6 +367,12 @@ public class AppOpsManager {
/** Answer incoming phone calls */
public static final String OPSTR_ANSWER_PHONE_CALLS
= "android:answer_phone_calls";
/***
* Accept call handover
* @hide
*/
public static final String OPSTR_ACCEPT_HANDOVER
= "android:accept_handover";
// Warning: If an permission is added here it also has to be added to
// com.android.packageinstaller.permission.utils.EventLogger
@@ -400,6 +408,7 @@ public class AppOpsManager {
OP_USE_SIP,
OP_PROCESS_OUTGOING_CALLS,
OP_ANSWER_PHONE_CALLS,
OP_ACCEPT_HANDOVER,
// Microphone
OP_RECORD_AUDIO,
// Camera
@@ -492,7 +501,8 @@ public class AppOpsManager {
OP_REQUEST_INSTALL_PACKAGES,
OP_PICTURE_IN_PICTURE,
OP_INSTANT_APP_START_FOREGROUND,
OP_ANSWER_PHONE_CALLS
OP_ANSWER_PHONE_CALLS,
OP_ACCEPT_HANDOVER
};
/**
@@ -570,6 +580,7 @@ public class AppOpsManager {
OPSTR_PICTURE_IN_PICTURE,
OPSTR_INSTANT_APP_START_FOREGROUND,
OPSTR_ANSWER_PHONE_CALLS,
OPSTR_ACCEPT_HANDOVER
};
/**
@@ -647,6 +658,7 @@ public class AppOpsManager {
"PICTURE_IN_PICTURE",
"INSTANT_APP_START_FOREGROUND",
"ANSWER_PHONE_CALLS",
"ACCEPT_HANDOVER"
};
/**
@@ -724,6 +736,7 @@ public class AppOpsManager {
null, // no permission for entering picture-in-picture on hide
Manifest.permission.INSTANT_APP_FOREGROUND_SERVICE,
Manifest.permission.ANSWER_PHONE_CALLS,
Manifest.permission.ACCEPT_HANDOVER
};
/**
@@ -802,6 +815,7 @@ public class AppOpsManager {
null, // ENTER_PICTURE_IN_PICTURE_ON_HIDE
null, // INSTANT_APP_START_FOREGROUND
null, // ANSWER_PHONE_CALLS
null, // ACCEPT_HANDOVER
};
/**
@@ -879,6 +893,7 @@ public class AppOpsManager {
false, // ENTER_PICTURE_IN_PICTURE_ON_HIDE
false, // INSTANT_APP_START_FOREGROUND
false, // ANSWER_PHONE_CALLS
false, // ACCEPT_HANDOVER
};
/**
@@ -955,6 +970,7 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED, // OP_PICTURE_IN_PICTURE
AppOpsManager.MODE_DEFAULT, // OP_INSTANT_APP_START_FOREGROUND
AppOpsManager.MODE_ALLOWED, // ANSWER_PHONE_CALLS
AppOpsManager.MODE_ALLOWED, // ACCEPT_HANDOVER
};
/**
@@ -1035,6 +1051,7 @@ public class AppOpsManager {
false, // OP_PICTURE_IN_PICTURE
false,
false, // ANSWER_PHONE_CALLS
false, // ACCEPT_HANDOVER
};
/**

View File

@@ -950,6 +950,23 @@
android:description="@string/permdesc_manageOwnCalls"
android:protectionLevel="normal" />
<!-- Allows a calling app to continue a call which was started in another app. An example is a
video calling app that wants to continue a voice call on the user's mobile network.<p>
When the handover of a call from one app to another takes place, there are two devices
which are involved in the handover; the initiating and receiving devices. The initiating
device is where the request to handover the call was started, and the receiving device is
where the handover request is confirmed by the other party.<p>
This permission protects access to
{@link android.telecom.TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, which
the receiving side of the handover uses to accept a handover.
<p>Protection level: dangerous
-->
<permission android:name="android.permission.ACCEPT_HANDOVER"
android:permissionGroup="android.permission-group.PHONE"
android.label="@string/permlab_acceptHandover"
android:description="@string/permdesc_acceptHandover"
android:protectionLevel="dangerous" />
<!-- ====================================================================== -->
<!-- Permissions for accessing the device microphone -->
<!-- ====================================================================== -->

View File

@@ -1076,6 +1076,17 @@
<string name="permdesc_manageOwnCalls">Allows the app to route its calls through the system in
order to improve the calling experience.</string>
<!-- Title of an application permission. When granted to a third party app, the user is giving
access to the app to continue a call which originated in another app. For example, the
user could be in a voice call over their carrier's mobile network, and a third party video
calling app wants to continue that voice call as a video call. -->
<string name="permlab_acceptHandover">continue a call from another app</string>
<!-- Description of an application permission. When granted to a third party app, the user is
giving access to the app to continue a call which originated in another app. For example,
the user could be in a voice call over their carrier's mobile network, and a third party
video calling app wants to continue that voice call as a video call. -->
<string name="permdesc_acceptHandover">Allows the app to continue a call which was started in another app.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permlab_readPhoneNumbers">read phone numbers</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->

View File

@@ -611,7 +611,8 @@ public class PackageManagerService extends IPackageManager.Stub
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_NUMBERS,
Manifest.permission.ANSWER_PHONE_CALLS);
Manifest.permission.ANSWER_PHONE_CALLS,
Manifest.permission.ACCEPT_HANDOVER);
/**

View File

@@ -1961,6 +1961,15 @@ public final class Call {
}
}
/** {@hide} */
final void internalOnHandoverComplete() {
for (CallbackRecord<Callback> record : mCallbackRecords) {
final Call call = this;
final Callback callback = record.getCallback();
record.getHandler().post(() -> callback.onHandoverComplete(call));
}
}
private void fireStateChanged(final int newState) {
for (CallbackRecord<Callback> record : mCallbackRecords) {
final Call call = this;

View File

@@ -2799,6 +2799,15 @@ public abstract class Connection extends Conferenceable {
*/
public void onCallEvent(String event, Bundle extras) {}
/**
* Notifies this {@link Connection} that a handover has completed.
* <p>
* A handover is initiated with {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int,
* Bundle)} on the initiating side of the handover, and on the receiving side with
* {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}.
*/
public void onHandoverComplete() {}
/**
* Notifies this {@link Connection} of a change to the extras made outside the
* {@link ConnectionService}.

View File

@@ -140,6 +140,7 @@ public abstract class ConnectionService extends Service {
private static final String SESSION_POST_DIAL_CONT = "CS.oPDC";
private static final String SESSION_PULL_EXTERNAL_CALL = "CS.pEC";
private static final String SESSION_SEND_CALL_EVENT = "CS.sCE";
private static final String SESSION_HANDOVER_COMPLETE = "CS.hC";
private static final String SESSION_EXTRAS_CHANGED = "CS.oEC";
private static final String SESSION_START_RTT = "CS.+RTT";
private static final String SESSION_STOP_RTT = "CS.-RTT";
@@ -179,6 +180,7 @@ public abstract class ConnectionService extends Service {
private static final int MSG_CONNECTION_SERVICE_FOCUS_LOST = 30;
private static final int MSG_CONNECTION_SERVICE_FOCUS_GAINED = 31;
private static final int MSG_HANDOVER_FAILED = 32;
private static final int MSG_HANDOVER_COMPLETE = 33;
private static Connection sNullConnection;
@@ -297,6 +299,19 @@ public abstract class ConnectionService extends Service {
}
}
@Override
public void handoverComplete(String callId, Session.Info sessionInfo) {
Log.startSession(sessionInfo, SESSION_HANDOVER_COMPLETE);
try {
SomeArgs args = SomeArgs.obtain();
args.arg1 = callId;
args.arg2 = Log.createSubsession();
mHandler.obtainMessage(MSG_HANDOVER_COMPLETE, args).sendToTarget();
} finally {
Log.endSession();
}
}
@Override
public void abort(String callId, Session.Info sessionInfo) {
Log.startSession(sessionInfo, SESSION_ABORT);
@@ -1028,6 +1043,19 @@ public abstract class ConnectionService extends Service {
}
break;
}
case MSG_HANDOVER_COMPLETE: {
SomeArgs args = (SomeArgs) msg.obj;
try {
Log.continueSession((Session) args.arg2,
SESSION_HANDLER + SESSION_HANDOVER_COMPLETE);
String callId = (String) args.arg1;
notifyHandoverComplete(callId);
} finally {
args.recycle();
Log.endSession();
}
break;
}
case MSG_ON_EXTRAS_CHANGED: {
SomeArgs args = (SomeArgs) msg.obj;
try {
@@ -1445,19 +1473,24 @@ public abstract class ConnectionService extends Service {
final ConnectionRequest request,
boolean isIncoming,
boolean isUnknown) {
boolean isLegacyHandover = request.getExtras() != null &&
request.getExtras().getBoolean(TelecomManager.EXTRA_IS_HANDOVER, false);
boolean isHandover = request.getExtras() != null && request.getExtras().getBoolean(
TelecomManager.EXTRA_IS_HANDOVER_CONNECTION, false);
Log.d(this, "createConnection, callManagerAccount: %s, callId: %s, request: %s, " +
"isIncoming: %b, isUnknown: %b", callManagerAccount, callId, request,
isIncoming,
isUnknown);
"isIncoming: %b, isUnknown: %b, isLegacyHandover: %b, isHandover: %b",
callManagerAccount, callId, request, isIncoming, isUnknown, isLegacyHandover,
isHandover);
Connection connection = null;
if (getApplicationContext().getApplicationInfo().targetSdkVersion >
Build.VERSION_CODES.O_MR1 && request.getExtras() != null &&
request.getExtras().getBoolean(TelecomManager.EXTRA_IS_HANDOVER,false)) {
if (isHandover) {
PhoneAccountHandle fromPhoneAccountHandle = request.getExtras() != null
? (PhoneAccountHandle) request.getExtras().getParcelable(
TelecomManager.EXTRA_HANDOVER_FROM_PHONE_ACCOUNT) : null;
if (!isIncoming) {
connection = onCreateOutgoingHandoverConnection(callManagerAccount, request);
connection = onCreateOutgoingHandoverConnection(fromPhoneAccountHandle, request);
} else {
connection = onCreateIncomingHandoverConnection(callManagerAccount, request);
connection = onCreateIncomingHandoverConnection(fromPhoneAccountHandle, request);
}
} else {
connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
@@ -1753,6 +1786,19 @@ public abstract class ConnectionService extends Service {
}
}
/**
* Notifies a {@link Connection} that a handover has completed.
*
* @param callId The ID of the call which completed handover.
*/
private void notifyHandoverComplete(String callId) {
Log.d(this, "notifyHandoverComplete(%s)", callId);
Connection connection = findConnectionForAction(callId, "notifyHandoverComplete");
if (connection != null) {
connection.onHandoverComplete();
}
}
/**
* Notifies a {@link Connection} or {@link Conference} of a change to the extras from Telecom.
* <p>

View File

@@ -81,6 +81,7 @@ public abstract class InCallService extends Service {
private static final int MSG_ON_RTT_UPGRADE_REQUEST = 10;
private static final int MSG_ON_RTT_INITIATION_FAILURE = 11;
private static final int MSG_ON_HANDOVER_FAILED = 12;
private static final int MSG_ON_HANDOVER_COMPLETE = 13;
/** Default Handler used to consolidate binder method calls onto a single thread. */
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -157,6 +158,11 @@ public abstract class InCallService extends Service {
mPhone.internalOnHandoverFailed(callId, error);
break;
}
case MSG_ON_HANDOVER_COMPLETE: {
String callId = (String) msg.obj;
mPhone.internalOnHandoverComplete(callId);
break;
}
default:
break;
}
@@ -237,6 +243,11 @@ public abstract class InCallService extends Service {
public void onHandoverFailed(String callId, int error) {
mHandler.obtainMessage(MSG_ON_HANDOVER_FAILED, error, 0, callId).sendToTarget();
}
@Override
public void onHandoverComplete(String callId) {
mHandler.obtainMessage(MSG_ON_HANDOVER_COMPLETE, callId).sendToTarget();
}
}
private Phone.Listener mPhoneListener = new Phone.Listener() {

View File

@@ -230,6 +230,13 @@ public final class Phone {
}
}
final void internalOnHandoverComplete(String callId) {
Call call = mCallByTelecomCallId.get(callId);
if (call != null) {
call.internalOnHandoverComplete();
}
}
/**
* Called to destroy the phone and cleanup any lingering calls.
*/

View File

@@ -378,6 +378,17 @@ public class TelecomManager {
*/
public static final String EXTRA_IS_HANDOVER = "android.telecom.extra.IS_HANDOVER";
/**
* When {@code true} indicates that a request to create a new connection is for the purpose of
* a handover. Note: This is used with the
* {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)} API as part of the
* internal communication mechanism with the {@link android.telecom.ConnectionService}. It is
* not the same as the legacy {@link #EXTRA_IS_HANDOVER} extra.
* @hide
*/
public static final String EXTRA_IS_HANDOVER_CONNECTION =
"android.telecom.extra.IS_HANDOVER_CONNECTION";
/**
* Parcelable extra used with {@link #EXTRA_IS_HANDOVER} to indicate the source
* {@link PhoneAccountHandle} when initiating a handover which {@link ConnectionService}

View File

@@ -104,6 +104,8 @@ oneway interface IConnectionService {
void handoverFailed(String callId, in ConnectionRequest request,
int error, in Session.Info sessionInfo);
void handoverComplete(String callId, in Session.Info sessionInfo);
void connectionServiceFocusLost(in Session.Info sessionInfo);
void connectionServiceFocusGained(in Session.Info sessionInfo);

View File

@@ -56,4 +56,6 @@ oneway interface IInCallService {
void onRttInitiationFailure(String callId, int reason);
void onHandoverFailed(String callId, int error);
void onHandoverComplete(String callId);
}