Merge "Remove the unused assistant orb UI." into sc-v2-dev
This commit is contained in:
@@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
~ Copyright (C) 2014 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
|
|
||||||
-->
|
|
||||||
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<gradient
|
|
||||||
android:type="linear"
|
|
||||||
android:angle="90"
|
|
||||||
android:startColor="#33000000"
|
|
||||||
android:endColor="#00000000" />
|
|
||||||
</shape>
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
~ Copyright (C) 2014 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
|
|
||||||
-->
|
|
||||||
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<gradient
|
|
||||||
android:type="linear"
|
|
||||||
android:angle="90"
|
|
||||||
android:startColor="#55000000"
|
|
||||||
android:endColor="#00000000" />
|
|
||||||
</shape>
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
**
|
|
||||||
** Copyright 2012, 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.
|
|
||||||
*/
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!-- Extends FrameLayout -->
|
|
||||||
<com.android.systemui.assist.AssistOrbContainer
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<com.android.systemui.statusbar.AlphaOptimizedView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="@dimen/assist_orb_scrim_height"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:id="@+id/assist_orb_scrim"
|
|
||||||
android:background="@drawable/assist_orb_scrim"/>
|
|
||||||
|
|
||||||
<com.android.systemui.assist.AssistOrbView
|
|
||||||
android:id="@+id/assist_orb"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:id="@+id/search_logo"/>
|
|
||||||
</com.android.systemui.assist.AssistOrbView>
|
|
||||||
|
|
||||||
<com.android.systemui.statusbar.AlphaOptimizedView
|
|
||||||
android:id="@+id/assist_orb_navbar_scrim"
|
|
||||||
android:layout_height="@dimen/assist_orb_navbar_scrim_height"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:elevation="50dp"
|
|
||||||
android:outlineProvider="none"
|
|
||||||
android:background="@drawable/assist_orb_navbar_scrim"/>
|
|
||||||
|
|
||||||
</com.android.systemui.assist.AssistOrbContainer>
|
|
||||||
@@ -87,8 +87,6 @@
|
|||||||
|
|
||||||
<color name="notification_section_clear_all_btn_color">@color/GM2_grey_700</color>
|
<color name="notification_section_clear_all_btn_color">@color/GM2_grey_700</color>
|
||||||
|
|
||||||
<color name="assist_orb_color">#ffffff</color>
|
|
||||||
|
|
||||||
<color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
|
<color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
|
||||||
|
|
||||||
<!-- The color of the navigation bar icons. Need to be in sync with ic_sysbar_* -->
|
<!-- The color of the navigation bar icons. Need to be in sync with ic_sysbar_* -->
|
||||||
|
|||||||
@@ -678,25 +678,6 @@
|
|||||||
from Keyguard. -->
|
from Keyguard. -->
|
||||||
<dimen name="go_to_full_shade_appearing_translation">200dp</dimen>
|
<dimen name="go_to_full_shade_appearing_translation">200dp</dimen>
|
||||||
|
|
||||||
<!-- The diameter of the search panel circle. -->
|
|
||||||
<dimen name="assist_orb_size">144dp</dimen>
|
|
||||||
|
|
||||||
<!-- The margin to the edge of the screen from where the orb starts to appear -->
|
|
||||||
<dimen name="assist_orb_base_margin">22dp</dimen>
|
|
||||||
|
|
||||||
<!-- The amount the orb translates when appearing -->
|
|
||||||
<dimen name="assist_orb_travel_distance">26dp</dimen>
|
|
||||||
|
|
||||||
<!-- The elevation of the orb -->
|
|
||||||
<dimen name="assist_orb_elevation">12dp</dimen>
|
|
||||||
|
|
||||||
<!-- The height of the scrim behind the orb. -->
|
|
||||||
<dimen name="assist_orb_scrim_height">250dp</dimen>
|
|
||||||
|
|
||||||
<!-- The height of the scrim behind the search panel circle. Should be navigation_bar_height
|
|
||||||
+ 8dp. -->
|
|
||||||
<dimen name="assist_orb_navbar_scrim_height">56dp</dimen>
|
|
||||||
|
|
||||||
<!-- The width/height of the keyguard bottom area icon view on keyguard. -->
|
<!-- The width/height of the keyguard bottom area icon view on keyguard. -->
|
||||||
<dimen name="keyguard_affordance_height">48dp</dimen>
|
<dimen name="keyguard_affordance_height">48dp</dimen>
|
||||||
<dimen name="keyguard_affordance_width">48dp</dimen>
|
<dimen name="keyguard_affordance_width">48dp</dimen>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.app.ActivityOptions;
|
import android.app.ActivityOptions;
|
||||||
import android.app.SearchManager;
|
import android.app.SearchManager;
|
||||||
import android.content.ActivityNotFoundException;
|
import android.content.ActivityNotFoundException;
|
||||||
@@ -27,7 +26,6 @@ import android.util.Log;
|
|||||||
|
|
||||||
import com.android.internal.app.AssistUtils;
|
import com.android.internal.app.AssistUtils;
|
||||||
import com.android.internal.app.IVoiceInteractionSessionListener;
|
import com.android.internal.app.IVoiceInteractionSessionListener;
|
||||||
import com.android.internal.app.IVoiceInteractionSessionShowCallback;
|
|
||||||
import com.android.internal.logging.MetricsLogger;
|
import com.android.internal.logging.MetricsLogger;
|
||||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||||
@@ -37,7 +35,6 @@ import com.android.systemui.dagger.SysUISingleton;
|
|||||||
import com.android.systemui.model.SysUiState;
|
import com.android.systemui.model.SysUiState;
|
||||||
import com.android.systemui.recents.OverviewProxyService;
|
import com.android.systemui.recents.OverviewProxyService;
|
||||||
import com.android.systemui.statusbar.CommandQueue;
|
import com.android.systemui.statusbar.CommandQueue;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
|
||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
@@ -124,23 +121,8 @@ public class AssistManager {
|
|||||||
|
|
||||||
private final DeviceProvisionedController mDeviceProvisionedController;
|
private final DeviceProvisionedController mDeviceProvisionedController;
|
||||||
private final CommandQueue mCommandQueue;
|
private final CommandQueue mCommandQueue;
|
||||||
private final AssistOrbController mOrbController;
|
|
||||||
protected final AssistUtils mAssistUtils;
|
protected final AssistUtils mAssistUtils;
|
||||||
|
|
||||||
private IVoiceInteractionSessionShowCallback mShowCallback =
|
|
||||||
new IVoiceInteractionSessionShowCallback.Stub() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailed() throws RemoteException {
|
|
||||||
mOrbController.postHide();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onShown() throws RemoteException {
|
|
||||||
mOrbController.postHide();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AssistManager(
|
public AssistManager(
|
||||||
DeviceProvisionedController controller,
|
DeviceProvisionedController controller,
|
||||||
@@ -149,7 +131,6 @@ public class AssistManager {
|
|||||||
CommandQueue commandQueue,
|
CommandQueue commandQueue,
|
||||||
PhoneStateMonitor phoneStateMonitor,
|
PhoneStateMonitor phoneStateMonitor,
|
||||||
OverviewProxyService overviewProxyService,
|
OverviewProxyService overviewProxyService,
|
||||||
ConfigurationController configurationController,
|
|
||||||
Lazy<SysUiState> sysUiState,
|
Lazy<SysUiState> sysUiState,
|
||||||
DefaultUiController defaultUiController,
|
DefaultUiController defaultUiController,
|
||||||
AssistLogger assistLogger) {
|
AssistLogger assistLogger) {
|
||||||
@@ -161,8 +142,6 @@ public class AssistManager {
|
|||||||
mPhoneStateMonitor = phoneStateMonitor;
|
mPhoneStateMonitor = phoneStateMonitor;
|
||||||
mAssistLogger = assistLogger;
|
mAssistLogger = assistLogger;
|
||||||
|
|
||||||
mOrbController = new AssistOrbController(configurationController, context);
|
|
||||||
|
|
||||||
registerVoiceInteractionSessionListener();
|
registerVoiceInteractionSessionListener();
|
||||||
|
|
||||||
mUiController = defaultUiController;
|
mUiController = defaultUiController;
|
||||||
@@ -223,10 +202,6 @@ public class AssistManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean shouldShowOrb() {
|
|
||||||
return !ActivityManager.isLowRamDeviceStatic();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startAssist(Bundle args) {
|
public void startAssist(Bundle args) {
|
||||||
final ComponentName assistComponent = getAssistInfo();
|
final ComponentName assistComponent = getAssistInfo();
|
||||||
if (assistComponent == null) {
|
if (assistComponent == null) {
|
||||||
@@ -234,10 +209,6 @@ public class AssistManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final boolean isService = assistComponent.equals(getVoiceInteractorComponentName());
|
final boolean isService = assistComponent.equals(getVoiceInteractorComponentName());
|
||||||
if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) {
|
|
||||||
mOrbController.showOrb(assistComponent, isService);
|
|
||||||
mOrbController.postHideDelayed(isService ? TIMEOUT_SERVICE : TIMEOUT_ACTIVITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args == null) {
|
if (args == null) {
|
||||||
args = new Bundle();
|
args = new Bundle();
|
||||||
@@ -329,7 +300,7 @@ public class AssistManager {
|
|||||||
|
|
||||||
private void startVoiceInteractor(Bundle args) {
|
private void startVoiceInteractor(Bundle args) {
|
||||||
mAssistUtils.showSessionForActiveService(args,
|
mAssistUtils.showSessionForActiveService(args,
|
||||||
VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null);
|
VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void launchVoiceAssistFromKeyguard() {
|
public void launchVoiceAssistFromKeyguard() {
|
||||||
|
|||||||
@@ -1,157 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.android.systemui.assist;
|
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
|
|
||||||
import com.android.systemui.R;
|
|
||||||
import com.android.systemui.animation.Interpolators;
|
|
||||||
|
|
||||||
public class AssistOrbContainer extends FrameLayout {
|
|
||||||
|
|
||||||
private static final long EXIT_START_DELAY = 150;
|
|
||||||
|
|
||||||
private View mScrim;
|
|
||||||
private View mNavbarScrim;
|
|
||||||
private AssistOrbView mOrb;
|
|
||||||
|
|
||||||
private boolean mAnimatingOut;
|
|
||||||
|
|
||||||
public AssistOrbContainer(Context context) {
|
|
||||||
this(context, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AssistOrbContainer(Context context, @Nullable AttributeSet attrs) {
|
|
||||||
this(context, attrs, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AssistOrbContainer(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
|
||||||
super(context, attrs, defStyleAttr);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onFinishInflate() {
|
|
||||||
super.onFinishInflate();
|
|
||||||
mScrim = findViewById(R.id.assist_orb_scrim);
|
|
||||||
mNavbarScrim = findViewById(R.id.assist_orb_navbar_scrim);
|
|
||||||
mOrb = (AssistOrbView) findViewById(R.id.assist_orb);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void show(final boolean show, boolean animate, Runnable onDone) {
|
|
||||||
if (show) {
|
|
||||||
if (getVisibility() != View.VISIBLE) {
|
|
||||||
setVisibility(View.VISIBLE);
|
|
||||||
if (animate) {
|
|
||||||
startEnterAnimation(onDone);
|
|
||||||
} else {
|
|
||||||
reset();
|
|
||||||
if (onDone != null) {
|
|
||||||
onDone.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (animate) {
|
|
||||||
startExitAnimation(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mAnimatingOut = false;
|
|
||||||
setVisibility(View.GONE);
|
|
||||||
if (onDone != null) {
|
|
||||||
onDone.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
setVisibility(View.GONE);
|
|
||||||
if (onDone != null) {
|
|
||||||
onDone.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void reset() {
|
|
||||||
mAnimatingOut = false;
|
|
||||||
mOrb.reset();
|
|
||||||
mScrim.setAlpha(1f);
|
|
||||||
mNavbarScrim.setAlpha(1f);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startEnterAnimation(Runnable onDone) {
|
|
||||||
if (mAnimatingOut) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mOrb.startEnterAnimation();
|
|
||||||
mScrim.setAlpha(0f);
|
|
||||||
mNavbarScrim.setAlpha(0f);
|
|
||||||
post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mScrim.animate()
|
|
||||||
.alpha(1f)
|
|
||||||
.setDuration(300)
|
|
||||||
.setStartDelay(0)
|
|
||||||
.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
|
|
||||||
mNavbarScrim.animate()
|
|
||||||
.alpha(1f)
|
|
||||||
.setDuration(300)
|
|
||||||
.setStartDelay(0)
|
|
||||||
.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
|
|
||||||
.withEndAction(onDone);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void startExitAnimation(final Runnable endRunnable) {
|
|
||||||
if (mAnimatingOut) {
|
|
||||||
if (endRunnable != null) {
|
|
||||||
endRunnable.run();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mAnimatingOut = true;
|
|
||||||
mOrb.startExitAnimation(EXIT_START_DELAY);
|
|
||||||
mScrim.animate()
|
|
||||||
.alpha(0f)
|
|
||||||
.setDuration(250)
|
|
||||||
.setStartDelay(EXIT_START_DELAY)
|
|
||||||
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
|
|
||||||
mNavbarScrim.animate()
|
|
||||||
.alpha(0f)
|
|
||||||
.setDuration(250)
|
|
||||||
.setStartDelay(EXIT_START_DELAY)
|
|
||||||
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
|
|
||||||
.withEndAction(endRunnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the panel is showing, or, if it's animating, whether it will be
|
|
||||||
* when the animation is done.
|
|
||||||
*/
|
|
||||||
public boolean isShowing() {
|
|
||||||
return getVisibility() == View.VISIBLE && !mAnimatingOut;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AssistOrbView getOrb() {
|
|
||||||
return mOrb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,182 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 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.assist;
|
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.pm.ActivityInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.content.res.Resources;
|
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.os.Binder;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import com.android.settingslib.applications.InterestingConfigChanges;
|
|
||||||
import com.android.systemui.R;
|
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AssistOrbController controls the showing and hiding of the assistant orb.
|
|
||||||
*/
|
|
||||||
public class AssistOrbController {
|
|
||||||
private static final String ASSIST_ICON_METADATA_NAME =
|
|
||||||
"com.android.systemui.action_assist_icon";
|
|
||||||
private static final String TAG = "AssistOrbController";
|
|
||||||
private static final boolean VERBOSE = false;
|
|
||||||
|
|
||||||
private final InterestingConfigChanges mInterestingConfigChanges;
|
|
||||||
private AssistOrbContainer mView;
|
|
||||||
private final Context mContext;
|
|
||||||
private final WindowManager mWindowManager;
|
|
||||||
|
|
||||||
private Runnable mHideRunnable = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
mView.removeCallbacks(this);
|
|
||||||
mView.show(false /* show */, true /* animate */, () -> {
|
|
||||||
if (mView.isAttachedToWindow()) {
|
|
||||||
mWindowManager.removeView(mView);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private ConfigurationController.ConfigurationListener mConfigurationListener =
|
|
||||||
new ConfigurationController.ConfigurationListener() {
|
|
||||||
@Override
|
|
||||||
public void onConfigChanged(Configuration newConfig) {
|
|
||||||
if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
boolean visible = false;
|
|
||||||
if (mView != null) {
|
|
||||||
visible = mView.isShowing();
|
|
||||||
if (mView.isAttachedToWindow()) {
|
|
||||||
mWindowManager.removeView(mView);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visible) {
|
|
||||||
showOrb(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
AssistOrbController(ConfigurationController configurationController, Context context) {
|
|
||||||
mContext = context;
|
|
||||||
mWindowManager = mContext.getSystemService(WindowManager.class);
|
|
||||||
mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
|
|
||||||
| ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
|
|
||||||
| ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
|
|
||||||
|
|
||||||
configurationController.addCallback(mConfigurationListener);
|
|
||||||
mConfigurationListener.onConfigChanged(context.getResources().getConfiguration());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void postHide() {
|
|
||||||
mView.post(mHideRunnable);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void postHideDelayed(long delayMs) {
|
|
||||||
mView.postDelayed(mHideRunnable, delayMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showOrb(boolean animated) {
|
|
||||||
if (mView == null) {
|
|
||||||
mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate(
|
|
||||||
R.layout.assist_orb, null);
|
|
||||||
mView.setVisibility(View.GONE);
|
|
||||||
mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
|
||||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
|
||||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
|
|
||||||
}
|
|
||||||
if (!mView.isAttachedToWindow()) {
|
|
||||||
WindowManager.LayoutParams params = getLayoutParams();
|
|
||||||
mWindowManager.addView(mView, params);
|
|
||||||
}
|
|
||||||
mView.show(true, animated, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private WindowManager.LayoutParams getLayoutParams() {
|
|
||||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
||||||
mContext.getResources().getDimensionPixelSize(R.dimen.assist_orb_scrim_height),
|
|
||||||
WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING,
|
|
||||||
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
|
||||||
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
|
|
||||||
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
|
|
||||||
PixelFormat.TRANSLUCENT);
|
|
||||||
lp.token = new Binder();
|
|
||||||
lp.gravity = Gravity.BOTTOM | Gravity.START;
|
|
||||||
lp.setTitle("AssistPreviewPanel");
|
|
||||||
lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
|
|
||||||
| WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
|
|
||||||
return lp;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showOrb(@NonNull ComponentName assistComponent, boolean isService) {
|
|
||||||
showOrb(true);
|
|
||||||
maybeSwapSearchIcon(assistComponent, isService);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void maybeSwapSearchIcon(@NonNull ComponentName assistComponent, boolean isService) {
|
|
||||||
replaceDrawable(mView.getOrb().getLogo(), assistComponent, ASSIST_ICON_METADATA_NAME,
|
|
||||||
isService);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void replaceDrawable(ImageView v, ComponentName component, String name,
|
|
||||||
boolean isService) {
|
|
||||||
if (component != null) {
|
|
||||||
try {
|
|
||||||
PackageManager packageManager = mContext.getPackageManager();
|
|
||||||
// Look for the search icon specified in the activity meta-data
|
|
||||||
Bundle metaData = isService
|
|
||||||
? packageManager.getServiceInfo(
|
|
||||||
component, PackageManager.GET_META_DATA).metaData
|
|
||||||
: packageManager.getActivityInfo(
|
|
||||||
component, PackageManager.GET_META_DATA).metaData;
|
|
||||||
if (metaData != null) {
|
|
||||||
int iconResId = metaData.getInt(name);
|
|
||||||
if (iconResId != 0) {
|
|
||||||
Resources res = packageManager.getResourcesForApplication(
|
|
||||||
component.getPackageName());
|
|
||||||
v.setImageDrawable(res.getDrawable(iconResId));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
|
||||||
if (VERBOSE) {
|
|
||||||
Log.v(TAG, "Assistant component "
|
|
||||||
+ component.flattenToShortString() + " not found");
|
|
||||||
}
|
|
||||||
} catch (Resources.NotFoundException nfe) {
|
|
||||||
Log.w(TAG, "Failed to swap drawable from "
|
|
||||||
+ component.flattenToShortString(), nfe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
v.setImageDrawable(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,279 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2014 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.assist;
|
|
||||||
|
|
||||||
import android.animation.Animator;
|
|
||||||
import android.animation.AnimatorListenerAdapter;
|
|
||||||
import android.animation.ValueAnimator;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Canvas;
|
|
||||||
import android.graphics.Outline;
|
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewOutlineProvider;
|
|
||||||
import android.view.animation.Interpolator;
|
|
||||||
import android.view.animation.OvershootInterpolator;
|
|
||||||
import android.widget.FrameLayout;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
|
|
||||||
import com.android.systemui.R;
|
|
||||||
import com.android.systemui.animation.Interpolators;
|
|
||||||
|
|
||||||
public class AssistOrbView extends FrameLayout {
|
|
||||||
|
|
||||||
private final int mCircleMinSize;
|
|
||||||
private final int mBaseMargin;
|
|
||||||
private final int mStaticOffset;
|
|
||||||
private final Paint mBackgroundPaint = new Paint();
|
|
||||||
private final Rect mCircleRect = new Rect();
|
|
||||||
private final Rect mStaticRect = new Rect();
|
|
||||||
private final Interpolator mOvershootInterpolator = new OvershootInterpolator();
|
|
||||||
|
|
||||||
private boolean mClipToOutline;
|
|
||||||
private final int mMaxElevation;
|
|
||||||
private float mOutlineAlpha;
|
|
||||||
private float mOffset;
|
|
||||||
private float mCircleSize;
|
|
||||||
private ImageView mLogo;
|
|
||||||
private float mCircleAnimationEndValue;
|
|
||||||
|
|
||||||
private ValueAnimator mOffsetAnimator;
|
|
||||||
private ValueAnimator mCircleAnimator;
|
|
||||||
|
|
||||||
private ValueAnimator.AnimatorUpdateListener mCircleUpdateListener
|
|
||||||
= new ValueAnimator.AnimatorUpdateListener() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationUpdate(ValueAnimator animation) {
|
|
||||||
applyCircleSize((float) animation.getAnimatedValue());
|
|
||||||
updateElevation();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
mCircleAnimator = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private ValueAnimator.AnimatorUpdateListener mOffsetUpdateListener
|
|
||||||
= new ValueAnimator.AnimatorUpdateListener() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationUpdate(ValueAnimator animation) {
|
|
||||||
mOffset = (float) animation.getAnimatedValue();
|
|
||||||
updateLayout();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
public AssistOrbView(Context context) {
|
|
||||||
this(context, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AssistOrbView(Context context, AttributeSet attrs) {
|
|
||||||
this(context, attrs, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr) {
|
|
||||||
this(context, attrs, defStyleAttr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr,
|
|
||||||
int defStyleRes) {
|
|
||||||
super(context, attrs, defStyleAttr, defStyleRes);
|
|
||||||
setOutlineProvider(new ViewOutlineProvider() {
|
|
||||||
@Override
|
|
||||||
public void getOutline(View view, Outline outline) {
|
|
||||||
if (mCircleSize > 0.0f) {
|
|
||||||
outline.setOval(mCircleRect);
|
|
||||||
} else {
|
|
||||||
outline.setEmpty();
|
|
||||||
}
|
|
||||||
outline.setAlpha(mOutlineAlpha);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setWillNotDraw(false);
|
|
||||||
mCircleMinSize = context.getResources().getDimensionPixelSize(
|
|
||||||
R.dimen.assist_orb_size);
|
|
||||||
mBaseMargin = context.getResources().getDimensionPixelSize(
|
|
||||||
R.dimen.assist_orb_base_margin);
|
|
||||||
mStaticOffset = context.getResources().getDimensionPixelSize(
|
|
||||||
R.dimen.assist_orb_travel_distance);
|
|
||||||
mMaxElevation = context.getResources().getDimensionPixelSize(
|
|
||||||
R.dimen.assist_orb_elevation);
|
|
||||||
mBackgroundPaint.setAntiAlias(true);
|
|
||||||
mBackgroundPaint.setColor(getResources().getColor(R.color.assist_orb_color));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ImageView getLogo() {
|
|
||||||
return mLogo;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDraw(Canvas canvas) {
|
|
||||||
super.onDraw(canvas);
|
|
||||||
drawBackground(canvas);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void drawBackground(Canvas canvas) {
|
|
||||||
canvas.drawCircle(mCircleRect.centerX(), mCircleRect.centerY(), mCircleSize / 2,
|
|
||||||
mBackgroundPaint);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onFinishInflate() {
|
|
||||||
super.onFinishInflate();
|
|
||||||
mLogo = findViewById(R.id.search_logo);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
|
||||||
mLogo.layout(0, 0, mLogo.getMeasuredWidth(), mLogo.getMeasuredHeight());
|
|
||||||
if (changed) {
|
|
||||||
updateCircleRect(mStaticRect, mStaticOffset, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void animateCircleSize(float circleSize, long duration,
|
|
||||||
long startDelay, Interpolator interpolator) {
|
|
||||||
if (circleSize == mCircleAnimationEndValue) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mCircleAnimator != null) {
|
|
||||||
mCircleAnimator.cancel();
|
|
||||||
}
|
|
||||||
mCircleAnimator = ValueAnimator.ofFloat(mCircleSize, circleSize);
|
|
||||||
mCircleAnimator.addUpdateListener(mCircleUpdateListener);
|
|
||||||
mCircleAnimator.addListener(mClearAnimatorListener);
|
|
||||||
mCircleAnimator.setInterpolator(interpolator);
|
|
||||||
mCircleAnimator.setDuration(duration);
|
|
||||||
mCircleAnimator.setStartDelay(startDelay);
|
|
||||||
mCircleAnimator.start();
|
|
||||||
mCircleAnimationEndValue = circleSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyCircleSize(float circleSize) {
|
|
||||||
mCircleSize = circleSize;
|
|
||||||
updateLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateElevation() {
|
|
||||||
float t = (mStaticOffset - mOffset) / (float) mStaticOffset;
|
|
||||||
t = 1.0f - Math.max(t, 0.0f);
|
|
||||||
float offset = t * mMaxElevation;
|
|
||||||
setElevation(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Animates the offset to the edge of the screen.
|
|
||||||
*
|
|
||||||
* @param offset The offset to apply.
|
|
||||||
* @param startDelay The desired start delay if animated.
|
|
||||||
*
|
|
||||||
* @param interpolator The desired interpolator if animated. If null,
|
|
||||||
* a default interpolator will be taken designed for appearing or
|
|
||||||
* disappearing.
|
|
||||||
*/
|
|
||||||
private void animateOffset(float offset, long duration, long startDelay,
|
|
||||||
Interpolator interpolator) {
|
|
||||||
if (mOffsetAnimator != null) {
|
|
||||||
mOffsetAnimator.removeAllListeners();
|
|
||||||
mOffsetAnimator.cancel();
|
|
||||||
}
|
|
||||||
mOffsetAnimator = ValueAnimator.ofFloat(mOffset, offset);
|
|
||||||
mOffsetAnimator.addUpdateListener(mOffsetUpdateListener);
|
|
||||||
mOffsetAnimator.addListener(new AnimatorListenerAdapter() {
|
|
||||||
@Override
|
|
||||||
public void onAnimationEnd(Animator animation) {
|
|
||||||
mOffsetAnimator = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
mOffsetAnimator.setInterpolator(interpolator);
|
|
||||||
mOffsetAnimator.setStartDelay(startDelay);
|
|
||||||
mOffsetAnimator.setDuration(duration);
|
|
||||||
mOffsetAnimator.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateLayout() {
|
|
||||||
updateCircleRect();
|
|
||||||
updateLogo();
|
|
||||||
invalidateOutline();
|
|
||||||
invalidate();
|
|
||||||
updateClipping();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateClipping() {
|
|
||||||
boolean clip = mCircleSize < mCircleMinSize;
|
|
||||||
if (clip != mClipToOutline) {
|
|
||||||
setClipToOutline(clip);
|
|
||||||
mClipToOutline = clip;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateLogo() {
|
|
||||||
float translationX = (mCircleRect.left + mCircleRect.right) / 2.0f - mLogo.getWidth() / 2.0f;
|
|
||||||
float translationY = (mCircleRect.top + mCircleRect.bottom) / 2.0f
|
|
||||||
- mLogo.getHeight() / 2.0f - mCircleMinSize / 7f;
|
|
||||||
float t = (mStaticOffset - mOffset) / (float) mStaticOffset;
|
|
||||||
translationY += t * mStaticOffset * 0.1f;
|
|
||||||
float alpha = 1.0f-t;
|
|
||||||
alpha = Math.max((alpha - 0.5f) * 2.0f, 0);
|
|
||||||
mLogo.setImageAlpha((int) (alpha * 255));
|
|
||||||
mLogo.setTranslationX(translationX);
|
|
||||||
mLogo.setTranslationY(translationY);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateCircleRect() {
|
|
||||||
updateCircleRect(mCircleRect, mOffset, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateCircleRect(Rect rect, float offset, boolean useStaticSize) {
|
|
||||||
int left, top;
|
|
||||||
float circleSize = useStaticSize ? mCircleMinSize : mCircleSize;
|
|
||||||
left = (int) (getWidth() - circleSize) / 2;
|
|
||||||
top = (int) (getHeight() - circleSize / 2 - mBaseMargin - offset);
|
|
||||||
rect.set(left, top, (int) (left + circleSize), (int) (top + circleSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startExitAnimation(long delay) {
|
|
||||||
animateCircleSize(0, 200, delay, Interpolators.FAST_OUT_LINEAR_IN);
|
|
||||||
animateOffset(0, 200, delay, Interpolators.FAST_OUT_LINEAR_IN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startEnterAnimation() {
|
|
||||||
applyCircleSize(0);
|
|
||||||
post(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
animateCircleSize(mCircleMinSize, 300, 0 /* delay */, mOvershootInterpolator);
|
|
||||||
animateOffset(mStaticOffset, 400, 0 /* delay */, Interpolators.LINEAR_OUT_SLOW_IN);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
mClipToOutline = false;
|
|
||||||
mBackgroundPaint.setAlpha(255);
|
|
||||||
mOutlineAlpha = 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasOverlappingRendering() {
|
|
||||||
// not really true but it's ok during an animation, as it's never permanent
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user