The voice assist may now be launched above the lockscreen

A possibility was introduced to launch voice assist over
the lockscreen using the left keyguard affordance.

Change-Id: Ic4618d24256b65441a50d77d0ef59b0ec99b6ead
This commit is contained in:
Selim Cinek
2015-04-24 16:46:13 -07:00
parent 08e474ca24
commit e70d653523
20 changed files with 361 additions and 83 deletions

View File

@@ -1190,6 +1190,7 @@ package android {
field public static final int summaryOff = 16843248; // 0x10101f0
field public static final int summaryOn = 16843247; // 0x10101ef
field public static final int supportsAssist = 16844012; // 0x10104ec
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844022; // 0x10104f6
field public static final int supportsRtl = 16843695; // 0x10103af
field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
field public static final int supportsUploading = 16843419; // 0x101029b
@@ -29141,6 +29142,7 @@ package android.service.voice {
method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback);
method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
method public android.os.IBinder onBind(android.content.Intent);
method public void onLaunchVoiceAssistFromKeyguard();
method public void onReady();
method public void onShutdown();
method public void showSession(android.os.Bundle, int);

View File

@@ -1265,6 +1265,7 @@ package android {
field public static final int summaryOff = 16843248; // 0x10101f0
field public static final int summaryOn = 16843247; // 0x10101ef
field public static final int supportsAssist = 16844012; // 0x10104ec
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844022; // 0x10104f6
field public static final int supportsRtl = 16843695; // 0x10103af
field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
field public static final int supportsUploading = 16843419; // 0x101029b
@@ -31253,6 +31254,7 @@ package android.service.voice {
method public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(java.lang.String, java.util.Locale, android.service.voice.AlwaysOnHotwordDetector.Callback);
method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
method public android.os.IBinder onBind(android.content.Intent);
method public void onLaunchVoiceAssistFromKeyguard();
method public void onReady();
method public void onShutdown();
method public void showSession(android.os.Bundle, int);

View File

@@ -23,4 +23,5 @@ oneway interface IVoiceInteractionService {
void ready();
void soundModelsChanged();
void shutdown();
void launchVoiceAssistFromKeyguard();
}

View File

@@ -98,6 +98,10 @@ public class VoiceInteractionService extends Service {
@Override public void soundModelsChanged() {
mHandler.sendEmptyMessage(MSG_SOUND_MODELS_CHANGED);
}
@Override
public void launchVoiceAssistFromKeyguard() throws RemoteException {
mHandler.sendEmptyMessage(MSG_LAUNCH_VOICE_ASSIST_FROM_KEYGUARD);
}
};
MyHandler mHandler;
@@ -113,6 +117,7 @@ public class VoiceInteractionService extends Service {
static final int MSG_READY = 1;
static final int MSG_SHUTDOWN = 2;
static final int MSG_SOUND_MODELS_CHANGED = 3;
static final int MSG_LAUNCH_VOICE_ASSIST_FROM_KEYGUARD = 4;
class MyHandler extends Handler {
@Override
@@ -127,12 +132,28 @@ public class VoiceInteractionService extends Service {
case MSG_SOUND_MODELS_CHANGED:
onSoundModelsChangedInternal();
break;
case MSG_LAUNCH_VOICE_ASSIST_FROM_KEYGUARD:
onLaunchVoiceAssistFromKeyguard();
break;
default:
super.handleMessage(msg);
}
}
}
/**
* Called when a user has activated an affordance to launch voice assist from the Keyguard.
*
* <p>This method will only be called if the VoiceInteractionService has set
* {@link android.R.attr#supportsLaunchVoiceAssistFromKeyguard} and the Keyguard is showing.</p>
*
* <p>A valid implementation must start a new activity that should use {@link
* android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} to display
* on top of the lock screen.</p>
*/
public void onLaunchVoiceAssistFromKeyguard() {
}
/**
* Check whether the given service component is the currently active
* VoiceInteractionService.

View File

@@ -44,6 +44,7 @@ public class VoiceInteractionServiceInfo {
private String mRecognitionService;
private String mSettingsActivity;
private boolean mSupportsAssist;
private boolean mSupportsLaunchFromKeyguard;
public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp)
throws PackageManager.NameNotFoundException {
@@ -98,6 +99,9 @@ public class VoiceInteractionServiceInfo {
mSupportsAssist = array.getBoolean(
com.android.internal.R.styleable.VoiceInteractionService_supportsAssist,
false);
mSupportsLaunchFromKeyguard = array.getBoolean(com.android.internal.
R.styleable.VoiceInteractionService_supportsLaunchVoiceAssistFromKeyguard,
false);
array.recycle();
if (mSessionService == null) {
mParseError = "No sessionService specified";
@@ -148,4 +152,8 @@ public class VoiceInteractionServiceInfo {
public boolean getSupportsAssist() {
return mSupportsAssist;
}
public boolean getSupportsLaunchFromKeyguard() {
return mSupportsLaunchFromKeyguard;
}
}

View File

@@ -96,6 +96,12 @@ interface IVoiceInteractionManagerService {
*/
void showSessionForActiveService(IVoiceInteractionSessionShowCallback showCallback);
/**
* Notifies the active service that a launch was requested from the Keyguard. This will only
* be called if {@link #activeServiceSupportsLaunchFromKeyguard()} returns true.
*/
void launchVoiceAssistFromKeyguard();
/**
* Indicates whether there is a voice session running (but not necessarily showing).
*/
@@ -106,4 +112,10 @@ interface IVoiceInteractionManagerService {
* assist gesture.
*/
boolean activeServiceSupportsAssist();
/**
* Indicates whether the currently active voice interaction service is capable of being launched
* from the lockscreen.
*/
boolean activeServiceSupportsLaunchFromKeyguard();
}

View File

@@ -7306,6 +7306,9 @@
<!-- Flag indicating whether this voice interaction service is capable of handling the
assist action. -->
<attr name="supportsAssist" format="boolean" />
<!-- Flag indicating whether this voice interaction service is capable of being launched
from the keyguard. -->
<attr name="supportsLaunchVoiceAssistFromKeyguard" format="boolean" />
</declare-styleable>
<!-- Use <code>voice-enrollment-application</code>

View File

@@ -2685,4 +2685,5 @@
<public type="attr" name="assistBlocked" />
<public type="attr" name="stylusButtonPressable" />
<public type="attr" name="supportsLaunchVoiceAssistFromKeyguard" />
</resources>

View File

@@ -0,0 +1,24 @@
<!--
Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="26.0dp"
android:height="26.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:pathData="M12.000000,14.000000c1.700000,0.000000 3.000000,-1.300000 3.000000,-3.000000l0.000000,-6.000000c0.000000,-1.700000 -1.300000,-3.000000 -3.000000,-3.000000c-1.700000,0.000000 -3.000000,1.300000 -3.000000,3.000000l0.000000,6.000000C9.000000,12.700000 10.300000,14.000000 12.000000,14.000000zM17.299999,11.000000c0.000000,3.000000 -2.500000,5.100000 -5.300000,5.100000c-2.800000,0.000000 -5.300000,-2.100000 -5.300000,-5.100000L5.000000,11.000000c0.000000,3.400000 2.700000,6.200000 6.000000,6.700000L11.000000,21.000000l2.000000,0.000000l0.000000,-3.300000c3.300000,-0.500000 6.000000,-3.300000 6.000000,-6.700000L17.299999,11.000001z"
android:fillColor="#FF000000"/>
</vector>

View File

@@ -52,7 +52,7 @@
android:contentDescription="@string/accessibility_camera_button" />
<com.android.systemui.statusbar.KeyguardAffordanceView
android:id="@+id/phone_button"
android:id="@+id/left_button"
android:layout_height="@dimen/keyguard_affordance_height"
android:layout_width="@dimen/keyguard_affordance_width"
android:layout_gravity="bottom|start"

View File

@@ -205,6 +205,8 @@
<string name="accessibility_camera_button">Camera</string>
<!-- Content description of the phone button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_phone_button">Phone</string>
<!-- Content description of the phone button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_voice_assist_button">Voice Assist</string>
<!-- Content description of the unlock button for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_unlock_button">Unlock</string>
<!-- Click action label for accessibility for the unlock button. [CHAR LIMIT=NONE] -->
@@ -212,6 +214,8 @@
<!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
<string name="phone_label">open phone</string>
<!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
<string name="voice_assist_label">open voice assist</string>
<!-- Click action label for accessibility for the phone button. [CHAR LIMIT=NONE] -->
<string name="camera_label">open camera</string>
<!-- Caption for "Recents resize" developer debug feature. [CHAR LIMIT=NONE] -->
<string name="recents_caption_resize">Select new task layout</string>
@@ -753,11 +757,14 @@
<!-- Shows when people have pressed the unlock icon to explain how to unlock. [CHAR LIMIT=60] -->
<string name="keyguard_unlock">Swipe up to unlock</string>
<!-- Shows when people have clicked at the left edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] -->
<string name="phone_hint">Swipe right for phone</string>
<!-- Shows when people have clicked on the phone icon [CHAR LIMIT=60] -->
<string name="phone_hint">Swipe from icon for phone</string>
<!-- Shows when people have clicked at the right edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] -->
<string name="camera_hint">Swipe left for camera</string>
<!-- Shows when people have clicked on the voice assist icon [CHAR LIMIT=60] -->
<string name="voice_hint">Swipe from icon for voice assist</string>
<!-- Shows when people have clicked on the camera icon [CHAR LIMIT=60] -->
<string name="camera_hint">Swipe from icon for camera</string>
<!-- Interruption level: None. [CHAR LIMIT=40] -->
<string name="interruption_level_none">Total silence</string>

View File

@@ -33,11 +33,11 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
/**
* Class to manage everything around the assist gesture.
* Class to manage everything related to assist in SystemUI.
*/
public class AssistGestureManager {
public class AssistManager {
private static final String TAG = "AssistGestureManager";
private static final String TAG = "AssistManager";
private static final String ASSIST_ICON_METADATA_NAME =
"com.android.systemui.action_assist_icon";
@@ -77,7 +77,7 @@ public class AssistGestureManager {
}
};
public AssistGestureManager(PhoneStatusBar bar, Context context) {
public AssistManager(PhoneStatusBar bar, Context context) {
mContext = context;
mBar = bar;
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
@@ -194,6 +194,14 @@ public class AssistGestureManager {
}
}
public void launchVoiceAssistFromKeyguard() {
try {
mVoiceInteractionManagerService.launchVoiceAssistFromKeyguard();
} catch (RemoteException e) {
Log.w(TAG, "Failed to call launchVoiceAssistFromKeyguard", e);
}
}
private boolean getVoiceInteractorSupportsAssistGesture() {
try {
return mVoiceInteractionManagerService.activeServiceSupportsAssist();
@@ -203,7 +211,16 @@ public class AssistGestureManager {
}
}
private ComponentName getVoiceInteractorComponentName() {
public boolean canVoiceAssistBeLaunchedFromKeyguard() {
try {
return mVoiceInteractionManagerService.activeServiceSupportsLaunchFromKeyguard();
} catch (RemoteException e) {
Log.w(TAG, "Failed to call activeServiceSupportsLaunchFromKeyguard", e);
return false;
}
}
public ComponentName getVoiceInteractorComponentName() {
try {
return mVoiceInteractionManagerService.getActiveServiceComponentName();
} catch (RemoteException e) {

View File

@@ -25,4 +25,5 @@ import android.content.Intent;
*/
public interface ActivityStarter {
public void startActivity(Intent intent, boolean dismissShade);
void preventNextAnimation();
}

View File

@@ -131,6 +131,10 @@ public class KeyguardAffordanceHelper {
mCenterIcon = mCallback.getCenterIcon();
mRightIcon = mCallback.getRightIcon();
mRightIcon.setIsLeft(false);
updatePreviews();
}
public void updatePreviews() {
mLeftIcon.setPreviewView(mCallback.getLeftPreview());
mRightIcon.setPreviewView(mCallback.getRightPreview());
}

View File

@@ -25,17 +25,13 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.hardware.fingerprint.FingerprintManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.Vibrator;
import android.provider.MediaStore;
import android.provider.Settings;
import android.telecom.TelecomManager;
import android.util.AttributeSet;
import android.util.Log;
@@ -54,6 +50,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardAffordanceView;
import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -85,12 +82,12 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private static final long TRANSIENT_FP_ERROR_TIMEOUT = 1300;
private KeyguardAffordanceView mCameraImageView;
private KeyguardAffordanceView mPhoneImageView;
private KeyguardAffordanceView mLeftAffordanceView;
private LockIcon mLockIcon;
private TextView mIndicationText;
private ViewGroup mPreviewContainer;
private View mPhonePreview;
private View mLeftPreview;
private View mCameraPreview;
private ActivityStarter mActivityStarter;
@@ -104,6 +101,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private final Interpolator mLinearOutSlowInInterpolator;
private boolean mPrewarmSent;
private boolean mLeftIsVoiceAssist;
private AssistManager mAssistManager;
public KeyguardBottomAreaView(Context context) {
this(context, null);
@@ -133,8 +132,12 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
label = getResources().getString(R.string.unlock_label);
} else if (host == mCameraImageView) {
label = getResources().getString(R.string.camera_label);
} else if (host == mPhoneImageView) {
label = getResources().getString(R.string.phone_label);
} else if (host == mLeftAffordanceView) {
if (mLeftIsVoiceAssist) {
label = getResources().getString(R.string.voice_assist_label);
} else {
label = getResources().getString(R.string.phone_label);
}
}
info.addAction(new AccessibilityAction(ACTION_CLICK, label));
}
@@ -149,8 +152,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
} else if (host == mCameraImageView) {
launchCamera();
return true;
} else if (host == mPhoneImageView) {
launchPhone();
} else if (host == mLeftAffordanceView) {
launchLeftAffordance();
return true;
}
}
@@ -164,29 +167,28 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mLockPatternUtils = new LockPatternUtils(mContext);
mPreviewContainer = (ViewGroup) findViewById(R.id.preview_container);
mCameraImageView = (KeyguardAffordanceView) findViewById(R.id.camera_button);
mPhoneImageView = (KeyguardAffordanceView) findViewById(R.id.phone_button);
mLeftAffordanceView = (KeyguardAffordanceView) findViewById(R.id.left_button);
mLockIcon = (LockIcon) findViewById(R.id.lock_icon);
mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text);
watchForCameraPolicyChanges();
updateCameraVisibility();
updatePhoneVisibility();
mUnlockMethodCache = UnlockMethodCache.getInstance(getContext());
mUnlockMethodCache.addListener(this);
mLockIcon.update();
setClipChildren(false);
setClipToPadding(false);
mPreviewInflater = new PreviewInflater(mContext, new LockPatternUtils(mContext));
inflatePreviews();
inflateCameraPreview();
mLockIcon.setOnClickListener(this);
mLockIcon.setOnLongClickListener(this);
mCameraImageView.setOnClickListener(this);
mPhoneImageView.setOnClickListener(this);
mLeftAffordanceView.setOnClickListener(this);
initAccessibility();
}
private void initAccessibility() {
mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate);
mPhoneImageView.setAccessibilityDelegate(mAccessibilityDelegate);
mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate);
mCameraImageView.setAccessibilityDelegate(mAccessibilityDelegate);
}
@@ -247,9 +249,26 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
}
private void updatePhoneVisibility() {
boolean visible = isPhoneVisible();
mPhoneImageView.setVisibility(visible ? View.VISIBLE : View.GONE);
private void updateLeftAffordanceIcon() {
mLeftIsVoiceAssist = canLaunchVoiceAssist();
int drawableId;
int contentDescription;
if (mLeftIsVoiceAssist) {
mLeftAffordanceView.setVisibility(View.VISIBLE);
drawableId = R.drawable.ic_mic_26dp;
contentDescription = R.string.accessibility_voice_assist_button;
} else {
boolean visible = isPhoneVisible();
mLeftAffordanceView.setVisibility(visible ? View.VISIBLE : View.GONE);
drawableId = R.drawable.ic_phone_24dp;
contentDescription = R.string.accessibility_phone_button;
}
mLeftAffordanceView.setImageDrawable(mContext.getDrawable(drawableId));
mLeftAffordanceView.setContentDescription(mContext.getString(contentDescription));
}
public boolean isLeftVoiceAssist() {
return mLeftIsVoiceAssist;
}
private boolean isPhoneVisible() {
@@ -287,9 +306,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
@Override
public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) {
mCameraImageView.setClickable(touchExplorationEnabled);
mPhoneImageView.setClickable(touchExplorationEnabled);
mLeftAffordanceView.setClickable(touchExplorationEnabled);
mCameraImageView.setFocusable(accessibilityEnabled);
mPhoneImageView.setFocusable(accessibilityEnabled);
mLeftAffordanceView.setFocusable(accessibilityEnabled);
mLockIcon.update();
}
@@ -297,8 +316,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
public void onClick(View v) {
if (v == mCameraImageView) {
launchCamera();
} else if (v == mPhoneImageView) {
launchPhone();
} else if (v == mLeftAffordanceView) {
launchLeftAffordance();
} if (v == mLockIcon) {
if (!mAccessibilityController.isAccessibilityEnabled()) {
handleTrustCircleClick();
@@ -363,6 +382,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
@Override
public void run() {
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
mActivityStarter.preventNextAnimation();
}
});
} else {
@@ -373,7 +393,35 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
}
public void launchPhone() {
public void launchLeftAffordance() {
if (mLeftIsVoiceAssist) {
launchVoiceAssist();
} else {
launchPhone();
}
}
private void launchVoiceAssist() {
Runnable runnable = new Runnable() {
@Override
public void run() {
mAssistManager.launchVoiceAssistFromKeyguard();
mActivityStarter.preventNextAnimation();
}
};
if (mPhoneStatusBar.isKeyguardCurrentlySecure()) {
AsyncTask.execute(runnable);
} else {
mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, false /* dismissShade */,
false /* afterKeyguardGone */);
}
}
private boolean canLaunchVoiceAssist() {
return mAssistManager.canVoiceAssistBeLaunchedFromKeyguard();
}
private void launchPhone() {
final TelecomManager tm = TelecomManager.from(mContext);
if (tm.isInCall()) {
AsyncTask.execute(new Runnable() {
@@ -397,19 +445,19 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
}
}
public KeyguardAffordanceView getPhoneView() {
return mPhoneImageView;
public KeyguardAffordanceView getLeftView() {
return mLeftAffordanceView;
}
public KeyguardAffordanceView getCameraView() {
public KeyguardAffordanceView getRightView() {
return mCameraImageView;
}
public View getPhonePreview() {
return mPhonePreview;
public View getLeftPreview() {
return mLeftPreview;
}
public View getCameraPreview() {
public View getRightPreview() {
return mCameraPreview;
}
@@ -432,23 +480,35 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
updateCameraVisibility();
}
private void inflatePreviews() {
mPhonePreview = mPreviewInflater.inflatePreview(PHONE_INTENT);
private void inflateCameraPreview() {
mCameraPreview = mPreviewInflater.inflatePreview(getCameraIntent());
if (mPhonePreview != null) {
mPreviewContainer.addView(mPhonePreview);
mPhonePreview.setVisibility(View.INVISIBLE);
}
if (mCameraPreview != null) {
mPreviewContainer.addView(mCameraPreview);
mCameraPreview.setVisibility(View.INVISIBLE);
}
}
private void updateLeftPreview() {
View previewBefore = mLeftPreview;
if (previewBefore != null) {
mPreviewContainer.removeView(previewBefore);
}
if (mLeftIsVoiceAssist) {
mLeftPreview = mPreviewInflater.inflatePreviewFromService(
mAssistManager.getVoiceInteractorComponentName());
} else {
mLeftPreview = mPreviewInflater.inflatePreview(PHONE_INTENT);
}
if (mLeftPreview != null) {
mPreviewContainer.addView(mLeftPreview);
mLeftPreview.setVisibility(View.INVISIBLE);
}
}
public void startFinishDozeAnimation() {
long delay = 0;
if (mPhoneImageView.getVisibility() == View.VISIBLE) {
startFinishDozeAnimationElement(mPhoneImageView, delay);
if (mLeftAffordanceView.getVisibility() == View.VISIBLE) {
startFinishDozeAnimationElement(mLeftAffordanceView, delay);
delay += DOZE_ANIMATION_STAGGER_DELAY;
}
startFinishDozeAnimationElement(mLockIcon, delay);
@@ -543,4 +603,14 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
KeyguardIndicationController keyguardIndicationController) {
mIndicationController = keyguardIndicationController;
}
public void setAssistManager(AssistManager assistManager) {
mAssistManager = assistManager;
updateLeftAffordance();
}
public void updateLeftAffordance() {
updateLeftAffordanceIcon();
updateLeftPreview();
}
}

View File

@@ -952,6 +952,10 @@ public class NotificationPanelView extends PanelView implements
} else {
mKeyguardStatusBar.setAlpha(1f);
mKeyguardStatusBar.setVisibility(keyguardShowing ? View.VISIBLE : View.INVISIBLE);
if (keyguardShowing && oldState != mStatusBarState) {
mKeyguardBottomArea.updateLeftAffordance();
mAfforanceHelper.updatePreviews();
}
}
resetVerticalPanelPosition();
updateQsState();
@@ -1831,7 +1835,7 @@ public class NotificationPanelView extends PanelView implements
if (start) {
EventLogTags.writeSysuiLockscreenGesture(
EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_DIALER, lengthDp, velocityDp);
mKeyguardBottomArea.launchPhone();
mKeyguardBottomArea.launchLeftAffordance();
} else {
EventLogTags.writeSysuiLockscreenGesture(
EventLogConstants.SYSUI_LOCKSCREEN_GESTURE_SWIPE_CAMERA, lengthDp, velocityDp);
@@ -1912,15 +1916,19 @@ public class NotificationPanelView extends PanelView implements
if (rightIcon) {
mStatusBar.onCameraHintStarted();
} else {
mStatusBar.onPhoneHintStarted();
if (mKeyguardBottomArea.isLeftVoiceAssist()) {
mStatusBar.onVoiceAssistHintStarted();
} else {
mStatusBar.onPhoneHintStarted();
}
}
}
@Override
public KeyguardAffordanceView getLeftIcon() {
return getLayoutDirection() == LAYOUT_DIRECTION_RTL
? mKeyguardBottomArea.getCameraView()
: mKeyguardBottomArea.getPhoneView();
? mKeyguardBottomArea.getRightView()
: mKeyguardBottomArea.getLeftView();
}
@Override
@@ -1931,22 +1939,22 @@ public class NotificationPanelView extends PanelView implements
@Override
public KeyguardAffordanceView getRightIcon() {
return getLayoutDirection() == LAYOUT_DIRECTION_RTL
? mKeyguardBottomArea.getPhoneView()
: mKeyguardBottomArea.getCameraView();
? mKeyguardBottomArea.getLeftView()
: mKeyguardBottomArea.getRightView();
}
@Override
public View getLeftPreview() {
return getLayoutDirection() == LAYOUT_DIRECTION_RTL
? mKeyguardBottomArea.getCameraPreview()
: mKeyguardBottomArea.getPhonePreview();
? mKeyguardBottomArea.getRightPreview()
: mKeyguardBottomArea.getLeftPreview();
}
@Override
public View getRightPreview() {
return getLayoutDirection() == LAYOUT_DIRECTION_RTL
? mKeyguardBottomArea.getPhonePreview()
: mKeyguardBottomArea.getCameraPreview();
? mKeyguardBottomArea.getLeftPreview()
: mKeyguardBottomArea.getRightPreview();
}
@Override

View File

@@ -101,7 +101,7 @@ import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.assist.AssistGestureManager;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.doze.DozeHost;
import com.android.systemui.doze.DozeLog;
import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -323,7 +323,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private int mNavigationIconHints = 0;
private HandlerThread mHandlerThread;
private AssistGestureManager mAssistGestureManager;
private AssistManager mAssistManager;
// ensure quick settings is disabled until the current user makes it through the setup wizard
private boolean mUserSetup = false;
@@ -645,8 +645,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
new NavigationBarView.OnVerticalChangedListener() {
@Override
public void onVerticalChanged(boolean isVertical) {
if (mAssistGestureManager != null) {
mAssistGestureManager.onConfigurationChanged();
if (mAssistManager != null) {
mAssistManager.onConfigurationChanged();
}
mNotificationPanel.setQsScrimEnabled(!isVertical);
}
@@ -662,6 +662,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// no window manager? good luck with that
}
mAssistManager = new AssistManager(this, context);
// figure out which pixel-format to use for the status bar.
mPixelFormat = PixelFormat.OPAQUE;
@@ -720,6 +722,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardBottomArea =
(KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
mKeyguardBottomArea.setActivityStarter(this);
mKeyguardBottomArea.setAssistManager(mAssistManager);
mKeyguardIndicationController = new KeyguardIndicationController(mContext,
(KeyguardIndicationTextView) mStatusBarWindow.findViewById(
R.id.keyguard_indication_text));
@@ -841,7 +844,6 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mBroadcastReceiver.onReceive(mContext,
new Intent(pm.isScreenOn() ? Intent.ACTION_SCREEN_ON : Intent.ACTION_SCREEN_OFF));
mAssistGestureManager = new AssistGestureManager(this, context);
// receive broadcasts
IntentFilter filter = new IntentFilter();
@@ -964,7 +966,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public void invokeAssistGesture(boolean vibrate) {
mHandler.removeCallbacks(mInvokeAssist);
mAssistGestureManager.onGestureInvoked(vibrate);
mAssistManager.onGestureInvoked(vibrate);
}
public int getStatusBarHeight() {
@@ -1044,7 +1046,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mNavigationBarView.getBackButton().setLongClickable(true);
mNavigationBarView.getBackButton().setOnLongClickListener(mLongPressBackRecentsListener);
mNavigationBarView.getHomeButton().setOnTouchListener(mHomeActionListener);
mAssistGestureManager.onConfigurationChanged();
mAssistManager.onConfigurationChanged();
}
// For small-screen devices (read: phones) that lack hardware navigation buttons
@@ -1805,6 +1807,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
startActivityDismissingKeyguard(intent, false, dismissShade);
}
@Override
public void preventNextAnimation() {
overrideActivityPendingAppTransition(true /* keyguardShowing */);
}
public void setQsExpanded(boolean expanded) {
mStatusBarWindowManager.setQsExpanded(expanded);
}
@@ -1924,6 +1931,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
return mHeadsUpManager.isSnoozed(sbn.getPackageName());
}
public boolean isKeyguardCurrentlySecure() {
return !mUnlockMethodCache.isCurrentlyInsecure();
}
/**
* All changes to the status bar and notifications funnel through here and are batched.
*/
@@ -2650,6 +2661,23 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
mContext, intent, mCurrentUserId);
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
Runnable runnable = new Runnable() {
public void run() {
intent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
mContext.startActivityAsUser(
intent, new UserHandle(UserHandle.USER_CURRENT));
overrideActivityPendingAppTransition(
keyguardShowing && !afterKeyguardGone);
}
};
executeRunnableDismissingKeyguard(runnable, dismissShade, afterKeyguardGone);
}
public void executeRunnableDismissingKeyguard(final Runnable runnable,
final boolean dismissShade,
final boolean afterKeyguardGone) {
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
dismissKeyguardThenExecute(new OnDismissAction() {
@Override
public boolean onDismiss() {
@@ -2660,12 +2688,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
ActivityManagerNative.getDefault()
.keyguardWaitingForActivityDrawn();
}
intent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
mContext.startActivityAsUser(
intent, new UserHandle(UserHandle.USER_CURRENT));
overrideActivityPendingAppTransition(
keyguardShowing && !afterKeyguardGone);
if (runnable != null) {
runnable.run();
}
} catch (RemoteException e) {
}
}
@@ -3019,7 +3044,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mHandlerThread = null;
}
mContext.unregisterReceiver(mBroadcastReceiver);
mAssistGestureManager.destroy();
mAssistManager.destroy();
}
private boolean mDemoModeAllowed;
@@ -3467,6 +3492,10 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardIndicationController.showTransientIndication(R.string.camera_hint);
}
public void onVoiceAssistHintStarted() {
mKeyguardIndicationController.showTransientIndication(R.string.voice_hint);
}
public void onPhoneHintStarted() {
mKeyguardIndicationController.showTransientIndication(R.string.phone_hint);
}

View File

@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -50,6 +51,15 @@ public class PreviewInflater {
public View inflatePreview(Intent intent) {
WidgetInfo info = getWidgetInfo(intent);
return inflatePreview(info);
}
public View inflatePreviewFromService(ComponentName componentName) {
WidgetInfo info = getWidgetInfoFromService(componentName);
return inflatePreview(info);
}
private KeyguardPreviewContainer inflatePreview(WidgetInfo info) {
if (info == null) {
return null;
}
@@ -77,8 +87,36 @@ public class PreviewInflater {
return widgetView;
}
private WidgetInfo getWidgetInfo(Intent intent) {
private WidgetInfo getWidgetInfoFromService(ComponentName componentName) {
PackageManager packageManager = mContext.getPackageManager();
// Look for the preview specified in the service meta-data
try {
Bundle metaData = packageManager.getServiceInfo(
componentName, PackageManager.GET_META_DATA).metaData;
return getWidgetInfoFromMetaData(componentName.getPackageName(), metaData);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Failed to load preview; " + componentName.flattenToShortString()
+ " not found", e);
}
return null;
}
private WidgetInfo getWidgetInfoFromMetaData(String contextPackage,
Bundle metaData) {
if (metaData == null) {
return null;
}
int layoutId = metaData.getInt(META_DATA_KEYGUARD_LAYOUT);
if (layoutId == 0) {
return null;
}
WidgetInfo info = new WidgetInfo();
info.contextPackage = contextPackage;
info.layoutId = layoutId;
return info;
}
private WidgetInfo getWidgetInfo(Intent intent) {
PackageManager packageManager = mContext.getPackageManager();
final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
intent, PackageManager.MATCH_DEFAULT_ONLY, KeyguardUpdateMonitor.getCurrentUser());
@@ -94,16 +132,8 @@ public class PreviewInflater {
if (resolved == null || resolved.activityInfo == null) {
return null;
}
if (resolved.activityInfo.metaData == null || resolved.activityInfo.metaData.isEmpty()) {
return null;
}
int layoutId = resolved.activityInfo.metaData.getInt(META_DATA_KEYGUARD_LAYOUT);
if (layoutId == 0) {
return null;
}
info.contextPackage = resolved.activityInfo.packageName;
info.layoutId = layoutId;
return info;
return getWidgetInfoFromMetaData(resolved.activityInfo.packageName,
resolved.activityInfo.metaData);
}
public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent,

View File

@@ -28,7 +28,6 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
@@ -725,6 +724,24 @@ public class VoiceInteractionManagerService extends SystemService {
}
}
@Override
public void launchVoiceAssistFromKeyguard() {
enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
synchronized (this) {
if (mImpl == null) {
Slog.w(TAG, "launchVoiceAssistFromKeyguard without running voice interaction"
+ "service");
return;
}
final long caller = Binder.clearCallingIdentity();
try {
mImpl.launchVoiceAssistFromKeyguard();
} finally {
Binder.restoreCallingIdentity(caller);
}
}
}
@Override
public boolean isSessionRunning() {
enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
@@ -741,6 +758,14 @@ public class VoiceInteractionManagerService extends SystemService {
}
}
@Override
public boolean activeServiceSupportsLaunchFromKeyguard() throws RemoteException {
enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE);
synchronized (this) {
return mImpl != null && mImpl.mInfo.getSupportsLaunchFromKeyguard();
}
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)

View File

@@ -235,6 +235,18 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
}
public void launchVoiceAssistFromKeyguard() {
if (mService == null) {
Slog.w(TAG, "Not bound to voice interaction service " + mComponent);
return;
}
try {
mService.launchVoiceAssistFromKeyguard();
} catch (RemoteException e) {
Slog.w(TAG, "RemoteException while calling launchVoiceAssistFromKeyguard", e);
}
}
void shutdownLocked() {
try {
if (mService != null) {
@@ -256,6 +268,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
void notifySoundModelsChangedLocked() {
if (mService == null) {
Slog.w(TAG, "Not bound to voice interaction service " + mComponent);
return;
}
try {
mService.soundModelsChanged();