diff options
-rw-r--r-- | api/current.txt | 1 | ||||
-rw-r--r-- | api/system-current.txt | 1 | ||||
-rw-r--r-- | core/java/android/app/Activity.java | 16 | ||||
-rw-r--r-- | core/java/android/app/ActivityManagerNative.java | 23 | ||||
-rw-r--r-- | core/java/android/app/IActivityManager.java | 3 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActivityManagerService.java | 11 | ||||
-rwxr-xr-x | services/core/java/com/android/server/am/ActivityRecord.java | 10 | ||||
-rw-r--r-- | services/core/java/com/android/server/am/ActivityStackSupervisor.java | 9 | ||||
-rw-r--r-- | tests/VoiceInteraction/res/layout/test_interaction.xml | 13 | ||||
-rw-r--r-- | tests/VoiceInteraction/res/values/strings.xml | 1 | ||||
-rw-r--r-- | tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java | 11 |
11 files changed, 92 insertions, 7 deletions
diff --git a/api/current.txt b/api/current.txt index 68ecf96..e16294e 100644 --- a/api/current.txt +++ b/api/current.txt @@ -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); diff --git a/api/system-current.txt b/api/system-current.txt index 2e0613a..a784378 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -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); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index bdea608..3c8af0d 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1229,6 +1229,22 @@ public class Activity extends ContextThemeWrapper } /** + * 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. */ diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index b758a7a..e144c29 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -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; } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 9ebbb9b..90216af 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -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; } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 783dea5..8f2c838 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -6552,6 +6552,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 public IIntentSender getIntentSender(int type, String packageName, IBinder token, String resultWho, int requestCode, Intent[] intents, String[] resolvedTypes, diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 0957eb5..3de2009 100755 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -107,6 +107,7 @@ final class ActivityRecord { boolean fullscreen; // covers the full screen? final boolean noDisplay; // activity is not displayed? 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 HOME_ACTIVITY_TYPE = 1; @@ -207,6 +208,9 @@ final class ActivityRecord { pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded); pw.print(" componentSpecified="); pw.print(componentSpecified); 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(" labelRes=0x"); pw.print(Integer.toHexString(labelRes)); pw.print(" icon=0x"); pw.print(Integer.toHexString(icon)); @@ -432,7 +436,8 @@ final class ActivityRecord { int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo, String _resultWho, int _reqCode, - boolean _componentSpecified, ActivityStackSupervisor supervisor, + boolean _componentSpecified, boolean _rootVoiceInteraction, + ActivityStackSupervisor supervisor, ActivityContainer container, Bundle options) { service = _service; appToken = new Token(this, service); @@ -444,6 +449,7 @@ final class ActivityRecord { shortComponentName = _intent.getComponent().flattenToShortString(); resolvedType = _resolvedType; componentSpecified = _componentSpecified; + rootVoiceInteraction = _rootVoiceInteraction; configuration = _configuration; stackConfigOverride = (container != null) ? container.mStack.mOverrideConfig : Configuration.EMPTY; @@ -1257,7 +1263,7 @@ final class ActivityRecord { } final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid, 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.taskDescription = taskDescription; diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 0be2f6f..71fd49b 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -1506,6 +1506,7 @@ public final class ActivityStackSupervisor implements DisplayListener { if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0 && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) { try { + intent.addCategory(Intent.CATEGORY_VOICE); if (!AppGlobals.getPackageManager().activitySupportsIntent( intent.getComponent(), intent, resolvedType)) { err = ActivityManager.START_NOT_VOICE_COMPATIBLE; @@ -1626,7 +1627,7 @@ public final class ActivityStackSupervisor implements DisplayListener { ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, - requestCode, componentSpecified, this, container, options); + requestCode, componentSpecified, voiceSession != null, this, container, options); if (outActivity != null) { outActivity[0] = r; } @@ -3721,19 +3722,19 @@ public final class ActivityStackSupervisor implements DisplayListener { @Override 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)); } @Override 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)); } @Override 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)); } diff --git a/tests/VoiceInteraction/res/layout/test_interaction.xml b/tests/VoiceInteraction/res/layout/test_interaction.xml index d1a7ad5..277117e 100644 --- a/tests/VoiceInteraction/res/layout/test_interaction.xml +++ b/tests/VoiceInteraction/res/layout/test_interaction.xml @@ -39,6 +39,19 @@ 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" + android:layout_height="wrap_content" + android:layout_marginTop="16dp" + android:orientation="horizontal"> + <Button android:id="@+id/complete" android:layout_width="wrap_content" android:layout_height="wrap_content" diff --git a/tests/VoiceInteraction/res/values/strings.xml b/tests/VoiceInteraction/res/values/strings.xml index 29ffe21..c665c23 100644 --- a/tests/VoiceInteraction/res/values/strings.xml +++ b/tests/VoiceInteraction/res/values/strings.xml @@ -21,6 +21,7 @@ <string name="tree">Tree</string> <string name="text">Text</string> <string name="asyncStructure">(Async structure goes here)</string> + <string name="launchAirplane">Launch airplane mode</string> <string name="confirm">Confirm</string> <string name="abort">Abort</string> <string name="complete">Complete</string> diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java index e10d89f..ada0e21 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java @@ -21,6 +21,7 @@ import android.app.VoiceInteractor; import android.content.ComponentName; import android.content.Intent; import android.os.Bundle; +import android.provider.Settings; import android.service.voice.VoiceInteractionService; import android.util.Log; import android.view.View; @@ -39,6 +40,7 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis VoiceInteractor mInteractor; VoiceInteractor.Request mCurrentRequest = null; TextView mLog; + Button mAirplaneButton; Button mAbortButton; Button mCompleteButton; Button mCommandButton; @@ -65,6 +67,8 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis setContentView(R.layout.test_interaction); mLog = (TextView)findViewById(R.id.log); + mAirplaneButton = (Button)findViewById(R.id.airplane); + mAirplaneButton.setOnClickListener(this); mAbortButton = (Button)findViewById(R.id.abort); mAbortButton.setOnClickListener(this); mCompleteButton = (Button)findViewById(R.id.complete); @@ -122,7 +126,12 @@ public class TestInteractionActivity extends Activity implements View.OnClickLis @Override 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(); mInteractor.submitRequest(req, REQUEST_ABORT); } else if (v == mCompleteButton) { |