Merge "Perform camera permission and app ops check when setting camera for VT."

This commit is contained in:
Brad Ebinger
2017-02-07 22:26:43 +00:00
committed by Gerrit Code Review
12 changed files with 107 additions and 25 deletions

View File

@@ -36655,6 +36655,7 @@ package android.telecom {
method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
method public void setCallDataUsage(long);
field public static final int SESSION_EVENT_CAMERA_FAILURE = 5; // 0x5
field public static final int SESSION_EVENT_CAMERA_PERMISSION_ERROR = 7; // 0x7
field public static final int SESSION_EVENT_CAMERA_READY = 6; // 0x6
field public static final int SESSION_EVENT_RX_PAUSE = 1; // 0x1
field public static final int SESSION_EVENT_RX_RESUME = 2; // 0x2

View File

@@ -39635,6 +39635,7 @@ package android.telecom {
method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
method public void setCallDataUsage(long);
field public static final int SESSION_EVENT_CAMERA_FAILURE = 5; // 0x5
field public static final int SESSION_EVENT_CAMERA_PERMISSION_ERROR = 7; // 0x7
field public static final int SESSION_EVENT_CAMERA_READY = 6; // 0x6
field public static final int SESSION_EVENT_RX_PAUSE = 1; // 0x1
field public static final int SESSION_EVENT_RX_RESUME = 2; // 0x2

View File

@@ -36737,6 +36737,7 @@ package android.telecom {
method public void receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile);
method public void setCallDataUsage(long);
field public static final int SESSION_EVENT_CAMERA_FAILURE = 5; // 0x5
field public static final int SESSION_EVENT_CAMERA_PERMISSION_ERROR = 7; // 0x7
field public static final int SESSION_EVENT_CAMERA_READY = 6; // 0x6
field public static final int SESSION_EVENT_RX_PAUSE = 1; // 0x1
field public static final int SESSION_EVENT_RX_RESUME = 2; // 0x2

View File

@@ -853,6 +853,7 @@ public final class Call {
private String mParentId = null;
private int mState;
private List<String> mCannedTextResponses = null;
private String mCallingPackage;
private String mRemainingPostDialSequence;
private VideoCallImpl mVideoCallImpl;
private Details mDetails;
@@ -1340,19 +1341,22 @@ public final class Call {
}
/** {@hide} */
Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter) {
Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, String callingPackage) {
mPhone = phone;
mTelecomCallId = telecomCallId;
mInCallAdapter = inCallAdapter;
mState = STATE_NEW;
mCallingPackage = callingPackage;
}
/** {@hide} */
Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state) {
Call(Phone phone, String telecomCallId, InCallAdapter inCallAdapter, int state,
String callingPackage) {
mPhone = phone;
mTelecomCallId = telecomCallId;
mInCallAdapter = inCallAdapter;
mState = state;
mCallingPackage = callingPackage;
}
/** {@hide} */
@@ -1362,6 +1366,7 @@ public final class Call {
/** {@hide} */
final void internalUpdate(ParcelableCall parcelableCall, Map<String, Call> callIdMap) {
// First, we update the internal state as far as possible before firing any updates.
Details details = Details.createFromParcelableCall(parcelableCall);
boolean detailsChanged = !Objects.equals(mDetails, details);
@@ -1377,7 +1382,7 @@ public final class Call {
cannedTextResponsesChanged = true;
}
VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl();
VideoCallImpl newVideoCallImpl = parcelableCall.getVideoCallImpl(mCallingPackage);
boolean videoCallChanged = parcelableCall.isVideoCallProviderChanged() &&
!Objects.equals(mVideoCallImpl, newVideoCallImpl);
if (videoCallChanged) {

View File

@@ -25,6 +25,7 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.hardware.camera2.CameraManager;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -799,7 +800,7 @@ public abstract class Connection extends Conferenceable {
public static final int SESSION_EVENT_TX_STOP = 4;
/**
* A camera failure has occurred for the selected camera. The {@link InCallService} can use
* A camera failure has occurred for the selected camera. The {@link VideoProvider} can use
* this as a cue to inform the user the camera is not available.
* @see #handleCallSessionEvent(int)
*/
@@ -807,12 +808,20 @@ public abstract class Connection extends Conferenceable {
/**
* Issued after {@link #SESSION_EVENT_CAMERA_FAILURE} when the camera is once again ready
* for operation. The {@link InCallService} can use this as a cue to inform the user that
* for operation. The {@link VideoProvider} can use this as a cue to inform the user that
* the camera has become available again.
* @see #handleCallSessionEvent(int)
*/
public static final int SESSION_EVENT_CAMERA_READY = 6;
/**
* Session event raised by Telecom when
* {@link android.telecom.InCallService.VideoCall#setCamera(String)} is called and the
* caller does not have the necessary {@link android.Manifest.permission#CAMERA} permission.
* @see #handleCallSessionEvent(int)
*/
public static final int SESSION_EVENT_CAMERA_PERMISSION_ERROR = 7;
/**
* Session modify request was successful.
* @see #receiveSessionModifyResponse(int, VideoProfile, VideoProfile)
@@ -862,6 +871,8 @@ public abstract class Connection extends Conferenceable {
private static final String SESSION_EVENT_TX_STOP_STR = "TX_STOP";
private static final String SESSION_EVENT_CAMERA_FAILURE_STR = "CAMERA_FAIL";
private static final String SESSION_EVENT_CAMERA_READY_STR = "CAMERA_READY";
private static final String SESSION_EVENT_CAMERA_PERMISSION_ERROR_STR =
"CAMERA_PERMISSION_ERROR";
private static final String SESSION_EVENT_UNKNOWN_STR = "UNKNOWN";
private VideoProvider.VideoProviderHandler mMessageHandler;
@@ -920,8 +931,17 @@ public abstract class Connection extends Conferenceable {
break;
}
case MSG_SET_CAMERA:
onSetCamera((String) msg.obj);
break;
{
SomeArgs args = (SomeArgs) msg.obj;
try {
onSetCamera((String) args.arg1);
onSetCamera((String) args.arg1, (String) args.arg2, args.argi1,
args.argi2);
} finally {
args.recycle();
}
}
break;
case MSG_SET_PREVIEW_SURFACE:
onSetPreviewSurface((Surface) msg.obj);
break;
@@ -976,8 +996,19 @@ public abstract class Connection extends Conferenceable {
MSG_REMOVE_VIDEO_CALLBACK, videoCallbackBinder).sendToTarget();
}
public void setCamera(String cameraId) {
mMessageHandler.obtainMessage(MSG_SET_CAMERA, cameraId).sendToTarget();
public void setCamera(String cameraId, String callingPackageName) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = cameraId;
// Propagate the calling package; originally determined in
// android.telecom.InCallService.VideoCall#setCamera(String) from the calling
// process.
args.arg2 = callingPackageName;
// Pass along the uid and pid of the calling app; this gets lost when we put the
// message onto the handler. These are required for Telecom to perform a permission
// check to see if the calling app is able to use the camera.
args.argi1 = Binder.getCallingUid();
args.argi2 = Binder.getCallingPid();
mMessageHandler.obtainMessage(MSG_SET_CAMERA, args).sendToTarget();
}
public void setPreviewSurface(Surface surface) {
@@ -1061,6 +1092,29 @@ public abstract class Connection extends Conferenceable {
*/
public abstract void onSetCamera(String cameraId);
/**
* Sets the camera to be used for the outgoing video.
* <p>
* The {@link VideoProvider} should respond by communicating the capabilities of the chosen
* camera via
* {@link VideoProvider#changeCameraCapabilities(VideoProfile.CameraCapabilities)}.
* <p>
* This prototype is used internally to ensure that the calling package name, UID and PID
* are sent to Telecom so that can perform a camera permission check on the caller.
* <p>
* Sent from the {@link InCallService} via
* {@link InCallService.VideoCall#setCamera(String)}.
*
* @param cameraId The id of the camera (use ids as reported by
* {@link CameraManager#getCameraIdList()}).
* @param callingPackageName The AppOpps package name of the caller.
* @param callingUid The UID of the caller.
* @param callingPid The PID of the caller.
* @hide
*/
public void onSetCamera(String cameraId, String callingPackageName, int callingUid,
int callingPid) {}
/**
* Sets the surface to be used for displaying a preview of what the user's camera is
* currently capturing. When video transmission is enabled, this is the video signal which
@@ -1247,7 +1301,8 @@ public abstract class Connection extends Conferenceable {
* {@link VideoProvider#SESSION_EVENT_TX_START},
* {@link VideoProvider#SESSION_EVENT_TX_STOP},
* {@link VideoProvider#SESSION_EVENT_CAMERA_FAILURE},
* {@link VideoProvider#SESSION_EVENT_CAMERA_READY}.
* {@link VideoProvider#SESSION_EVENT_CAMERA_READY},
* {@link VideoProvider#SESSION_EVENT_CAMERA_FAILURE}.
*/
public void handleCallSessionEvent(int event) {
if (mVideoCallbacks != null) {
@@ -1396,6 +1451,8 @@ public abstract class Connection extends Conferenceable {
return SESSION_EVENT_TX_START_STR;
case SESSION_EVENT_TX_STOP:
return SESSION_EVENT_TX_STOP_STR;
case SESSION_EVENT_CAMERA_PERMISSION_ERROR:
return SESSION_EVENT_CAMERA_PERMISSION_ERROR_STR;
default:
return SESSION_EVENT_UNKNOWN_STR + " " + event;
}

View File

@@ -87,7 +87,8 @@ public abstract class InCallService extends Service {
switch (msg.what) {
case MSG_SET_IN_CALL_ADAPTER:
mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));
String callingPackage = getApplicationContext().getOpPackageName();
mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage);
mPhone.addListener(mPhoneListener);
onPhoneCreated(mPhone);
break;
@@ -664,7 +665,8 @@ public abstract class InCallService extends Service {
* {@link Connection.VideoProvider#SESSION_EVENT_TX_START},
* {@link Connection.VideoProvider#SESSION_EVENT_TX_STOP},
* {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_FAILURE},
* {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_READY}.
* {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_READY},
* {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_PERMISSION_ERROR}.
*/
public abstract void onCallSessionEvent(int event);

View File

@@ -190,10 +190,10 @@ public final class ParcelableCall implements Parcelable {
* @return The video call.
*/
public VideoCallImpl getVideoCallImpl() {
public VideoCallImpl getVideoCallImpl(String callingPackageName) {
if (mVideoCall == null && mVideoCallProvider != null) {
try {
mVideoCall = new VideoCallImpl(mVideoCallProvider);
mVideoCall = new VideoCallImpl(mVideoCallProvider, callingPackageName);
} catch (RemoteException ignored) {
// Ignore RemoteException.
}

View File

@@ -125,13 +125,16 @@ public final class Phone {
private boolean mCanAddCall = true;
Phone(InCallAdapter adapter) {
private final String mCallingPackage;
Phone(InCallAdapter adapter, String callingPackage) {
mInCallAdapter = adapter;
mCallingPackage = callingPackage;
}
final void internalAddCall(ParcelableCall parcelableCall) {
Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
parcelableCall.getState());
parcelableCall.getState(), mCallingPackage);
mCallByTelecomCallId.put(parcelableCall.getId(), call);
mCalls.add(call);
checkCallTree(parcelableCall);

View File

@@ -408,6 +408,8 @@ public final class RemoteConnection {
private final IVideoProvider mVideoProviderBinder;
private final String mCallingPackage;
/**
* ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
* load factor before resizing, 1 means we only expect a single thread to
@@ -416,8 +418,9 @@ public final class RemoteConnection {
private final Set<Callback> mCallbacks = Collections.newSetFromMap(
new ConcurrentHashMap<Callback, Boolean>(8, 0.9f, 1));
VideoProvider(IVideoProvider videoProviderBinder) {
VideoProvider(IVideoProvider videoProviderBinder, String callingPackage) {
mVideoProviderBinder = videoProviderBinder;
mCallingPackage = callingPackage;
try {
mVideoProviderBinder.addVideoCallback(mVideoCallbackServant.getStub().asBinder());
} catch (RemoteException e) {
@@ -452,7 +455,7 @@ public final class RemoteConnection {
*/
public void setCamera(String cameraId) {
try {
mVideoProviderBinder.setCamera(cameraId);
mVideoProviderBinder.setCamera(cameraId, mCallingPackage);
} catch (RemoteException e) {
}
}
@@ -628,7 +631,7 @@ public final class RemoteConnection {
* @hide
*/
RemoteConnection(String callId, IConnectionService connectionService,
ParcelableConnection connection) {
ParcelableConnection connection, String callingPackage) {
mConnectionId = callId;
mConnectionService = connectionService;
mConnected = true;
@@ -640,7 +643,7 @@ public final class RemoteConnection {
mVideoState = connection.getVideoState();
IVideoProvider videoProvider = connection.getVideoProvider();
if (videoProvider != null) {
mVideoProvider = new RemoteConnection.VideoProvider(videoProvider);
mVideoProvider = new RemoteConnection.VideoProvider(videoProvider, callingPackage);
} else {
mVideoProvider = null;
}

View File

@@ -283,9 +283,13 @@ final class RemoteConnectionService {
@Override
public void setVideoProvider(String callId, IVideoProvider videoProvider,
Session.Info sessionInfo) {
String callingPackage = mOurConnectionServiceImpl.getApplicationContext()
.getOpPackageName();
RemoteConnection.VideoProvider remoteVideoProvider = null;
if (videoProvider != null) {
remoteVideoProvider = new RemoteConnection.VideoProvider(videoProvider);
remoteVideoProvider = new RemoteConnection.VideoProvider(videoProvider,
callingPackage);
}
findConnectionForAction(callId, "setVideoProvider")
.setVideoProvider(remoteVideoProvider);
@@ -351,8 +355,10 @@ final class RemoteConnectionService {
@Override
public void addExistingConnection(String callId, ParcelableConnection connection,
Session.Info sessionInfo) {
String callingPackage = mOurConnectionServiceImpl.getApplicationContext().
getOpPackageName();
RemoteConnection remoteConnection = new RemoteConnection(callId,
mOutgoingConnectionServiceRpc, connection);
mOutgoingConnectionServiceRpc, connection, callingPackage);
mConnectionById.put(callId, remoteConnection);
remoteConnection.registerCallback(new RemoteConnection.Callback() {
@Override

View File

@@ -43,6 +43,7 @@ public class VideoCallImpl extends VideoCall {
private VideoCall.Callback mCallback;
private int mVideoQuality = VideoProfile.QUALITY_UNKNOWN;
private int mVideoState = VideoProfile.STATE_AUDIO_ONLY;
private final String mCallingPackageName;
private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
@Override
@@ -197,12 +198,13 @@ public class VideoCallImpl extends VideoCall {
private Handler mHandler;
VideoCallImpl(IVideoProvider videoProvider) throws RemoteException {
VideoCallImpl(IVideoProvider videoProvider, String callingPackageName) throws RemoteException {
mVideoProvider = videoProvider;
mVideoProvider.asBinder().linkToDeath(mDeathRecipient, 0);
mBinder = new VideoCallListenerBinder();
mVideoProvider.addVideoCallback(mBinder);
mCallingPackageName = callingPackageName;
}
public void destroy() {
@@ -240,7 +242,8 @@ public class VideoCallImpl extends VideoCall {
/** {@inheritDoc} */
public void setCamera(String cameraId) {
try {
mVideoProvider.setCamera(cameraId);
Log.w(this, "setCamera: cameraId=%s, calling=%s", cameraId, mCallingPackageName);
mVideoProvider.setCamera(cameraId, mCallingPackageName);
} catch (RemoteException e) {
}
}

View File

@@ -30,7 +30,7 @@ oneway interface IVideoProvider {
void removeVideoCallback(IBinder videoCallbackBinder);
void setCamera(String cameraId);
void setCamera(String cameraId, in String mCallingPackageName);
void setPreviewSurface(in Surface surface);