Skip to content

Commit d9b0f84

Browse files
Dianne HackbornAndroid (Google) Code Review
authored andcommitted
Merge "Fix issue #22860466: viapi security bug - rubber stamping in nested VIs" into mnc-dev
2 parents 04e2cf6 + fb81d09 commit d9b0f84

11 files changed

Lines changed: 92 additions & 7 deletions

File tree

api/current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3341,6 +3341,7 @@ package android.app {
33413341
method public boolean isImmersive();
33423342
method public boolean isTaskRoot();
33433343
method public boolean isVoiceInteraction();
3344+
method public boolean isVoiceInteractionRoot();
33443345
method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
33453346
method public boolean moveTaskToBack(boolean);
33463347
method public boolean navigateUpTo(android.content.Intent);

api/system-current.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3444,6 +3444,7 @@ package android.app {
34443444
method public boolean isImmersive();
34453445
method public boolean isTaskRoot();
34463446
method public boolean isVoiceInteraction();
3447+
method public boolean isVoiceInteractionRoot();
34473448
method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
34483449
method public boolean moveTaskToBack(boolean);
34493450
method public boolean navigateUpTo(android.content.Intent);

core/java/android/app/Activity.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,22 @@ public boolean isVoiceInteraction() {
12281228
return mVoiceInteractor != null;
12291229
}
12301230

1231+
/**
1232+
* Like {@link #isVoiceInteraction}, but only returns true if this is also the root
1233+
* of a voice interaction. That is, returns true if this activity was directly
1234+
* started by the voice interaction service as the initiation of a voice interaction.
1235+
* Otherwise, for example if it was started by another activity while under voice
1236+
* interaction, returns false.
1237+
*/
1238+
public boolean isVoiceInteractionRoot() {
1239+
try {
1240+
return mVoiceInteractor != null
1241+
&& ActivityManagerNative.getDefault().isRootVoiceInteraction(mToken);
1242+
} catch (RemoteException e) {
1243+
}
1244+
return false;
1245+
}
1246+
12311247
/**
12321248
* Retrieve the active {@link VoiceInteractor} that the user is going through to
12331249
* interact with this activity.

core/java/android/app/ActivityManagerNative.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,6 +2582,15 @@ public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
25822582
reply.writeInt(res ? 1 : 0);
25832583
return true;
25842584
}
2585+
2586+
case IS_ROOT_VOICE_INTERACTION_TRANSACTION: {
2587+
data.enforceInterface(IActivityManager.descriptor);
2588+
IBinder token = data.readStrongBinder();
2589+
boolean res = isRootVoiceInteraction(token);
2590+
reply.writeNoException();
2591+
reply.writeInt(res ? 1 : 0);
2592+
return true;
2593+
}
25852594
}
25862595

25872596
return super.onTransact(code, data, reply, flags);
@@ -5962,5 +5971,19 @@ public boolean setProcessMemoryTrimLevel(String process, int userId, int level)
59625971
return res != 0;
59635972
}
59645973

5974+
@Override
5975+
public boolean isRootVoiceInteraction(IBinder token) throws RemoteException {
5976+
Parcel data = Parcel.obtain();
5977+
Parcel reply = Parcel.obtain();
5978+
data.writeInterfaceToken(IActivityManager.descriptor);
5979+
data.writeStrongBinder(token);
5980+
mRemote.transact(IS_ROOT_VOICE_INTERACTION_TRANSACTION, data, reply, 0);
5981+
reply.readException();
5982+
int res = reply.readInt();
5983+
data.recycle();
5984+
reply.recycle();
5985+
return res != 0;
5986+
}
5987+
59655988
private IBinder mRemote;
59665989
}

core/java/android/app/IActivityManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,8 @@ public int getPackageProcessState(String packageName, String callingPackage)
515515
public boolean setProcessMemoryTrimLevel(String process, int uid, int level)
516516
throws RemoteException;
517517

518+
public boolean isRootVoiceInteraction(IBinder token) throws RemoteException;
519+
518520
/*
519521
* Private non-Binder interfaces
520522
*/
@@ -861,4 +863,5 @@ private WaitResult(Parcel source) {
861863
int IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION
862864
= IBinder.FIRST_CALL_TRANSACTION+299;
863865
int SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+300;
866+
int IS_ROOT_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+301;
864867
}

services/core/java/com/android/server/am/ActivityManagerService.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6551,6 +6551,17 @@ public String getPackageForToken(IBinder token) {
65516551
}
65526552
}
65536553

6554+
@Override
6555+
public boolean isRootVoiceInteraction(IBinder token) {
6556+
synchronized(this) {
6557+
ActivityRecord r = ActivityRecord.isInStackLocked(token);
6558+
if (r == null) {
6559+
return false;
6560+
}
6561+
return r.rootVoiceInteraction;
6562+
}
6563+
}
6564+
65546565
@Override
65556566
public IIntentSender getIntentSender(int type,
65566567
String packageName, IBinder token, String resultWho,

services/core/java/com/android/server/am/ActivityRecord.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ final class ActivityRecord {
107107
boolean fullscreen; // covers the full screen?
108108
final boolean noDisplay; // activity is not displayed?
109109
final boolean componentSpecified; // did caller specifiy an explicit component?
110+
final boolean rootVoiceInteraction; // was this the root activity of a voice interaction?
110111

111112
static final int APPLICATION_ACTIVITY_TYPE = 0;
112113
static final int HOME_ACTIVITY_TYPE = 1;
@@ -207,6 +208,9 @@ void dump(PrintWriter pw, String prefix) {
207208
pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
208209
pw.print(" componentSpecified="); pw.print(componentSpecified);
209210
pw.print(" mActivityType="); pw.println(mActivityType);
211+
if (rootVoiceInteraction) {
212+
pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
213+
}
210214
pw.print(prefix); pw.print("compat="); pw.print(compat);
211215
pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
212216
pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
@@ -432,7 +436,8 @@ boolean isNotResolverActivity() {
432436
int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
433437
ActivityInfo aInfo, Configuration _configuration,
434438
ActivityRecord _resultTo, String _resultWho, int _reqCode,
435-
boolean _componentSpecified, ActivityStackSupervisor supervisor,
439+
boolean _componentSpecified, boolean _rootVoiceInteraction,
440+
ActivityStackSupervisor supervisor,
436441
ActivityContainer container, Bundle options) {
437442
service = _service;
438443
appToken = new Token(this, service);
@@ -444,6 +449,7 @@ boolean isNotResolverActivity() {
444449
shortComponentName = _intent.getComponent().flattenToShortString();
445450
resolvedType = _resolvedType;
446451
componentSpecified = _componentSpecified;
452+
rootVoiceInteraction = _rootVoiceInteraction;
447453
configuration = _configuration;
448454
stackConfigOverride = (container != null)
449455
? container.mStack.mOverrideConfig : Configuration.EMPTY;
@@ -1257,7 +1263,7 @@ static ActivityRecord restoreFromXml(XmlPullParser in,
12571263
}
12581264
final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid,
12591265
launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(),
1260-
null, null, 0, componentSpecified, stackSupervisor, null, null);
1266+
null, null, 0, componentSpecified, false, stackSupervisor, null, null);
12611267

12621268
r.persistentState = persistentState;
12631269
r.taskDescription = taskDescription;

services/core/java/com/android/server/am/ActivityStackSupervisor.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,7 @@ final int startActivityLocked(IApplicationThread caller,
15061506
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
15071507
&& sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
15081508
try {
1509+
intent.addCategory(Intent.CATEGORY_VOICE);
15091510
if (!AppGlobals.getPackageManager().activitySupportsIntent(
15101511
intent.getComponent(), intent, resolvedType)) {
15111512
err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
@@ -1626,7 +1627,7 @@ final int startActivityLocked(IApplicationThread caller,
16261627

16271628
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
16281629
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
1629-
requestCode, componentSpecified, this, container, options);
1630+
requestCode, componentSpecified, voiceSession != null, this, container, options);
16301631
if (outActivity != null) {
16311632
outActivity[0] = r;
16321633
}
@@ -3721,19 +3722,19 @@ final void scheduleSleepTimeout() {
37213722

37223723
@Override
37233724
public void onDisplayAdded(int displayId) {
3724-
Slog.v(TAG, "Display added displayId=" + displayId);
3725+
if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
37253726
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_ADDED, displayId, 0));
37263727
}
37273728

37283729
@Override
37293730
public void onDisplayRemoved(int displayId) {
3730-
Slog.v(TAG, "Display removed displayId=" + displayId);
3731+
if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId);
37313732
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_REMOVED, displayId, 0));
37323733
}
37333734

37343735
@Override
37353736
public void onDisplayChanged(int displayId) {
3736-
Slog.v(TAG, "Display changed displayId=" + displayId);
3737+
if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId);
37373738
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0));
37383739
}
37393740

tests/VoiceInteraction/res/layout/test_interaction.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@
3434
android:textAppearance="?android:attr/textAppearanceMedium"
3535
/>
3636

37+
<LinearLayout android:layout_width="match_parent"
38+
android:layout_height="wrap_content"
39+
android:layout_marginTop="16dp"
40+
android:orientation="horizontal">
41+
42+
<Button android:id="@+id/airplane"
43+
android:layout_width="wrap_content"
44+
android:layout_height="wrap_content"
45+
android:text="@string/launchAirplane"
46+
/>
47+
48+
</LinearLayout>
49+
3750
<LinearLayout android:layout_width="match_parent"
3851
android:layout_height="wrap_content"
3952
android:layout_marginTop="16dp"

tests/VoiceInteraction/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
<string name="tree">Tree</string>
2222
<string name="text">Text</string>
2323
<string name="asyncStructure">(Async structure goes here)</string>
24+
<string name="launchAirplane">Launch airplane mode</string>
2425
<string name="confirm">Confirm</string>
2526
<string name="abort">Abort</string>
2627
<string name="complete">Complete</string>

0 commit comments

Comments
 (0)