am 14bafef5: am 24922798: am b20a8ed9: am d9b0f843: Merge "Fix issue #22860466: viapi security bug - rubber stamping in nested VIs" into mnc-dev

* commit '14bafef5b050f14c0fed3bfed8b137862139e627':
  Fix issue #22860466: viapi security bug - rubber stamping in nested VIs
This commit is contained in:
Dianne Hackborn
2015-08-04 01:37:57 +00:00
committed by Android Git Automerger
11 changed files with 92 additions and 7 deletions

View File

@ -3341,6 +3341,7 @@ package android.app {
method public boolean isImmersive(); method public boolean isImmersive();
method public boolean isTaskRoot(); method public boolean isTaskRoot();
method public boolean isVoiceInteraction(); 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 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 moveTaskToBack(boolean);
method public boolean navigateUpTo(android.content.Intent); method public boolean navigateUpTo(android.content.Intent);

View File

@ -3444,6 +3444,7 @@ package android.app {
method public boolean isImmersive(); method public boolean isImmersive();
method public boolean isTaskRoot(); method public boolean isTaskRoot();
method public boolean isVoiceInteraction(); 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 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 moveTaskToBack(boolean);
method public boolean navigateUpTo(android.content.Intent); method public boolean navigateUpTo(android.content.Intent);

View File

@ -1228,6 +1228,22 @@ public class Activity extends ContextThemeWrapper
return mVoiceInteractor != null; 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 * Retrieve the active {@link VoiceInteractor} that the user is going through to
* interact with this activity. * interact with this activity.

View File

@ -2582,6 +2582,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeInt(res ? 1 : 0); reply.writeInt(res ? 1 : 0);
return true; 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); return super.onTransact(code, data, reply, flags);
@ -5962,5 +5971,19 @@ class ActivityManagerProxy implements IActivityManager
return res != 0; 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; private IBinder mRemote;
} }

View File

@ -515,6 +515,8 @@ public interface IActivityManager extends IInterface {
public boolean setProcessMemoryTrimLevel(String process, int uid, int level) public boolean setProcessMemoryTrimLevel(String process, int uid, int level)
throws RemoteException; throws RemoteException;
public boolean isRootVoiceInteraction(IBinder token) throws RemoteException;
/* /*
* Private non-Binder interfaces * Private non-Binder interfaces
*/ */
@ -861,4 +863,5 @@ public interface IActivityManager extends IInterface {
int IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION int IS_SCREEN_CAPTURE_ALLOWED_ON_CURRENT_ACTIVITY_TRANSACTION
= IBinder.FIRST_CALL_TRANSACTION+299; = IBinder.FIRST_CALL_TRANSACTION+299;
int SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+300; int SHOW_ASSIST_FROM_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+300;
int IS_ROOT_VOICE_INTERACTION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+301;
} }

View File

@ -6540,6 +6540,17 @@ public final class ActivityManagerService extends ActivityManagerNative
} }
} }
@Override
public boolean isRootVoiceInteraction(IBinder token) {
synchronized(this) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
return false;
}
return r.rootVoiceInteraction;
}
}
@Override @Override
public IIntentSender getIntentSender(int type, public IIntentSender getIntentSender(int type,
String packageName, IBinder token, String resultWho, String packageName, IBinder token, String resultWho,

View File

@ -107,6 +107,7 @@ final class ActivityRecord {
boolean fullscreen; // covers the full screen? boolean fullscreen; // covers the full screen?
final boolean noDisplay; // activity is not displayed? final boolean noDisplay; // activity is not displayed?
final boolean componentSpecified; // did caller specifiy an explicit component? final boolean componentSpecified; // did caller specifiy an explicit component?
final boolean rootVoiceInteraction; // was this the root activity of a voice interaction?
static final int APPLICATION_ACTIVITY_TYPE = 0; static final int APPLICATION_ACTIVITY_TYPE = 0;
static final int HOME_ACTIVITY_TYPE = 1; static final int HOME_ACTIVITY_TYPE = 1;
@ -207,6 +208,9 @@ final class ActivityRecord {
pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded); pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
pw.print(" componentSpecified="); pw.print(componentSpecified); pw.print(" componentSpecified="); pw.print(componentSpecified);
pw.print(" mActivityType="); pw.println(mActivityType); pw.print(" mActivityType="); pw.println(mActivityType);
if (rootVoiceInteraction) {
pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
}
pw.print(prefix); pw.print("compat="); pw.print(compat); pw.print(prefix); pw.print("compat="); pw.print(compat);
pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes)); pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
pw.print(" icon=0x"); pw.print(Integer.toHexString(icon)); pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
@ -432,7 +436,8 @@ final class ActivityRecord {
int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration, ActivityInfo aInfo, Configuration _configuration,
ActivityRecord _resultTo, String _resultWho, int _reqCode, ActivityRecord _resultTo, String _resultWho, int _reqCode,
boolean _componentSpecified, ActivityStackSupervisor supervisor, boolean _componentSpecified, boolean _rootVoiceInteraction,
ActivityStackSupervisor supervisor,
ActivityContainer container, Bundle options) { ActivityContainer container, Bundle options) {
service = _service; service = _service;
appToken = new Token(this, service); appToken = new Token(this, service);
@ -444,6 +449,7 @@ final class ActivityRecord {
shortComponentName = _intent.getComponent().flattenToShortString(); shortComponentName = _intent.getComponent().flattenToShortString();
resolvedType = _resolvedType; resolvedType = _resolvedType;
componentSpecified = _componentSpecified; componentSpecified = _componentSpecified;
rootVoiceInteraction = _rootVoiceInteraction;
configuration = _configuration; configuration = _configuration;
stackConfigOverride = (container != null) stackConfigOverride = (container != null)
? container.mStack.mOverrideConfig : Configuration.EMPTY; ? container.mStack.mOverrideConfig : Configuration.EMPTY;
@ -1257,7 +1263,7 @@ final class ActivityRecord {
} }
final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid, final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid,
launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(), launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(),
null, null, 0, componentSpecified, stackSupervisor, null, null); null, null, 0, componentSpecified, false, stackSupervisor, null, null);
r.persistentState = persistentState; r.persistentState = persistentState;
r.taskDescription = taskDescription; r.taskDescription = taskDescription;

View File

@ -1506,6 +1506,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0
&& sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) { && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
try { try {
intent.addCategory(Intent.CATEGORY_VOICE);
if (!AppGlobals.getPackageManager().activitySupportsIntent( if (!AppGlobals.getPackageManager().activitySupportsIntent(
intent.getComponent(), intent, resolvedType)) { intent.getComponent(), intent, resolvedType)) {
err = ActivityManager.START_NOT_VOICE_COMPATIBLE; err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
@ -1626,7 +1627,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
requestCode, componentSpecified, this, container, options); requestCode, componentSpecified, voiceSession != null, this, container, options);
if (outActivity != null) { if (outActivity != null) {
outActivity[0] = r; outActivity[0] = r;
} }
@ -3721,19 +3722,19 @@ public final class ActivityStackSupervisor implements DisplayListener {
@Override @Override
public void onDisplayAdded(int displayId) { public void onDisplayAdded(int displayId) {
Slog.v(TAG, "Display added displayId=" + displayId); if (DEBUG_STACK) Slog.v(TAG, "Display added displayId=" + displayId);
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_ADDED, displayId, 0)); mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_ADDED, displayId, 0));
} }
@Override @Override
public void onDisplayRemoved(int displayId) { public void onDisplayRemoved(int displayId) {
Slog.v(TAG, "Display removed displayId=" + displayId); if (DEBUG_STACK) Slog.v(TAG, "Display removed displayId=" + displayId);
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_REMOVED, displayId, 0)); mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_REMOVED, displayId, 0));
} }
@Override @Override
public void onDisplayChanged(int displayId) { public void onDisplayChanged(int displayId) {
Slog.v(TAG, "Display changed displayId=" + displayId); if (DEBUG_STACK) Slog.v(TAG, "Display changed displayId=" + displayId);
mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0)); mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0));
} }

View File

@ -34,6 +34,19 @@
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
/> />
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<Button android:id="@+id/airplane"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/launchAirplane"
/>
</LinearLayout>
<LinearLayout android:layout_width="match_parent" <LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"

View File

@ -21,6 +21,7 @@
<string name="tree">Tree</string> <string name="tree">Tree</string>
<string name="text">Text</string> <string name="text">Text</string>
<string name="asyncStructure">(Async structure goes here)</string> <string name="asyncStructure">(Async structure goes here)</string>
<string name="launchAirplane">Launch airplane mode</string>
<string name="confirm">Confirm</string> <string name="confirm">Confirm</string>
<string name="abort">Abort</string> <string name="abort">Abort</string>
<string name="complete">Complete</string> <string name="complete">Complete</string>

View File

@ -21,6 +21,7 @@ import android.app.VoiceInteractor;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.provider.Settings;
import android.service.voice.VoiceInteractionService; import android.service.voice.VoiceInteractionService;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
@ -39,6 +40,7 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis
VoiceInteractor mInteractor; VoiceInteractor mInteractor;
VoiceInteractor.Request mCurrentRequest = null; VoiceInteractor.Request mCurrentRequest = null;
TextView mLog; TextView mLog;
Button mAirplaneButton;
Button mAbortButton; Button mAbortButton;
Button mCompleteButton; Button mCompleteButton;
Button mCommandButton; Button mCommandButton;
@ -65,6 +67,8 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis
setContentView(R.layout.test_interaction); setContentView(R.layout.test_interaction);
mLog = (TextView)findViewById(R.id.log); mLog = (TextView)findViewById(R.id.log);
mAirplaneButton = (Button)findViewById(R.id.airplane);
mAirplaneButton.setOnClickListener(this);
mAbortButton = (Button)findViewById(R.id.abort); mAbortButton = (Button)findViewById(R.id.abort);
mAbortButton.setOnClickListener(this); mAbortButton.setOnClickListener(this);
mCompleteButton = (Button)findViewById(R.id.complete); mCompleteButton = (Button)findViewById(R.id.complete);
@ -122,7 +126,12 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis
@Override @Override
public void onClick(View v) { public void onClick(View v) {
if (v == mAbortButton) { if (v == mAirplaneButton) {
Intent intent = new Intent(Settings.ACTION_VOICE_CONTROL_AIRPLANE_MODE);
intent.addCategory(Intent.CATEGORY_VOICE);
intent.putExtra(Settings.EXTRA_AIRPLANE_MODE_ENABLED, true);
startActivity(intent);
} else if (v == mAbortButton) {
VoiceInteractor.AbortVoiceRequest req = new TestAbortVoice(); VoiceInteractor.AbortVoiceRequest req = new TestAbortVoice();
mInteractor.submitRequest(req, REQUEST_ABORT); mInteractor.submitRequest(req, REQUEST_ABORT);
} else if (v == mCompleteButton) { } else if (v == mCompleteButton) {