diff --git a/api/current.txt b/api/current.txt index 31663115e9a78..38a9be8bf0e88 100644 --- a/api/current.txt +++ b/api/current.txt @@ -38532,9 +38532,9 @@ package android.telecom { method public final android.os.IBinder onBind(android.content.Intent); method public void onConference(android.telecom.Connection, android.telecom.Connection); method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); - method public void onCreateIncomingConnectionFailed(android.telecom.ConnectionRequest); + method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); - method public void onCreateOutgoingConnectionFailed(android.telecom.ConnectionRequest); + method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public void onRemoteConferenceAdded(android.telecom.RemoteConference); method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection); field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService"; diff --git a/api/system-current.txt b/api/system-current.txt index caf564dd13ae3..6d6b321fb8ce4 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -41675,9 +41675,9 @@ package android.telecom { method public final android.os.IBinder onBind(android.content.Intent); method public void onConference(android.telecom.Connection, android.telecom.Connection); method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); - method public void onCreateIncomingConnectionFailed(android.telecom.ConnectionRequest); + method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); - method public void onCreateOutgoingConnectionFailed(android.telecom.ConnectionRequest); + method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public void onRemoteConferenceAdded(android.telecom.RemoteConference); method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection); field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService"; diff --git a/api/test-current.txt b/api/test-current.txt index 35f6465e0e962..70eecded1e217 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -38717,9 +38717,9 @@ package android.telecom { method public final android.os.IBinder onBind(android.content.Intent); method public void onConference(android.telecom.Connection, android.telecom.Connection); method public android.telecom.Connection onCreateIncomingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); - method public void onCreateIncomingConnectionFailed(android.telecom.ConnectionRequest); + method public void onCreateIncomingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public android.telecom.Connection onCreateOutgoingConnection(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); - method public void onCreateOutgoingConnectionFailed(android.telecom.ConnectionRequest); + method public void onCreateOutgoingConnectionFailed(android.telecom.PhoneAccountHandle, android.telecom.ConnectionRequest); method public void onRemoteConferenceAdded(android.telecom.RemoteConference); method public void onRemoteExistingConnectionAdded(android.telecom.RemoteConnection); field public static final java.lang.String SERVICE_INTERFACE = "android.telecom.ConnectionService"; diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java index ca53dd15007b1..c79090203c0bb 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -1026,6 +1026,7 @@ public final class Call { private int mState; private List mCannedTextResponses = null; private String mCallingPackage; + private int mTargetSdkVersion; private String mRemainingPostDialSequence; private VideoCallImpl mVideoCallImpl; private RttCall mRttCall; @@ -1559,22 +1560,25 @@ public final class Call { } /** {@hide} */ - Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage) { + Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage, + int targetSdkVersion) { mPhone = phone; mTelecomCallId = telecomCallId; mInCallAdapter = inCallAdapter; mState = STATE_NEW; mCallingPackage = callingPackage; + mTargetSdkVersion = targetSdkVersion; } /** {@hide} */ Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state, - String callingPackage) { + String callingPackage, int targetSdkVersion) { mPhone = phone; mTelecomCallId = telecomCallId; mInCallAdapter = inCallAdapter; mState = state; mCallingPackage = callingPackage; + mTargetSdkVersion = targetSdkVersion; } /** {@hide} */ @@ -1600,7 +1604,8 @@ public final class Call { cannedTextResponsesChanged = true; } - VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage); + VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage, + mTargetSdkVersion); boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() && !Objects.equals(mVideoCallImpl, newVideoCallImpl); if (videoCallChanged) { diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index c2824f403fa9f..833affa379f34 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -24,6 +24,8 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.app.Notification; +import android.content.Intent; import android.hardware.camera2.CameraManager; import android.net.Uri; import android.os.Binder; @@ -1057,7 +1059,7 @@ public abstract class Connection extends Conferenceable { try { onSetCamera((String) args.arg1); onSetCamera((String) args.arg1, (String) args.arg2, args.argi1, - args.argi2); + args.argi2, args.argi3); } finally { args.recycle(); } @@ -1117,7 +1119,9 @@ public abstract class Connection extends Conferenceable { MSG_REMOVE_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget(); } - public void setCamera(String cameraId, String callingPackageName) { + public void setCamera(String cameraId, String callingPackageName, + int targetSdkVersion) { + SomeArgs args = SomeArgs.obtain(); args.arg1 = cameraId; // Propagate the calling package; originally determined in @@ -1129,6 +1133,9 @@ public abstract class Connection extends Conferenceable { // check to see if the calling app is able to use the camera. args.argi1 = Binder.getCallingUid(); args.argi2 = Binder.getCallingPid(); + // Pass along the target SDK version of the calling InCallService. This is used to + // maintain backwards compatibility of the API for older callers. + args.argi3 = targetSdkVersion; mMessageHandler.obtainMessage(MSG_SET_CAMERA, args).sendToTarget(); } @@ -1231,10 +1238,11 @@ public abstract class Connection extends Conferenceable { * @param callingPackageName The AppOpps package name of the caller. * @param callingUid The UID of the caller. * @param callingPid The PID of the caller. + * @param targetSdkVersion The target SDK version of the caller. * @hide */ public void onSetCamera(String cameraId, String callingPackageName, int callingUid, - int callingPid) {} + int callingPid, int targetSdkVersion) {} /** * Sets the surface to be used for displaying a preview of what the user's camera is @@ -2685,6 +2693,41 @@ public abstract class Connection extends Conferenceable { * regular {@link ConnectionService}, the Telecom framework will display its own incoming call * user interface to allow the user to choose whether to answer the new incoming call and * disconnect other ongoing calls, or to reject the new incoming call. + *

+ * You should trigger the display of the incoming call user interface for your application by + * showing a {@link Notification} with a full-screen {@link Intent} specified. + * For example: + *


+     *     // Create an intent which triggers your fullscreen incoming call user interface.
+     *     Intent intent = new Intent(Intent.ACTION_MAIN, null);
+     *     intent.setFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION | Intent.FLAG_ACTIVITY_NEW_TASK);
+     *     intent.setClass(context, YourIncomingCallActivity.class);
+     *     PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, 0);
+     *
+     *     // Build the notification as an ongoing high priority item; this ensures it will show as
+     *     // a heads up notification which slides down over top of the current content.
+     *     final Notification.Builder builder = new Notification.Builder(context);
+     *     builder.setOngoing(true);
+     *     builder.setPriority(Notification.PRIORITY_HIGH);
+     *
+     *     // Set notification content intent to take user to fullscreen UI if user taps on the
+     *     // notification body.
+     *     builder.setContentIntent(pendingIntent);
+     *     // Set full screen intent to trigger display of the fullscreen UI when the notification
+     *     // manager deems it appropriate.
+     *     builder.setFullScreenIntent(pendingIntent, true);
+     *
+     *     // Setup notification content.
+     *     builder.setSmallIcon( yourIconResourceId );
+     *     builder.setContentTitle("Your notification title");
+     *     builder.setContentText("Your notification content.");
+     *
+     *     // Use builder.addAction(..) to add buttons to answer or reject the call.
+     *
+     *     NotificationManager notificationManager = mContext.getSystemService(
+     *         NotificationManager.class);
+     *     notificationManager.notify(YOUR_TAG, YOUR_ID, builder.build());
+     * 
*/ public void onShowIncomingCallUi() {} diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java index 9bc77b81e3aa6..bf8f8e4e723e8 100644 --- a/telecomm/java/android/telecom/ConnectionService.java +++ b/telecomm/java/android/telecom/ConnectionService.java @@ -222,6 +222,7 @@ public abstract class ConnectionService extends Service { @Override public void createConnectionFailed( + PhoneAccountHandle connectionManagerPhoneAccount, String callId, ConnectionRequest request, boolean isIncoming, @@ -232,6 +233,7 @@ public abstract class ConnectionService extends Service { args.arg1 = callId; args.arg2 = request; args.arg3 = Log.createSubsession(); + args.arg4 = connectionManagerPhoneAccount; args.argi1 = isIncoming ? 1 : 0; mHandler.obtainMessage(MSG_CREATE_CONNECTION_FAILED, args).sendToTarget(); } finally { @@ -636,6 +638,8 @@ public abstract class ConnectionService extends Service { final String id = (String) args.arg1; final ConnectionRequest request = (ConnectionRequest) args.arg2; final boolean isIncoming = args.argi1 == 1; + final PhoneAccountHandle connectionMgrPhoneAccount = + (PhoneAccountHandle) args.arg4; if (!mAreAccountsInitialized) { Log.d(this, "Enqueueing pre-init request %s", id); mPreInitializationConnectionRequests.add( @@ -644,12 +648,14 @@ public abstract class ConnectionService extends Service { null /*lock*/) { @Override public void loggedRun() { - createConnectionFailed(id, request, isIncoming); + createConnectionFailed(connectionMgrPhoneAccount, id, + request, isIncoming); } }.prepare()); } else { Log.i(this, "createConnectionFailed %s", id); - createConnectionFailed(id, request, isIncoming); + createConnectionFailed(connectionMgrPhoneAccount, id, request, + isIncoming); } } finally { args.recycle(); @@ -1355,14 +1361,15 @@ public abstract class ConnectionService extends Service { } } - private void createConnectionFailed(final String callId, final ConnectionRequest request, - boolean isIncoming) { + private void createConnectionFailed(final PhoneAccountHandle callManagerAccount, + final String callId, final ConnectionRequest request, + boolean isIncoming) { Log.i(this, "createConnectionFailed %s", callId); if (isIncoming) { - onCreateIncomingConnectionFailed(request); + onCreateIncomingConnectionFailed(callManagerAccount, request); } else { - onCreateOutgoingConnectionFailed(request); + onCreateOutgoingConnectionFailed(callManagerAccount, request); } } @@ -1839,9 +1846,12 @@ public abstract class ConnectionService extends Service { *

* See {@link TelecomManager#isIncomingCallPermitted(PhoneAccountHandle)} for more information. * + * @param connectionManagerPhoneAccount See description at + * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}. * @param request The incoming connection request. */ - public void onCreateIncomingConnectionFailed(ConnectionRequest request) { + public void onCreateIncomingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount, + ConnectionRequest request) { } /** @@ -1855,9 +1865,12 @@ public abstract class ConnectionService extends Service { *

* See {@link TelecomManager#isOutgoingCallPermitted(PhoneAccountHandle)} for more information. * + * @param connectionManagerPhoneAccount See description at + * {@link #onCreateOutgoingConnection(PhoneAccountHandle, ConnectionRequest)}. * @param request The outgoing connection request. */ - public void onCreateOutgoingConnectionFailed(ConnectionRequest request) { + public void onCreateOutgoingConnectionFailed(PhoneAccountHandle connectionManagerPhoneAccount, + ConnectionRequest request) { } /** diff --git a/telecomm/java/android/telecom/InCallService.java b/telecomm/java/android/telecom/InCallService.java index 5d8f9f6d5a7bd..e384d4696ab00 100644 --- a/telecomm/java/android/telecom/InCallService.java +++ b/telecomm/java/android/telecom/InCallService.java @@ -90,7 +90,8 @@ public abstract class InCallService extends Service { switch (msg.what) { case MSG_SET_IN_CALL_ADAPTER: String callingPackage = getApplicationContext().getOpPackageName(); - mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage); + mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage, + getApplicationContext().getApplicationInfo().targetSdkVersion); mPhone.addListener(mPhoneListener); onPhoneCreated(mPhone); break; diff --git a/telecomm/java/android/telecom/ParcelableCall.java b/telecomm/java/android/telecom/ParcelableCall.java index 975aa5a332ca0..85a92d1a135ad 100644 --- a/telecomm/java/android/telecom/ParcelableCall.java +++ b/telecomm/java/android/telecom/ParcelableCall.java @@ -193,13 +193,16 @@ public final class ParcelableCall implements Parcelable { /** * Returns an object for remotely communicating through the video call provider's binder. - + * + * @param callingPackageName the package name of the calling InCallService. + * @param targetSdkVersion the target SDK version of the calling InCallService. * @return The video call. */ - public VideoCallImpl getVideoCallImpl(String callingPackageName) { + public VideoCallImpl getVideoCallImpl(String callingPackageName, int targetSdkVersion) { if (mVideoCall == null && mVideoCallProvider != null) { try { - mVideoCall = new VideoCallImpl(mVideoCallProvider, callingPackageName); + mVideoCall = new VideoCallImpl(mVideoCallProvider, callingPackageName, + targetSdkVersion); } catch (RemoteException ignored) { // Ignore RemoteException. } diff --git a/telecomm/java/android/telecom/Phone.java b/telecomm/java/android/telecom/Phone.java index db2abf30cf6db..066f6c26dd52a 100644 --- a/telecomm/java/android/telecom/Phone.java +++ b/telecomm/java/android/telecom/Phone.java @@ -127,14 +127,20 @@ public final class Phone { private final String mCallingPackage; - Phone(InCallAdapter adapter, String callingPackage) { + /** + * The Target SDK version of the InCallService implementation. + */ + private final int mTargetSdkVersion; + + Phone(InCallAdapter adapter, String callingPackage, int targetSdkVersion) { mInCallAdapter = adapter; mCallingPackage = callingPackage; + mTargetSdkVersion = targetSdkVersion; } final void internalAddCall(ParcelableCall parcelableCall) { Call call = new Call(this, parcelableCall.getId(), mInCallAdapter, - parcelableCall.getState(), mCallingPackage); + parcelableCall.getState(), mCallingPackage, mTargetSdkVersion); mCallByTelecomCallId.put(parcelableCall.getId(), call); mCalls.add(call); checkCallTree(parcelableCall); diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java index 1ca54c867dd78..57fc9ced91aea 100644 --- a/telecomm/java/android/telecom/RemoteConnection.java +++ b/telecomm/java/android/telecom/RemoteConnection.java @@ -446,6 +446,8 @@ public final class RemoteConnection { private final String mCallingPackage; + private final int mTargetSdkVersion; + /** * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is * load factor before resizing, 1 means we only expect a single thread to @@ -454,9 +456,12 @@ public final class RemoteConnection { private final Set mCallbacks = Collections.newSetFromMap( new ConcurrentHashMap(8, 0.9f, 1)); - VideoProvider(IVideoProvider videoProviderBinder, String callingPackage) { + VideoProvider(IVideoProvider videoProviderBinder, String callingPackage, + int targetSdkVersion) { + mVideoProviderBinder = videoProviderBinder; mCallingPackage = callingPackage; + mTargetSdkVersion = targetSdkVersion; try { mVideoProviderBinder.addVideoCallback(mVideoCallbackServant.getStub().asBinder()); } catch (RemoteException e) { @@ -491,7 +496,7 @@ public final class RemoteConnection { */ public void setCamera(String cameraId) { try { - mVideoProviderBinder.setCamera(cameraId, mCallingPackage); + mVideoProviderBinder.setCamera(cameraId, mCallingPackage, mTargetSdkVersion); } catch (RemoteException e) { } } @@ -667,7 +672,7 @@ public final class RemoteConnection { * @hide */ RemoteConnection(String callId, IConnectionService connectionService, - ParcelableConnection connection, String callingPackage) { + ParcelableConnection connection, String callingPackage, int targetSdkVersion) { mConnectionId = callId; mConnectionService = connectionService; mConnected = true; @@ -679,7 +684,8 @@ public final class RemoteConnection { mVideoState = connection.getVideoState(); IVideoProvider videoProvider = connection.getVideoProvider(); if (videoProvider != null) { - mVideoProvider = new RemoteConnection.VideoProvider(videoProvider, callingPackage); + mVideoProvider = new RemoteConnection.VideoProvider(videoProvider, callingPackage, + targetSdkVersion); } else { mVideoProvider = null; } diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java index ffba93a3edf82..06cdd1aa7c3c7 100644 --- a/telecomm/java/android/telecom/RemoteConnectionService.java +++ b/telecomm/java/android/telecom/RemoteConnectionService.java @@ -286,10 +286,11 @@ final class RemoteConnectionService { String callingPackage = mOurConnectionServiceImpl.getApplicationContext() .getOpPackageName(); + int targetSdkVersion = mOurConnectionServiceImpl.getApplicationInfo().targetSdkVersion; RemoteConnection.VideoProvider remoteVideoProvider = null; if (videoProvider != null) { remoteVideoProvider = new RemoteConnection.VideoProvider(videoProvider, - callingPackage); + callingPackage, targetSdkVersion); } findConnectionForAction(callId, "setVideoProvider") .setVideoProvider(remoteVideoProvider); @@ -357,8 +358,11 @@ final class RemoteConnectionService { Session.Info sessionInfo) { String callingPackage = mOurConnectionServiceImpl.getApplicationContext(). getOpPackageName(); + int callingTargetSdkVersion = mOurConnectionServiceImpl.getApplicationInfo() + .targetSdkVersion; RemoteConnection remoteConnection = new RemoteConnection(callId, - mOutgoingConnectionServiceRpc, connection, callingPackage); + mOutgoingConnectionServiceRpc, connection, callingPackage, + callingTargetSdkVersion); mConnectionById.put(callId, remoteConnection); remoteConnection.registerCallback(new RemoteConnection.Callback() { @Override diff --git a/telecomm/java/android/telecom/VideoCallImpl.java b/telecomm/java/android/telecom/VideoCallImpl.java index d8ede5c213164..429a434992c56 100644 --- a/telecomm/java/android/telecom/VideoCallImpl.java +++ b/telecomm/java/android/telecom/VideoCallImpl.java @@ -44,6 +44,7 @@ public class VideoCallImpl extends VideoCall { private int mVideoQuality = VideoProfile.QUALITY_UNKNOWN; private int mVideoState = VideoProfile.STATE_AUDIO_ONLY; private final String mCallingPackageName; + private final int mTargetSdkVersion; private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { @Override @@ -198,13 +199,15 @@ public class VideoCallImpl extends VideoCall { private Handler mHandler; - VideoCallImpl(IVideoProvider videoProvider, String callingPackageName) throws RemoteException { + VideoCallImpl(IVideoProvider videoProvider, String callingPackageName, int targetSdkVersion) + throws RemoteException { mVideoProvider = videoProvider; mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0); mBinder = new VideoCallListenerBinder(); mVideoProvider.addVideoCallback(mBinder); mCallingPackageName = callingPackageName; + mTargetSdkVersion = targetSdkVersion; } public void destroy() { @@ -243,7 +246,7 @@ public class VideoCallImpl extends VideoCall { public void setCamera(String cameraId) { try { Log.w(this, "setCamera: cameraId=%s, calling=%s", cameraId, mCallingPackageName); - mVideoProvider.setCamera(cameraId, mCallingPackageName); + mVideoProvider.setCamera(cameraId, mCallingPackageName, mTargetSdkVersion); } catch (RemoteException e) { } } diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl index 114949ee284a0..c631d085f6e7a 100644 --- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl +++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl @@ -47,8 +47,8 @@ oneway interface IConnectionService { boolean isUnknown, in Session.Info sessionInfo); - void createConnectionFailed(String callId, in ConnectionRequest request, boolean isIncoming, - in Session.Info sessionInfo); + void createConnectionFailed(in PhoneAccountHandle connectionManagerPhoneAccount, String callId, + in ConnectionRequest request, boolean isIncoming, in Session.Info sessionInfo); void abort(String callId, in Session.Info sessionInfo); diff --git a/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl b/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl index a109e90243fe9..272b884bd2007 100644 --- a/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl +++ b/telecomm/java/com/android/internal/telecom/IVideoProvider.aidl @@ -30,7 +30,7 @@ oneway interface IVideoProvider { void removeVideoCallback(IBinder videoCallbackBinder); - void setCamera(String cameraId, in String mCallingPackageName); + void setCamera(String cameraId, in String mCallingPackageName, int targetSdkVersion); void setPreviewSurface(in Surface surface);