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

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

Further work on voice interaction services.

This makes VoiceInteractionSession a more first-class
concept.  Now the flow is that a VoiceInteractionService
calls startSession() when it wants to begin a session.
This will result in a new VoiceInteractionSession via the
VoiceInteractionSessionService containing it, and the
session at that point an decide what to do.  It can now
show UI, and it is what has access to the startVoiceActivity
API.

Change-Id: Ie2b85b3020ef1206d3f44b335b128d064e8f9935
parent 6b003c9e
Loading
Loading
Loading
Loading
+32 −2
Original line number Diff line number Diff line
@@ -25130,23 +25130,53 @@ package android.service.voice {
  public class VoiceInteractionService extends android.app.Service {
    ctor public VoiceInteractionService();
    method public android.os.IBinder onBind(android.content.Intent);
    method public void startVoiceActivity(android.content.Intent, android.os.Bundle);
    method public void startSession(android.os.Bundle);
    field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
    field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction";
  }
  public abstract class VoiceInteractionSession {
  public abstract class VoiceInteractionSession implements android.view.KeyEvent.Callback {
    ctor public VoiceInteractionSession(android.content.Context);
    ctor public VoiceInteractionSession(android.content.Context, android.os.Handler);
    method public void finish();
    method public android.view.LayoutInflater getLayoutInflater();
    method public android.app.Dialog getWindow();
    method public void hideWindow();
    method public void onBackPressed();
    method public abstract void onCancel(android.service.voice.VoiceInteractionSession.Request);
    method public void onCloseSystemDialogs();
    method public abstract void onCommand(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.String, android.os.Bundle);
    method public void onComputeInsets(android.service.voice.VoiceInteractionSession.Insets);
    method public abstract void onConfirm(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.String, android.os.Bundle);
    method public void onCreate(android.os.Bundle);
    method public android.view.View onCreateContentView();
    method public void onDestroy();
    method public abstract boolean[] onGetSupportedCommands(android.service.voice.VoiceInteractionSession.Caller, java.lang.String[]);
    method public boolean onKeyDown(int, android.view.KeyEvent);
    method public boolean onKeyLongPress(int, android.view.KeyEvent);
    method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
    method public boolean onKeyUp(int, android.view.KeyEvent);
    method public void onTaskFinished(android.content.Intent, int);
    method public void onTaskStarted(android.content.Intent, int);
    method public void setContentView(android.view.View);
    method public void setTheme(int);
    method public void showWindow();
    method public void startVoiceActivity(android.content.Intent);
  }
  public static class VoiceInteractionSession.Caller {
  }
  public static final class VoiceInteractionSession.Insets {
    ctor public VoiceInteractionSession.Insets();
    field public static final int TOUCHABLE_INSETS_CONTENT = 1; // 0x1
    field public static final int TOUCHABLE_INSETS_FRAME = 0; // 0x0
    field public static final int TOUCHABLE_INSETS_REGION = 3; // 0x3
    field public int contentTopInsets;
    field public int touchableInsets;
    field public final android.graphics.Region touchableRegion;
  }
  public static class VoiceInteractionSession.Request {
    method public void sendCancelResult();
    method public void sendCommandResult(boolean, android.os.Bundle);
+2 −1
Original line number Diff line number Diff line
@@ -664,7 +664,8 @@ public class InputMethodService extends AbstractInputMethodService {
        mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
        mInflater = (LayoutInflater)getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        mWindow = new SoftInputWindow(this, mTheme, mDispatcherState);
        mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
                false);
        if (mHardwareAccelerated) {
            mWindow.getWindow().addFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
        }
+68 −10
Original line number Diff line number Diff line
@@ -30,11 +30,20 @@ import android.view.WindowManager;
 * method window.  It will be displayed along the edge of the screen, moving
 * the application user interface away from it so that the focused item is
 * always visible.
 * @hide
 */
class SoftInputWindow extends Dialog {
public class SoftInputWindow extends Dialog {
    final String mName;
    final Callback mCallback;
    final KeyEvent.Callback mKeyEventCallback;
    final KeyEvent.DispatcherState mDispatcherState;
    final boolean mTakesFocus;
    private final Rect mBounds = new Rect();

    public interface Callback {
        public void onBackPressed();
    }

    public void setToken(IBinder token) {
        WindowManager.LayoutParams lp = getWindow().getAttributes();
        lp.token = token;
@@ -53,10 +62,15 @@ class SoftInputWindow extends Dialog {
     *        using styles. This theme is applied on top of the current theme in
     *        <var>context</var>. If 0, the default dialog theme will be used.
     */
    public SoftInputWindow(Context context, int theme,
            KeyEvent.DispatcherState dispatcherState) {
    public SoftInputWindow(Context context, String name, int theme, Callback callback,
            KeyEvent.Callback keyEventCallback, KeyEvent.DispatcherState dispatcherState,
            boolean takesFocus) {
        super(context, theme);
        mName = name;
        mCallback = callback;
        mKeyEventCallback = keyEventCallback;
        mDispatcherState = dispatcherState;
        mTakesFocus = takesFocus;
        initDockWindow();
    }

@@ -148,11 +162,47 @@ class SoftInputWindow extends Dialog {
        }
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (mKeyEventCallback != null && mKeyEventCallback.onKeyDown(keyCode, event)) {
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
        if (mKeyEventCallback != null && mKeyEventCallback.onKeyLongPress(keyCode, event)) {
            return true;
        }
        return super.onKeyLongPress(keyCode, event);
    }

    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (mKeyEventCallback != null && mKeyEventCallback.onKeyUp(keyCode, event)) {
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }

    public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
        if (mKeyEventCallback != null && mKeyEventCallback.onKeyMultiple(keyCode, count, event)) {
            return true;
        }
        return super.onKeyMultiple(keyCode, count, event);
    }

    public void onBackPressed() {
        if (mCallback != null) {
            mCallback.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }

    private void initDockWindow() {
        WindowManager.LayoutParams lp = getWindow().getAttributes();

        lp.type = WindowManager.LayoutParams.TYPE_INPUT_METHOD;
        lp.setTitle("InputMethod");
        lp.setTitle(mName);

        lp.gravity = Gravity.BOTTOM;
        lp.width = -1;
@@ -161,11 +211,19 @@ class SoftInputWindow extends Dialog {
        //lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;

        getWindow().setAttributes(lp);
        getWindow().setFlags(
                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |

        int windowSetFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
        int windowModFlags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN |
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                WindowManager.LayoutParams.FLAG_DIM_BEHIND);
                WindowManager.LayoutParams.FLAG_DIM_BEHIND;

        if (!mTakesFocus) {
            windowSetFlags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
        } else {
            windowSetFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
            windowModFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
        }

        getWindow().setFlags(windowSetFlags, windowModFlags);
    }
}
+6 −5
Original line number Diff line number Diff line
@@ -16,13 +16,14 @@

package android.service.voice;

import android.os.Bundle;

import com.android.internal.app.IVoiceInteractorCallback;
import com.android.internal.app.IVoiceInteractorRequest;
import android.content.Intent;

/**
 * @hide
 */
interface IVoiceInteractionSession {
oneway interface IVoiceInteractionSession {
    void taskStarted(in Intent intent, int taskId);
    void taskFinished(in Intent intent, int taskId);
    void closeSystemDialogs();
    void destroy();
}
+15 −4
Original line number Diff line number Diff line
@@ -27,6 +27,19 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import com.android.internal.app.IVoiceInteractionManagerService;

/**
 * Top-level service of the current global voice interactor, which is providing
 * support for hotwording, the back-end of a {@link android.app.VoiceInteractor}, etc.
 * The current VoiceInteractionService that has been selected by the user is kept
 * always running by the system, to allow it to do things like listen for hotwords
 * in the background to instigate voice interactions.
 *
 * <p>Because this service is always running, it should be kept as lightweight as
 * possible.  Heavy-weight operations (including showing UI) should be implemented
 * in the associated {@link android.service.voice.VoiceInteractionSessionService} when
 * an actual voice interaction is taking place, and that service should run in a
 * separate process from this one.
 */
public class VoiceInteractionService extends Service {
    /**
     * The {@link Intent} that must be declared as handled by the service.
@@ -51,11 +64,9 @@ public class VoiceInteractionService extends Service {

    IVoiceInteractionManagerService mSystemService;

    public void startVoiceActivity(Intent intent, Bundle sessionArgs) {
    public void startSession(Bundle args) {
        try {
            mSystemService.startVoiceActivity(intent,
                    intent.resolveType(getContentResolver()),
                    mInterface, sessionArgs);
            mSystemService.startSession(mInterface, args);
        } catch (RemoteException e) {
        }
    }
Loading