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

Commit fb81d09d authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Fix issue #22860466: viapi security bug - rubber stamping in nested VIs

Add new Activity.isVoiceInteractionRoot() API that an activity can use
to determine whether it is the root activity of a voice interaction
session started by the user's designated voice interaction service.

This is a special new API that apps must explicitly check, because as
with visual activities the model behind an activity should usually be
that it accomplishes its task by interacting with the user (implicitly
getting their approval) rather than trusting that whoever invoked it
is telling it to do what the user once.  In the voice world, however,
there are some cases where quick interactions want to allow for immediate
execution without further user involvement, so this API allows for that
without opening up security holes from other applications.

Change-Id: Ie02d2458f16cb0b12af825641bcf8beaf086931b
parent 0ca1e98f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3341,6 +3341,7 @@ package android.app {
    method public boolean isImmersive();
    method public boolean isTaskRoot();
    method public boolean isVoiceInteraction();
    method public boolean isVoiceInteractionRoot();
    method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
    method public boolean moveTaskToBack(boolean);
    method public boolean navigateUpTo(android.content.Intent);
+1 −0
Original line number Diff line number Diff line
@@ -3444,6 +3444,7 @@ package android.app {
    method public boolean isImmersive();
    method public boolean isTaskRoot();
    method public boolean isVoiceInteraction();
    method public boolean isVoiceInteractionRoot();
    method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
    method public boolean moveTaskToBack(boolean);
    method public boolean navigateUpTo(android.content.Intent);
+16 −0
Original line number Diff line number Diff line
@@ -1228,6 +1228,22 @@ public class Activity extends ContextThemeWrapper
        return mVoiceInteractor != null;
    }

    /**
     * Like {@link #isVoiceInteraction}, but only returns true if this is also the root
     * of a voice interaction.  That is, returns true if this activity was directly
     * started by the voice interaction service as the initiation of a voice interaction.
     * Otherwise, for example if it was started by another activity while under voice
     * interaction, returns false.
     */
    public boolean isVoiceInteractionRoot() {
        try {
            return mVoiceInteractor != null
                    && ActivityManagerNative.getDefault().isRootVoiceInteraction(mToken);
        } catch (RemoteException e) {
        }
        return false;
    }

    /**
     * Retrieve the active {@link VoiceInteractor} that the user is going through to
     * interact with this activity.
+23 −0
Original line number Diff line number Diff line
@@ -2582,6 +2582,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            reply.writeInt(res ? 1 : 0);
            return true;
        }

        case IS_ROOT_VOICE_INTERACTION_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder token = data.readStrongBinder();
            boolean res = isRootVoiceInteraction(token);
            reply.writeNoException();
            reply.writeInt(res ? 1 : 0);
            return true;
        }
        }

        return super.onTransact(code, data, reply, flags);
@@ -5962,5 +5971,19 @@ class ActivityManagerProxy implements IActivityManager
        return res != 0;
    }

    @Override
    public boolean isRootVoiceInteraction(IBinder token) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(token);
        mRemote.transact(IS_ROOT_VOICE_INTERACTION_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        data.recycle();
        reply.recycle();
        return res != 0;
    }

    private IBinder mRemote;
}
+3 −0
Original line number Diff line number Diff line
@@ -515,6 +515,8 @@ public interface IActivityManager extends IInterface {
    public boolean setProcessMemoryTrimLevel(String process, int uid, int level)
            throws RemoteException;

    public boolean isRootVoiceInteraction(IBinder token) throws RemoteException;

    /*
     * Private non-Binder interfaces
     */
@@ -861,4 +863,5 @@ public interface IActivityManager extends IInterface {
    int IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION
            = IBinder.FIRST_CALL_TRANSACTION+299;
    int SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+300;
    int IS_ROOT_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+301;
}
Loading