Loading core/java/android/app/Activity.java +38 −0 Original line number Diff line number Diff line Loading @@ -87,11 +87,13 @@ import android.os.Parcelable; import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.os.StrictMode; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.service.voice.VoiceInteractionSession; import android.text.Selection; import android.text.SpannableStringBuilder; import android.text.TextUtils; Loading Loading @@ -155,6 +157,7 @@ import android.window.WindowOnBackInvokedDispatcher; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractionManagerService; import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.ToolbarActionBar; import com.android.internal.app.WindowDecorActionBar; Loading Loading @@ -1602,6 +1605,25 @@ public class Activity extends ContextThemeWrapper return callbacks; } private void notifyVoiceInteractionManagerServiceActivityEvent( @VoiceInteractionSession.VoiceInteractionActivityEventType int type) { final IVoiceInteractionManagerService service = IVoiceInteractionManagerService.Stub.asInterface( ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE)); if (service == null) { Log.w(TAG, "notifyVoiceInteractionManagerServiceActivityEvent: Can not get " + "VoiceInteractionManagerService"); return; } try { service.notifyActivityEventChanged(mToken, type); } catch (RemoteException e) { // Empty } } /** * Called when the activity is starting. This is where most initialization * should go: calling {@link #setContentView(int)} to inflate the Loading Loading @@ -1877,6 +1899,9 @@ public class Activity extends ContextThemeWrapper mCalled = true; notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_START); notifyVoiceInteractionManagerServiceActivityEvent( VoiceInteractionSession.VOICE_INTERACTION_ACTIVITY_EVENT_START); } /** Loading Loading @@ -2020,6 +2045,12 @@ public class Activity extends ContextThemeWrapper final Window win = getWindow(); if (win != null) win.makeActive(); if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(true); // Because the test case "com.android.launcher3.jank.BinderTests#testPressHome" doesn't // allow any binder call in onResume, we call this method in onPostResume. notifyVoiceInteractionManagerServiceActivityEvent( VoiceInteractionSession.VOICE_INTERACTION_ACTIVITY_EVENT_RESUME); mCalled = true; } Loading Loading @@ -2395,6 +2426,10 @@ public class Activity extends ContextThemeWrapper getAutofillClientController().onActivityPaused(); notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_PAUSE); notifyVoiceInteractionManagerServiceActivityEvent( VoiceInteractionSession.VOICE_INTERACTION_ACTIVITY_EVENT_PAUSE); mCalled = true; } Loading Loading @@ -2624,6 +2659,9 @@ public class Activity extends ContextThemeWrapper getAutofillClientController().onActivityStopped(mIntent, mChangingConfigurations); mEnterAnimationComplete = false; notifyVoiceInteractionManagerServiceActivityEvent( VoiceInteractionSession.VOICE_INTERACTION_ACTIVITY_EVENT_STOP); } /** Loading core/java/android/app/ActivityManagerInternal.java +2 −3 Original line number Diff line number Diff line Loading @@ -747,10 +747,9 @@ public abstract class ActivityManagerInternal { */ public interface VoiceInteractionManagerProvider { /** * Notifies the service when a high-level activity event has been changed, for example, * an activity was resumed or stopped. * Notifies the service when an activity is destroyed. */ void notifyActivityEventChanged(); void notifyActivityDestroyed(IBinder activityToken); } /** Loading core/java/android/service/voice/VoiceInteractionSession.java +22 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -73,6 +74,8 @@ import com.android.internal.util.function.pooled.PooledLambda; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -146,6 +149,25 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall */ public static final int SHOW_SOURCE_AUTOMOTIVE_SYSTEM_UI = 1 << 7; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_START = 1; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_RESUME = 2; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_PAUSE = 3; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_STOP = 4; /** @hide */ @IntDef(prefix = { "VOICE_INTERACTION_ACTIVITY_EVENT_" }, value = { VOICE_INTERACTION_ACTIVITY_EVENT_START, VOICE_INTERACTION_ACTIVITY_EVENT_RESUME, VOICE_INTERACTION_ACTIVITY_EVENT_PAUSE, VOICE_INTERACTION_ACTIVITY_EVENT_STOP }) @Retention(RetentionPolicy.SOURCE) public @interface VoiceInteractionActivityEventType{} final Context mContext; final HandlerCaller mHandlerCaller; Loading core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl +18 −7 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.internal.app; import android.content.ComponentName; import android.content.Intent; import android.hardware.soundtrigger.KeyphraseMetadata; import android.hardware.soundtrigger.SoundTrigger; import android.media.AudioFormat; import android.media.permission.Identity; import android.os.Bundle; Loading @@ -25,18 +27,17 @@ import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.RemoteCallback; import android.os.SharedMemory; import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback; import android.service.voice.IVoiceInteractionService; import android.service.voice.IVoiceInteractionSession; import android.service.voice.VisibleActivityInfo; import com.android.internal.app.IHotwordRecognitionStatusCallback; import com.android.internal.app.IVoiceActionCheckCallback; import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.IVoiceInteractionSessionListener; import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractionSoundTriggerSession; import android.hardware.soundtrigger.KeyphraseMetadata; import android.hardware.soundtrigger.SoundTrigger; import android.service.voice.IVoiceInteractionService; import android.service.voice.IVoiceInteractionSession; import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback; import com.android.internal.app.IVoiceInteractor; interface IVoiceInteractionManagerService { void showSession(in Bundle sessionArgs, int flags, String attributionTag); Loading Loading @@ -303,4 +304,14 @@ interface IVoiceInteractionManagerService { * Notifies when the session window is shown or hidden. */ void setSessionWindowVisible(in IBinder token, boolean visible); /** * Notifies when the Activity lifecycle event changed. * * @param activityToken The token of activity. * @param type The type of lifecycle event of the activity lifecycle. */ oneway void notifyActivityEventChanged( in IBinder activityToken, int type); } services/core/java/com/android/server/am/ActivityManagerService.java +7 −4 Original line number Diff line number Diff line Loading @@ -2935,10 +2935,13 @@ public class ActivityManagerService extends IActivityManager.Stub || event == Event.ACTIVITY_DESTROYED)) { contentCaptureService.notifyActivityEvent(userId, activity, event); } // TODO(b/201234353): Move the logic to client side. if (mVoiceInteractionManagerProvider != null && (event == Event.ACTIVITY_PAUSED || event == Event.ACTIVITY_RESUMED || event == Event.ACTIVITY_STOPPED)) { mVoiceInteractionManagerProvider.notifyActivityEventChanged(); // Currently we have move most of logic to the client side. When the activity lifecycle // event changed, the client side will notify the VoiceInteractionManagerService. But // when the application process died, the VoiceInteractionManagerService will miss the // activity lifecycle event changed, so we still need ACTIVITY_DESTROYED event here to // know if the activity has been destroyed. if (mVoiceInteractionManagerProvider != null && event == Event.ACTIVITY_DESTROYED) { mVoiceInteractionManagerProvider.notifyActivityDestroyed(appToken); } } Loading Loading
core/java/android/app/Activity.java +38 −0 Original line number Diff line number Diff line Loading @@ -87,11 +87,13 @@ import android.os.Parcelable; import android.os.PersistableBundle; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.ServiceManager.ServiceNotFoundException; import android.os.StrictMode; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.service.voice.VoiceInteractionSession; import android.text.Selection; import android.text.SpannableStringBuilder; import android.text.TextUtils; Loading Loading @@ -155,6 +157,7 @@ import android.window.WindowOnBackInvokedDispatcher; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractionManagerService; import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.ToolbarActionBar; import com.android.internal.app.WindowDecorActionBar; Loading Loading @@ -1602,6 +1605,25 @@ public class Activity extends ContextThemeWrapper return callbacks; } private void notifyVoiceInteractionManagerServiceActivityEvent( @VoiceInteractionSession.VoiceInteractionActivityEventType int type) { final IVoiceInteractionManagerService service = IVoiceInteractionManagerService.Stub.asInterface( ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE)); if (service == null) { Log.w(TAG, "notifyVoiceInteractionManagerServiceActivityEvent: Can not get " + "VoiceInteractionManagerService"); return; } try { service.notifyActivityEventChanged(mToken, type); } catch (RemoteException e) { // Empty } } /** * Called when the activity is starting. This is where most initialization * should go: calling {@link #setContentView(int)} to inflate the Loading Loading @@ -1877,6 +1899,9 @@ public class Activity extends ContextThemeWrapper mCalled = true; notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_START); notifyVoiceInteractionManagerServiceActivityEvent( VoiceInteractionSession.VOICE_INTERACTION_ACTIVITY_EVENT_START); } /** Loading Loading @@ -2020,6 +2045,12 @@ public class Activity extends ContextThemeWrapper final Window win = getWindow(); if (win != null) win.makeActive(); if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(true); // Because the test case "com.android.launcher3.jank.BinderTests#testPressHome" doesn't // allow any binder call in onResume, we call this method in onPostResume. notifyVoiceInteractionManagerServiceActivityEvent( VoiceInteractionSession.VOICE_INTERACTION_ACTIVITY_EVENT_RESUME); mCalled = true; } Loading Loading @@ -2395,6 +2426,10 @@ public class Activity extends ContextThemeWrapper getAutofillClientController().onActivityPaused(); notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_PAUSE); notifyVoiceInteractionManagerServiceActivityEvent( VoiceInteractionSession.VOICE_INTERACTION_ACTIVITY_EVENT_PAUSE); mCalled = true; } Loading Loading @@ -2624,6 +2659,9 @@ public class Activity extends ContextThemeWrapper getAutofillClientController().onActivityStopped(mIntent, mChangingConfigurations); mEnterAnimationComplete = false; notifyVoiceInteractionManagerServiceActivityEvent( VoiceInteractionSession.VOICE_INTERACTION_ACTIVITY_EVENT_STOP); } /** Loading
core/java/android/app/ActivityManagerInternal.java +2 −3 Original line number Diff line number Diff line Loading @@ -747,10 +747,9 @@ public abstract class ActivityManagerInternal { */ public interface VoiceInteractionManagerProvider { /** * Notifies the service when a high-level activity event has been changed, for example, * an activity was resumed or stopped. * Notifies the service when an activity is destroyed. */ void notifyActivityEventChanged(); void notifyActivityDestroyed(IBinder activityToken); } /** Loading
core/java/android/service/voice/VoiceInteractionSession.java +22 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.view.Display.DEFAULT_DISPLAY; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; Loading Loading @@ -73,6 +74,8 @@ import com.android.internal.util.function.pooled.PooledLambda; import java.io.FileDescriptor; import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Arrays; Loading Loading @@ -146,6 +149,25 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall */ public static final int SHOW_SOURCE_AUTOMOTIVE_SYSTEM_UI = 1 << 7; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_START = 1; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_RESUME = 2; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_PAUSE = 3; /** @hide */ public static final int VOICE_INTERACTION_ACTIVITY_EVENT_STOP = 4; /** @hide */ @IntDef(prefix = { "VOICE_INTERACTION_ACTIVITY_EVENT_" }, value = { VOICE_INTERACTION_ACTIVITY_EVENT_START, VOICE_INTERACTION_ACTIVITY_EVENT_RESUME, VOICE_INTERACTION_ACTIVITY_EVENT_PAUSE, VOICE_INTERACTION_ACTIVITY_EVENT_STOP }) @Retention(RetentionPolicy.SOURCE) public @interface VoiceInteractionActivityEventType{} final Context mContext; final HandlerCaller mHandlerCaller; Loading
core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl +18 −7 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.internal.app; import android.content.ComponentName; import android.content.Intent; import android.hardware.soundtrigger.KeyphraseMetadata; import android.hardware.soundtrigger.SoundTrigger; import android.media.AudioFormat; import android.media.permission.Identity; import android.os.Bundle; Loading @@ -25,18 +27,17 @@ import android.os.ParcelFileDescriptor; import android.os.PersistableBundle; import android.os.RemoteCallback; import android.os.SharedMemory; import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback; import android.service.voice.IVoiceInteractionService; import android.service.voice.IVoiceInteractionSession; import android.service.voice.VisibleActivityInfo; import com.android.internal.app.IHotwordRecognitionStatusCallback; import com.android.internal.app.IVoiceActionCheckCallback; import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.IVoiceInteractionSessionListener; import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.app.IVoiceInteractionSoundTriggerSession; import android.hardware.soundtrigger.KeyphraseMetadata; import android.hardware.soundtrigger.SoundTrigger; import android.service.voice.IVoiceInteractionService; import android.service.voice.IVoiceInteractionSession; import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback; import com.android.internal.app.IVoiceInteractor; interface IVoiceInteractionManagerService { void showSession(in Bundle sessionArgs, int flags, String attributionTag); Loading Loading @@ -303,4 +304,14 @@ interface IVoiceInteractionManagerService { * Notifies when the session window is shown or hidden. */ void setSessionWindowVisible(in IBinder token, boolean visible); /** * Notifies when the Activity lifecycle event changed. * * @param activityToken The token of activity. * @param type The type of lifecycle event of the activity lifecycle. */ oneway void notifyActivityEventChanged( in IBinder activityToken, int type); }
services/core/java/com/android/server/am/ActivityManagerService.java +7 −4 Original line number Diff line number Diff line Loading @@ -2935,10 +2935,13 @@ public class ActivityManagerService extends IActivityManager.Stub || event == Event.ACTIVITY_DESTROYED)) { contentCaptureService.notifyActivityEvent(userId, activity, event); } // TODO(b/201234353): Move the logic to client side. if (mVoiceInteractionManagerProvider != null && (event == Event.ACTIVITY_PAUSED || event == Event.ACTIVITY_RESUMED || event == Event.ACTIVITY_STOPPED)) { mVoiceInteractionManagerProvider.notifyActivityEventChanged(); // Currently we have move most of logic to the client side. When the activity lifecycle // event changed, the client side will notify the VoiceInteractionManagerService. But // when the application process died, the VoiceInteractionManagerService will miss the // activity lifecycle event changed, so we still need ACTIVITY_DESTROYED event here to // know if the activity has been destroyed. if (mVoiceInteractionManagerProvider != null && event == Event.ACTIVITY_DESTROYED) { mVoiceInteractionManagerProvider.notifyActivityDestroyed(appToken); } } Loading