Loading packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +7 −132 Original line number Diff line number Diff line Loading @@ -14,14 +14,8 @@ import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; 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.metrics.LogMaker; import android.os.AsyncTask; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; Loading @@ -30,12 +24,6 @@ import android.os.UserHandle; import android.provider.Settings; import android.service.voice.VoiceInteractionSession; 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.internal.app.AssistUtils; import com.android.internal.app.IVoiceInteractionSessionListener; Loading @@ -43,7 +31,6 @@ import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.settingslib.applications.InterestingConfigChanges; import com.android.systemui.R; import com.android.systemui.assist.ui.DefaultUiController; import com.android.systemui.dagger.SysUISingleton; Loading Loading @@ -97,8 +84,6 @@ public class AssistManager { // Note that VERBOSE logging may leak PII (e.g. transcription contents). private static final boolean VERBOSE = false; private static final String ASSIST_ICON_METADATA_NAME = "com.android.systemui.action_assist_icon"; private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms"; private static final String INVOCATION_PHONE_STATE_KEY = "invocation_phone_state"; public static final String INVOCATION_TYPE_KEY = "invocation_type"; Loading @@ -123,69 +108,29 @@ public class AssistManager { private static final long TIMEOUT_ACTIVITY = 1000; protected final Context mContext; private final WindowManager mWindowManager; private final AssistDisclosure mAssistDisclosure; private final InterestingConfigChanges mInterestingConfigChanges; private final PhoneStateMonitor mPhoneStateMonitor; private final AssistHandleBehaviorController mHandleController; private final UiController mUiController; protected final Lazy<SysUiState> mSysUiState; protected final AssistLogger mAssistLogger; private AssistOrbContainer mView; private final DeviceProvisionedController mDeviceProvisionedController; private final CommandQueue mCommandQueue; private final AssistOrbController mOrbController; protected final AssistUtils mAssistUtils; private final boolean mShouldEnableOrb; private IVoiceInteractionSessionShowCallback mShowCallback = new IVoiceInteractionSessionShowCallback.Stub() { @Override public void onFailed() throws RemoteException { mView.post(mHideRunnable); mOrbController.postHide(); } @Override public void onShown() throws RemoteException { mView.post(mHideRunnable); } }; private Runnable mHideRunnable = new Runnable() { @Override public void run() { mView.removeCallbacks(this); mView.show(false /* show */, true /* animate */); } }; 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); } } 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); WindowManager.LayoutParams lp = getLayoutParams(); mWindowManager.addView(mView, lp); if (visible) { mView.show(true /* show */, false /* animate */); } mOrbController.postHide(); } }; Loading @@ -205,21 +150,15 @@ public class AssistManager { mContext = context; mDeviceProvisionedController = controller; mCommandQueue = commandQueue; mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); mAssistUtils = assistUtils; mAssistDisclosure = new AssistDisclosure(context, new Handler()); mPhoneStateMonitor = phoneStateMonitor; mHandleController = handleController; mAssistLogger = assistLogger; configurationController.addCallback(mConfigurationListener); mOrbController = new AssistOrbController(configurationController, context); registerVoiceInteractionSessionListener(); mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS); mConfigurationListener.onConfigChanged(context.getResources().getConfiguration()); mShouldEnableOrb = !ActivityManager.isLowRamDeviceStatic(); mUiController = defaultUiController; Loading Loading @@ -282,7 +221,7 @@ public class AssistManager { } protected boolean shouldShowOrb() { return false; return !ActivityManager.isLowRamDeviceStatic(); } public void startAssist(Bundle args) { Loading @@ -293,10 +232,8 @@ public class AssistManager { final boolean isService = assistComponent.equals(getVoiceInteractorComponentName()); if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) { showOrb(assistComponent, isService); mView.postDelayed(mHideRunnable, isService ? TIMEOUT_SERVICE : TIMEOUT_ACTIVITY); mOrbController.showOrb(assistComponent, isService); mOrbController.postHideDelayed(isService ? TIMEOUT_SERVICE : TIMEOUT_ACTIVITY); } if (args == null) { Loading Loading @@ -340,30 +277,6 @@ public class AssistManager { mAssistUtils.hideCurrentSession(); } 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; } private void showOrb(@NonNull ComponentName assistComponent, boolean isService) { maybeSwapSearchIcon(assistComponent, isService); if (mShouldEnableOrb) { mView.show(true /* show */, true /* animate */); } } private void startAssistInternal(Bundle args, @NonNull ComponentName assistComponent, boolean isService) { if (isService) { Loading Loading @@ -440,44 +353,6 @@ public class AssistManager { return mAssistUtils.isSessionRunning(); } 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); } protected AssistHandleBehaviorController getHandleBehaviorController() { return mHandleController; } Loading packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java +14 −4 Original line number Diff line number Diff line Loading @@ -55,14 +55,17 @@ public class AssistOrbContainer extends FrameLayout { mOrb = (AssistOrbView) findViewById(R.id.assist_orb); } public void show(final boolean show, boolean animate) { public void show(final boolean show, boolean animate, Runnable onDone) { if (show) { if (getVisibility() != View.VISIBLE) { setVisibility(View.VISIBLE); if (animate) { startEnterAnimation(); startEnterAnimation(onDone); } else { reset(); if (onDone != null) { onDone.run(); } } } } else { Loading @@ -72,10 +75,16 @@ public class AssistOrbContainer extends FrameLayout { public void run() { mAnimatingOut = false; setVisibility(View.GONE); if (onDone != null) { onDone.run(); } } }); } else { setVisibility(View.GONE); if (onDone != null) { onDone.run(); } } } } Loading @@ -87,7 +96,7 @@ public class AssistOrbContainer extends FrameLayout { mNavbarScrim.setAlpha(1f); } private void startEnterAnimation() { private void startEnterAnimation(Runnable onDone) { if (mAnimatingOut) { return; } Loading @@ -106,7 +115,8 @@ public class AssistOrbContainer extends FrameLayout { .alpha(1f) .setDuration(300) .setStartDelay(0) .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN) .withEndAction(onDone); } }); } Loading packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java 0 → 100644 +180 −0 Original line number Diff line number Diff line /* * 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 */, () -> { 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); } } Loading
packages/SystemUI/src/com/android/systemui/assist/AssistManager.java +7 −132 Original line number Diff line number Diff line Loading @@ -14,14 +14,8 @@ import android.content.ActivityNotFoundException; import android.content.ComponentName; import android.content.Context; import android.content.Intent; 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.metrics.LogMaker; import android.os.AsyncTask; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.RemoteException; Loading @@ -30,12 +24,6 @@ import android.os.UserHandle; import android.provider.Settings; import android.service.voice.VoiceInteractionSession; 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.internal.app.AssistUtils; import com.android.internal.app.IVoiceInteractionSessionListener; Loading @@ -43,7 +31,6 @@ import com.android.internal.app.IVoiceInteractionSessionShowCallback; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.settingslib.applications.InterestingConfigChanges; import com.android.systemui.R; import com.android.systemui.assist.ui.DefaultUiController; import com.android.systemui.dagger.SysUISingleton; Loading Loading @@ -97,8 +84,6 @@ public class AssistManager { // Note that VERBOSE logging may leak PII (e.g. transcription contents). private static final boolean VERBOSE = false; private static final String ASSIST_ICON_METADATA_NAME = "com.android.systemui.action_assist_icon"; private static final String INVOCATION_TIME_MS_KEY = "invocation_time_ms"; private static final String INVOCATION_PHONE_STATE_KEY = "invocation_phone_state"; public static final String INVOCATION_TYPE_KEY = "invocation_type"; Loading @@ -123,69 +108,29 @@ public class AssistManager { private static final long TIMEOUT_ACTIVITY = 1000; protected final Context mContext; private final WindowManager mWindowManager; private final AssistDisclosure mAssistDisclosure; private final InterestingConfigChanges mInterestingConfigChanges; private final PhoneStateMonitor mPhoneStateMonitor; private final AssistHandleBehaviorController mHandleController; private final UiController mUiController; protected final Lazy<SysUiState> mSysUiState; protected final AssistLogger mAssistLogger; private AssistOrbContainer mView; private final DeviceProvisionedController mDeviceProvisionedController; private final CommandQueue mCommandQueue; private final AssistOrbController mOrbController; protected final AssistUtils mAssistUtils; private final boolean mShouldEnableOrb; private IVoiceInteractionSessionShowCallback mShowCallback = new IVoiceInteractionSessionShowCallback.Stub() { @Override public void onFailed() throws RemoteException { mView.post(mHideRunnable); mOrbController.postHide(); } @Override public void onShown() throws RemoteException { mView.post(mHideRunnable); } }; private Runnable mHideRunnable = new Runnable() { @Override public void run() { mView.removeCallbacks(this); mView.show(false /* show */, true /* animate */); } }; 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); } } 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); WindowManager.LayoutParams lp = getLayoutParams(); mWindowManager.addView(mView, lp); if (visible) { mView.show(true /* show */, false /* animate */); } mOrbController.postHide(); } }; Loading @@ -205,21 +150,15 @@ public class AssistManager { mContext = context; mDeviceProvisionedController = controller; mCommandQueue = commandQueue; mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); mAssistUtils = assistUtils; mAssistDisclosure = new AssistDisclosure(context, new Handler()); mPhoneStateMonitor = phoneStateMonitor; mHandleController = handleController; mAssistLogger = assistLogger; configurationController.addCallback(mConfigurationListener); mOrbController = new AssistOrbController(configurationController, context); registerVoiceInteractionSessionListener(); mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS); mConfigurationListener.onConfigChanged(context.getResources().getConfiguration()); mShouldEnableOrb = !ActivityManager.isLowRamDeviceStatic(); mUiController = defaultUiController; Loading Loading @@ -282,7 +221,7 @@ public class AssistManager { } protected boolean shouldShowOrb() { return false; return !ActivityManager.isLowRamDeviceStatic(); } public void startAssist(Bundle args) { Loading @@ -293,10 +232,8 @@ public class AssistManager { final boolean isService = assistComponent.equals(getVoiceInteractorComponentName()); if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) { showOrb(assistComponent, isService); mView.postDelayed(mHideRunnable, isService ? TIMEOUT_SERVICE : TIMEOUT_ACTIVITY); mOrbController.showOrb(assistComponent, isService); mOrbController.postHideDelayed(isService ? TIMEOUT_SERVICE : TIMEOUT_ACTIVITY); } if (args == null) { Loading Loading @@ -340,30 +277,6 @@ public class AssistManager { mAssistUtils.hideCurrentSession(); } 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; } private void showOrb(@NonNull ComponentName assistComponent, boolean isService) { maybeSwapSearchIcon(assistComponent, isService); if (mShouldEnableOrb) { mView.show(true /* show */, true /* animate */); } } private void startAssistInternal(Bundle args, @NonNull ComponentName assistComponent, boolean isService) { if (isService) { Loading Loading @@ -440,44 +353,6 @@ public class AssistManager { return mAssistUtils.isSessionRunning(); } 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); } protected AssistHandleBehaviorController getHandleBehaviorController() { return mHandleController; } Loading
packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java +14 −4 Original line number Diff line number Diff line Loading @@ -55,14 +55,17 @@ public class AssistOrbContainer extends FrameLayout { mOrb = (AssistOrbView) findViewById(R.id.assist_orb); } public void show(final boolean show, boolean animate) { public void show(final boolean show, boolean animate, Runnable onDone) { if (show) { if (getVisibility() != View.VISIBLE) { setVisibility(View.VISIBLE); if (animate) { startEnterAnimation(); startEnterAnimation(onDone); } else { reset(); if (onDone != null) { onDone.run(); } } } } else { Loading @@ -72,10 +75,16 @@ public class AssistOrbContainer extends FrameLayout { public void run() { mAnimatingOut = false; setVisibility(View.GONE); if (onDone != null) { onDone.run(); } } }); } else { setVisibility(View.GONE); if (onDone != null) { onDone.run(); } } } } Loading @@ -87,7 +96,7 @@ public class AssistOrbContainer extends FrameLayout { mNavbarScrim.setAlpha(1f); } private void startEnterAnimation() { private void startEnterAnimation(Runnable onDone) { if (mAnimatingOut) { return; } Loading @@ -106,7 +115,8 @@ public class AssistOrbContainer extends FrameLayout { .alpha(1f) .setDuration(300) .setStartDelay(0) .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN); .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN) .withEndAction(onDone); } }); } Loading
packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java 0 → 100644 +180 −0 Original line number Diff line number Diff line /* * 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 */, () -> { 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); } }