diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/IntentButtonProvider.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/IntentButtonProvider.java new file mode 100644 index 0000000000000..1b8efa79ad739 --- /dev/null +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/IntentButtonProvider.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2016 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. + */ + +package com.android.systemui.plugins; + +import android.content.Intent; +import android.graphics.drawable.Drawable; + +/** + * An Intent Button represents a triggerable element in SysUI that consists of an + * Icon and an intent to trigger when it is activated (clicked, swiped, etc.). + */ +public interface IntentButtonProvider extends Plugin { + + public static final int VERSION = 1; + + public IntentButton getIntentButton(); + + public interface IntentButton { + public static class IconState { + public boolean isVisible = true; + public CharSequence contentDescription = null; + public Drawable drawable; + } + + public IconState getIcon(); + + public Intent getIntent(); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java index 0a391ebda5be1..427014714040d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java @@ -61,6 +61,11 @@ import com.android.systemui.EventLogTags; import com.android.systemui.Interpolators; import com.android.systemui.R; import com.android.systemui.assist.AssistManager; +import com.android.systemui.plugins.IntentButtonProvider; +import com.android.systemui.plugins.IntentButtonProvider.IntentButton; +import com.android.systemui.plugins.IntentButtonProvider.IntentButton.IconState; +import com.android.systemui.plugins.PluginListener; +import com.android.systemui.plugins.PluginManager; import com.android.systemui.plugins.qs.QSContainer.ActivityStarter; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.KeyguardAffordanceView; @@ -86,6 +91,11 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL public static final String EXTRA_CAMERA_LAUNCH_SOURCE = "com.android.systemui.camera_launch_source"; + private static final String LEFT_BUTTON_PLUGIN + = "com.android.systemui.action.PLUGIN_LOCKSCREEN_LEFT_BUTTON"; + private static final String RIGHT_BUTTON_PLUGIN + = "com.android.systemui.action.PLUGIN_LOCKSCREEN_RIGHT_BUTTON"; + private static final Intent SECURE_CAMERA_INTENT = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE) .addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); @@ -95,7 +105,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private static final int DOZE_ANIMATION_STAGGER_DELAY = 48; private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250; - private KeyguardAffordanceView mCameraImageView; + private KeyguardAffordanceView mRightAffordanceView; private KeyguardAffordanceView mLeftAffordanceView; private LockIcon mLockIcon; private TextView mIndicationText; @@ -132,6 +142,9 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private boolean mLeftIsVoiceAssist; private AssistManager mAssistManager; + private IntentButton mRightButton = new DefaultRightButton(); + private IntentButton mLeftButton = new DefaultLeftButton(); + public KeyguardBottomAreaView(Context context) { this(context, null); } @@ -156,7 +169,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL String label = null; if (host == mLockIcon) { label = getResources().getString(R.string.unlock_label); - } else if (host == mCameraImageView) { + } else if (host == mRightAffordanceView) { label = getResources().getString(R.string.camera_label); } else if (host == mLeftAffordanceView) { if (mLeftIsVoiceAssist) { @@ -175,7 +188,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mPhoneStatusBar.animateCollapsePanels( CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL, true /* force */); return true; - } else if (host == mCameraImageView) { + } else if (host == mRightAffordanceView) { launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE); return true; } else if (host == mLeftAffordanceView) { @@ -192,7 +205,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL super.onFinishInflate(); mLockPatternUtils = new LockPatternUtils(mContext); mPreviewContainer = (ViewGroup) findViewById(R.id.preview_container); - mCameraImageView = (KeyguardAffordanceView) findViewById(R.id.camera_button); + mRightAffordanceView = (KeyguardAffordanceView) findViewById(R.id.camera_button); mLeftAffordanceView = (KeyguardAffordanceView) findViewById(R.id.left_button); mLockIcon = (LockIcon) findViewById(R.id.lock_icon); mIndicationText = (TextView) findViewById(R.id.keyguard_indication_text); @@ -207,15 +220,31 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL inflateCameraPreview(); mLockIcon.setOnClickListener(this); mLockIcon.setOnLongClickListener(this); - mCameraImageView.setOnClickListener(this); + mRightAffordanceView.setOnClickListener(this); mLeftAffordanceView.setOnClickListener(this); initAccessibility(); } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + PluginManager.getInstance(getContext()).addPluginListener(RIGHT_BUTTON_PLUGIN, + mRightListener, IntentButtonProvider.VERSION, false /* Only allow one */); + PluginManager.getInstance(getContext()).addPluginListener(LEFT_BUTTON_PLUGIN, + mLeftListener, IntentButtonProvider.VERSION, false /* Only allow one */); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + PluginManager.getInstance(getContext()).removePluginListener(mRightListener); + PluginManager.getInstance(getContext()).removePluginListener(mLeftListener); + } + private void initAccessibility() { mLockIcon.setAccessibilityDelegate(mAccessibilityDelegate); mLeftAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate); - mCameraImageView.setAccessibilityDelegate(mAccessibilityDelegate); + mRightAffordanceView.setAccessibilityDelegate(mAccessibilityDelegate); } @Override @@ -234,11 +263,11 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL getResources().getDimensionPixelSize( com.android.internal.R.dimen.text_size_small_material)); - ViewGroup.LayoutParams lp = mCameraImageView.getLayoutParams(); + ViewGroup.LayoutParams lp = mRightAffordanceView.getLayoutParams(); lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width); lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_height); - mCameraImageView.setLayoutParams(lp); - mCameraImageView.setImageDrawable(mContext.getDrawable(R.drawable.ic_camera_alt_24dp)); + mRightAffordanceView.setLayoutParams(lp); + updateRightAffordanceIcon(); lp = mLockIcon.getLayoutParams(); lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_width); @@ -253,6 +282,13 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL updateLeftAffordanceIcon(); } + private void updateRightAffordanceIcon() { + IconState state = mRightButton.getIcon(); + mRightAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE); + mRightAffordanceView.setImageDrawable(state.drawable); + mRightAffordanceView.setContentDescription(state.contentDescription); + } + public void setActivityStarter(ActivityStarter activityStarter) { mActivityStarter = activityStarter; } @@ -279,11 +315,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } private Intent getCameraIntent() { - KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); - boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer( - KeyguardUpdateMonitor.getCurrentUser()); - boolean secure = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()); - return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT; + return mRightButton.getIntent(); } /** @@ -296,33 +328,19 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } private void updateCameraVisibility() { - if (mCameraImageView == null) { + if (mRightAffordanceView == null) { // Things are not set up yet; reply hazy, ask again later return; } - ResolveInfo resolved = resolveCameraIntent(); - boolean visible = !isCameraDisabledByDpm() && resolved != null - && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance) - && mUserSetupComplete; - mCameraImageView.setVisibility(visible ? View.VISIBLE : View.GONE); + mRightAffordanceView.setVisibility(mRightButton.getIcon().isVisible + ? View.VISIBLE : View.GONE); } private void updateLeftAffordanceIcon() { - mLeftIsVoiceAssist = canLaunchVoiceAssist(); - int drawableId; - int contentDescription; - boolean visible = mUserSetupComplete; - if (mLeftIsVoiceAssist) { - drawableId = R.drawable.ic_mic_26dp; - contentDescription = R.string.accessibility_voice_assist_button; - } else { - visible &= isPhoneVisible(); - drawableId = R.drawable.ic_phone_24dp; - contentDescription = R.string.accessibility_phone_button; - } - mLeftAffordanceView.setVisibility(visible ? View.VISIBLE : View.GONE); - mLeftAffordanceView.setImageDrawable(mContext.getDrawable(drawableId)); - mLeftAffordanceView.setContentDescription(mContext.getString(contentDescription)); + IconState state = mLeftButton.getIcon(); + mLeftAffordanceView.setVisibility(state.isVisible ? View.VISIBLE : View.GONE); + mLeftAffordanceView.setImageDrawable(state.drawable); + mLeftAffordanceView.setContentDescription(state.contentDescription); } public boolean isLeftVoiceAssist() { @@ -363,16 +381,16 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL @Override public void onStateChanged(boolean accessibilityEnabled, boolean touchExplorationEnabled) { - mCameraImageView.setClickable(touchExplorationEnabled); + mRightAffordanceView.setClickable(touchExplorationEnabled); mLeftAffordanceView.setClickable(touchExplorationEnabled); - mCameraImageView.setFocusable(accessibilityEnabled); + mRightAffordanceView.setFocusable(accessibilityEnabled); mLeftAffordanceView.setFocusable(accessibilityEnabled); mLockIcon.update(); } @Override public void onClick(View v) { - if (v == mCameraImageView) { + if (v == mRightAffordanceView) { launchCamera(CAMERA_LAUNCH_SOURCE_AFFORDANCE); } else if (v == mLeftAffordanceView) { launchLeftAffordance(); @@ -541,7 +559,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } }); } else { - mActivityStarter.startActivity(PHONE_INTENT, false /* dismissShade */); + mActivityStarter.startActivity(mLeftButton.getIntent(), false /* dismissShade */); } } @@ -560,7 +578,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } public KeyguardAffordanceView getRightView() { - return mCameraImageView; + return mRightAffordanceView; } public View getLeftPreview() { @@ -613,7 +631,7 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL mLeftPreview = mPreviewInflater.inflatePreviewFromService( mAssistManager.getVoiceInteractorComponentName()); } else { - mLeftPreview = mPreviewInflater.inflatePreview(PHONE_INTENT); + mLeftPreview = mPreviewInflater.inflatePreview(mLeftButton.getIntent()); } if (mLeftPreview != null) { mPreviewContainer.addView(mLeftPreview); @@ -629,8 +647,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL } startFinishDozeAnimationElement(mLockIcon, delay); delay += DOZE_ANIMATION_STAGGER_DELAY; - if (mCameraImageView.getVisibility() == View.VISIBLE) { - startFinishDozeAnimationElement(mCameraImageView, delay); + if (mRightAffordanceView.getVisibility() == View.VISIBLE) { + startFinishDozeAnimationElement(mRightAffordanceView, delay); } mIndicationText.setAlpha(0f); mIndicationText.animate() @@ -664,46 +682,46 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback = new KeyguardUpdateMonitorCallback() { - @Override - public void onUserSwitchComplete(int userId) { - updateCameraVisibility(); - } + @Override + public void onUserSwitchComplete(int userId) { + updateCameraVisibility(); + } - @Override - public void onStartedWakingUp() { - mLockIcon.setDeviceInteractive(true); - } + @Override + public void onStartedWakingUp() { + mLockIcon.setDeviceInteractive(true); + } - @Override - public void onFinishedGoingToSleep(int why) { - mLockIcon.setDeviceInteractive(false); - } + @Override + public void onFinishedGoingToSleep(int why) { + mLockIcon.setDeviceInteractive(false); + } - @Override - public void onScreenTurnedOn() { - mLockIcon.setScreenOn(true); - } + @Override + public void onScreenTurnedOn() { + mLockIcon.setScreenOn(true); + } - @Override - public void onScreenTurnedOff() { - mLockIcon.setScreenOn(false); - } + @Override + public void onScreenTurnedOff() { + mLockIcon.setScreenOn(false); + } - @Override - public void onKeyguardVisibilityChanged(boolean showing) { - mLockIcon.update(); - } + @Override + public void onKeyguardVisibilityChanged(boolean showing) { + mLockIcon.update(); + } - @Override - public void onFingerprintRunningStateChanged(boolean running) { - mLockIcon.update(); - } + @Override + public void onFingerprintRunningStateChanged(boolean running) { + mLockIcon.update(); + } - @Override - public void onStrongAuthStateChanged(int userId) { - mLockIcon.update(); - } - }; + @Override + public void onStrongAuthStateChanged(int userId) { + mLockIcon.update(); + } + }; public void setKeyguardIndicationController( KeyguardIndicationController keyguardIndicationController) { @@ -724,4 +742,96 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL updateLeftAffordance(); inflateCameraPreview(); } + + private void setRightButton(IntentButton button) { + mRightButton = button; + updateRightAffordanceIcon(); + updateCameraVisibility(); + inflateCameraPreview(); + } + + private void setLeftButton(IntentButton button) { + mLeftButton = button; + mLeftIsVoiceAssist = false; + updateLeftAffordance(); + } + + private final PluginListener mRightListener = + new PluginListener() { + @Override + public void onPluginConnected(IntentButtonProvider plugin) { + setRightButton(plugin.getIntentButton()); + } + + @Override + public void onPluginDisconnected(IntentButtonProvider plugin) { + setRightButton(new DefaultRightButton()); + } + }; + + private final PluginListener mLeftListener = + new PluginListener() { + @Override + public void onPluginConnected(IntentButtonProvider plugin) { + setLeftButton(plugin.getIntentButton()); + } + + @Override + public void onPluginDisconnected(IntentButtonProvider plugin) { + setLeftButton(new DefaultLeftButton()); + } + }; + + private class DefaultLeftButton implements IntentButton { + + private IconState mIconState = new IconState(); + + @Override + public IconState getIcon() { + mLeftIsVoiceAssist = canLaunchVoiceAssist(); + if (mLeftIsVoiceAssist) { + mIconState.isVisible = mUserSetupComplete; + mIconState.drawable = mContext.getDrawable(R.drawable.ic_mic_26dp); + mIconState.contentDescription = mContext.getString( + R.string.accessibility_voice_assist_button); + } else { + mIconState.isVisible = mUserSetupComplete && isPhoneVisible(); + mIconState.drawable = mContext.getDrawable(R.drawable.ic_phone_24dp); + mIconState.contentDescription = mContext.getString( + R.string.accessibility_phone_button); + } + return mIconState; + } + + @Override + public Intent getIntent() { + return PHONE_INTENT; + } + } + + private class DefaultRightButton implements IntentButton { + + private IconState mIconState = new IconState(); + + @Override + public IconState getIcon() { + ResolveInfo resolved = resolveCameraIntent(); + mIconState.isVisible = !isCameraDisabledByDpm() && resolved != null + && getResources().getBoolean(R.bool.config_keyguardShowCameraAffordance) + && mUserSetupComplete; + mIconState.drawable = mContext.getDrawable(R.drawable.ic_camera_alt_24dp); + mIconState.contentDescription = + mContext.getString(R.string.accessibility_camera_button); + return mIconState; + } + + @Override + public Intent getIntent() { + KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext); + boolean canSkipBouncer = updateMonitor.getUserCanSkipBouncer( + KeyguardUpdateMonitor.getCurrentUser()); + boolean secure = mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser()); + return (secure && !canSkipBouncer) ? SECURE_CAMERA_INTENT : INSECURE_CAMERA_INTENT; + } + } }