diff --git a/packages/SystemUI/res/anim/car_arrow_fade_in_rotate_down.xml b/packages/CarSystemUI/res/anim/car_arrow_fade_in_rotate_down.xml similarity index 100% rename from packages/SystemUI/res/anim/car_arrow_fade_in_rotate_down.xml rename to packages/CarSystemUI/res/anim/car_arrow_fade_in_rotate_down.xml diff --git a/packages/SystemUI/res/anim/car_arrow_fade_in_rotate_up.xml b/packages/CarSystemUI/res/anim/car_arrow_fade_in_rotate_up.xml similarity index 100% rename from packages/SystemUI/res/anim/car_arrow_fade_in_rotate_up.xml rename to packages/CarSystemUI/res/anim/car_arrow_fade_in_rotate_up.xml diff --git a/packages/SystemUI/res/anim/car_arrow_fade_out.xml b/packages/CarSystemUI/res/anim/car_arrow_fade_out.xml similarity index 100% rename from packages/SystemUI/res/anim/car_arrow_fade_out.xml rename to packages/CarSystemUI/res/anim/car_arrow_fade_out.xml diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml b/packages/CarSystemUI/res/anim/car_user_switcher_close_animation.xml similarity index 93% rename from packages/SystemUI/res/anim/car_user_switcher_close_animation.xml rename to packages/CarSystemUI/res/anim/car_user_switcher_close_animation.xml index ed637a7adcbfc..6f12338d8db80 100644 --- a/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml +++ b/packages/CarSystemUI/res/anim/car_user_switcher_close_animation.xml @@ -1,4 +1,4 @@ - - - - \ No newline at end of file + + + + + diff --git a/packages/CarSystemUI/res/drawable/car_stat_sys_data_bluetooth_indicator.xml b/packages/CarSystemUI/res/drawable/car_stat_sys_data_bluetooth_indicator.xml new file mode 100644 index 0000000000000..34578fe252d43 --- /dev/null +++ b/packages/CarSystemUI/res/drawable/car_stat_sys_data_bluetooth_indicator.xml @@ -0,0 +1,28 @@ + + + + + + diff --git a/packages/CarSystemUI/res/drawable/ic_mic_white.xml b/packages/CarSystemUI/res/drawable/ic_mic_white.xml index f5a91b5ded32b..e1e389d7f4728 100644 --- a/packages/CarSystemUI/res/drawable/ic_mic_white.xml +++ b/packages/CarSystemUI/res/drawable/ic_mic_white.xml @@ -1,3 +1,19 @@ + + - - - - - diff --git a/packages/SystemUI/res/drawable/car_ic_notification.xml b/packages/SystemUI/res/drawable/car_ic_notification.xml deleted file mode 100644 index 61d937b90d04c..0000000000000 --- a/packages/SystemUI/res/drawable/car_ic_notification.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - \ No newline at end of file diff --git a/packages/SystemUI/res/drawable/car_ic_overview.xml b/packages/SystemUI/res/drawable/car_ic_overview.xml deleted file mode 100644 index 4651dcb3a2290..0000000000000 --- a/packages/SystemUI/res/drawable/car_ic_overview.xml +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - diff --git a/packages/SystemUI/res/drawable/car_rounded_bg_bottom.xml b/packages/SystemUI/res/drawable/car_rounded_bg_bottom.xml deleted file mode 100644 index 25b449ab3a8a4..0000000000000 --- a/packages/SystemUI/res/drawable/car_rounded_bg_bottom.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - diff --git a/packages/SystemUI/res/layout/car_navigation_bar.xml b/packages/SystemUI/res/layout/car_navigation_bar.xml deleted file mode 100644 index d568d0d3c179f..0000000000000 --- a/packages/SystemUI/res/layout/car_navigation_bar.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml b/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml deleted file mode 100644 index 4ba6c06d80a13..0000000000000 --- a/packages/SystemUI/res/layout/car_navigation_bar_unprovisioned.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - - - - - diff --git a/packages/SystemUI/res/layout/car_status_bar_header.xml b/packages/SystemUI/res/layout/car_status_bar_header.xml deleted file mode 100644 index f2ef30180bc0f..0000000000000 --- a/packages/SystemUI/res/layout/car_status_bar_header.xml +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - - - - diff --git a/packages/SystemUI/res/layout/car_top_navigation_bar.xml b/packages/SystemUI/res/layout/car_top_navigation_bar.xml deleted file mode 100644 index e16014bb89457..0000000000000 --- a/packages/SystemUI/res/layout/car_top_navigation_bar.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - - diff --git a/packages/SystemUI/res/layout/car_volume_dialog.xml b/packages/SystemUI/res/layout/car_volume_dialog.xml deleted file mode 100644 index a6beaa15a4bf4..0000000000000 --- a/packages/SystemUI/res/layout/car_volume_dialog.xml +++ /dev/null @@ -1,31 +0,0 @@ - - diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml index 0cc3c9eb55dcd..34c208ab81aa8 100644 --- a/packages/SystemUI/res/layout/super_status_bar.xml +++ b/packages/SystemUI/res/layout/super_status_bar.xml @@ -56,11 +56,6 @@ android:layout_width="match_parent" android:layout_height="wrap_content" /> - - - - - - - - - - - diff --git a/packages/SystemUI/res/xml/car_volume_items.xml b/packages/SystemUI/res/xml/car_volume_items.xml deleted file mode 100644 index 742dfdda73c82..0000000000000 --- a/packages/SystemUI/res/xml/car_volume_items.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index 417d5168641d0..867c9175d308b 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -62,6 +62,7 @@ import com.android.systemui.statusbar.phone.StatusBarIconController; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler; import com.android.systemui.statusbar.policy.SmartReplyConstants; +import com.android.systemui.volume.VolumeDialogComponent; import java.util.function.Consumer; @@ -132,6 +133,10 @@ public class SystemUIFactory { return new QSTileHost(context, statusBar, iconController); } + public VolumeDialogComponent createVolumeDialogComponent(SystemUI systemUi, Context context) { + return new VolumeDialogComponent(systemUi, context); + } + public void injectDependencies(ArrayMap providers, Context context) { providers.put(StatusBarStateController.class, StatusBarStateController::new); diff --git a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java deleted file mode 100644 index 09c000b469a79..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/car/CarSystemUIFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.car; - -import android.content.Context; -import android.util.ArrayMap; - -import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.ViewMediatorCallback; -import com.android.systemui.Dependency.DependencyProvider; -import com.android.systemui.SystemUIFactory; -import com.android.systemui.statusbar.NotificationMediaManager; -import com.android.systemui.statusbar.car.CarFacetButtonController; -import com.android.systemui.statusbar.car.CarStatusBarKeyguardViewManager; -import com.android.systemui.statusbar.car.hvac.HvacController; -import com.android.systemui.statusbar.notification.NotificationEntryManager; -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; - -/** - * Class factory to provide car specific SystemUI components. - */ -public class CarSystemUIFactory extends SystemUIFactory { - - public StatusBarKeyguardViewManager createStatusBarKeyguardViewManager(Context context, - ViewMediatorCallback viewMediatorCallback, LockPatternUtils lockPatternUtils) { - return new CarStatusBarKeyguardViewManager(context, viewMediatorCallback, lockPatternUtils); - } - - @Override - public void injectDependencies(ArrayMap providers, - Context context) { - super.injectDependencies(providers, context); - providers.put(NotificationEntryManager.class, - () -> new CarNotificationEntryManager(context)); - providers.put(CarFacetButtonController.class, () -> new CarFacetButtonController(context)); - providers.put(HvacController.class, () -> new HvacController(context)); - providers.put(NotificationMediaManager.class, - () -> new CarNotificationMediaManager(context)); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java deleted file mode 100644 index bd328567fb46e..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarFacetButton.java +++ /dev/null @@ -1,186 +0,0 @@ -package com.android.systemui.statusbar.car; - -import android.content.Context; -import android.content.Intent; -import android.content.res.TypedArray; -import android.os.UserHandle; -import android.util.AttributeSet; -import android.view.View; -import android.widget.ImageView; -import android.widget.LinearLayout; - -import com.android.keyguard.AlphaOptimizedImageButton; -import com.android.systemui.Dependency; -import com.android.systemui.R; - -/** - * CarFacetButton is a ui component designed to be used as a shortcut for an app of a defined - * category. It can also render a indicator impling that there are more options of apps to launch - * using this component. This is done with a "More icon" currently an arrow as defined in the layout - * file. The class is to serve as an example. - * Usage example: A button that allows a user to select a music app and indicate that there are - * other music apps installed. - */ -public class CarFacetButton extends LinearLayout { - private static final String FACET_FILTER_DELIMITER = ";"; - /** - * Extra information to be sent to a helper to make the decision of what app to launch when - * clicked. - */ - private static final String EXTRA_FACET_CATEGORIES = "categories"; - private static final String EXTRA_FACET_PACKAGES = "packages"; - private static final String EXTRA_FACET_ID = "filter_id"; - private static final String EXTRA_FACET_LAUNCH_PICKER = "launch_picker"; - - private Context mContext; - private AlphaOptimizedImageButton mIcon; - private AlphaOptimizedImageButton mMoreIcon; - private boolean mSelected = false; - private String[] mComponentNames; - /** App categories that are to be used with this widget */ - private String[] mFacetCategories; - /** App packages that are allowed to be used with this widget */ - private String[] mFacetPackages; - private int mIconResourceId; - /** - * If defined in the xml this will be the icon that's rendered when the button is marked as - * selected - */ - private int mSelectedIconResourceId; - private boolean mUseMoreIcon = true; - private float mSelectedAlpha = 1f; - private float mUnselectedAlpha = 1f; - - - public CarFacetButton(Context context, AttributeSet attrs) { - super(context, attrs); - mContext = context; - View.inflate(context, R.layout.car_facet_button, this); - - // extract custom attributes - TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarFacetButton); - setupIntents(typedArray); - setupIcons(typedArray); - CarFacetButtonController carFacetButtonController = Dependency.get( - CarFacetButtonController.class); - carFacetButtonController.addFacetButton(this); - - } - - /** - * Reads the custom attributes to setup click handlers for this component. - */ - private void setupIntents(TypedArray typedArray) { - String intentString = typedArray.getString(R.styleable.CarFacetButton_intent); - String longPressIntentString = typedArray.getString(R.styleable.CarFacetButton_longIntent); - String categoryString = typedArray.getString(R.styleable.CarFacetButton_categories); - String packageString = typedArray.getString(R.styleable.CarFacetButton_packages); - String componentNameString = - typedArray.getString(R.styleable.CarFacetButton_componentNames); - try { - final Intent intent = Intent.parseUri(intentString, Intent.URI_INTENT_SCHEME); - intent.putExtra(EXTRA_FACET_ID, Integer.toString(getId())); - - if (packageString != null) { - mFacetPackages = packageString.split(FACET_FILTER_DELIMITER); - intent.putExtra(EXTRA_FACET_PACKAGES, mFacetPackages); - } - if (categoryString != null) { - mFacetCategories = categoryString.split(FACET_FILTER_DELIMITER); - intent.putExtra(EXTRA_FACET_CATEGORIES, mFacetCategories); - } - if (componentNameString != null) { - mComponentNames = componentNameString.split(FACET_FILTER_DELIMITER); - } - - setOnClickListener(v -> { - intent.putExtra(EXTRA_FACET_LAUNCH_PICKER, mSelected); - mContext.startActivityAsUser(intent, UserHandle.CURRENT); - }); - - if (longPressIntentString != null) { - final Intent longPressIntent = Intent.parseUri(longPressIntentString, - Intent.URI_INTENT_SCHEME); - setOnLongClickListener(v -> { - mContext.startActivityAsUser(longPressIntent, UserHandle.CURRENT); - return true; - }); - } - } catch (Exception e) { - throw new RuntimeException("Failed to attach intent", e); - } - } - - - private void setupIcons(TypedArray styledAttributes) { - mSelectedAlpha = styledAttributes.getFloat( - R.styleable.CarFacetButton_selectedAlpha, mSelectedAlpha); - mUnselectedAlpha = styledAttributes.getFloat( - R.styleable.CarFacetButton_unselectedAlpha, mUnselectedAlpha); - mIcon = findViewById(R.id.car_nav_button_icon); - mIcon.setScaleType(ImageView.ScaleType.CENTER); - mIcon.setClickable(false); - mIcon.setAlpha(mUnselectedAlpha); - mIconResourceId = styledAttributes.getResourceId(R.styleable.CarFacetButton_icon, 0); - mIcon.setImageResource(mIconResourceId); - mSelectedIconResourceId = styledAttributes.getResourceId( - R.styleable.CarFacetButton_selectedIcon, mIconResourceId); - - mMoreIcon = findViewById(R.id.car_nav_button_more_icon); - mMoreIcon.setClickable(false); - mMoreIcon.setAlpha(mSelectedAlpha); - mMoreIcon.setVisibility(GONE); - mUseMoreIcon = styledAttributes.getBoolean(R.styleable.CarFacetButton_useMoreIcon, true); - } - - /** - * @return The app categories the component represents - */ - public String[] getCategories() { - if (mFacetCategories == null) { - return new String[0]; - } - return mFacetCategories; - } - - /** - * @return The valid packages that should be considered. - */ - public String[] getFacetPackages() { - if (mFacetPackages == null) { - return new String[0]; - } - return mFacetPackages; - } - - public String[] getComponentName() { - if (mComponentNames == null) { - return new String[0]; - } - return mComponentNames; - } - - /** - * Updates the alpha of the icons to "selected" and shows the "More icon" - * @param selected true if the view must be selected, false otherwise - */ - public void setSelected(boolean selected) { - super.setSelected(selected); - setSelected(selected, selected); - } - - /** - * Updates the visual state to let the user know if it's been selected. - * @param selected true if should update the alpha of the icon to selected, false otherwise - * @param showMoreIcon true if the "more icon" should be shown, false otherwise. Note this - * is ignored if the attribute useMoreIcon is set to false - */ - public void setSelected(boolean selected, boolean showMoreIcon) { - mSelected = selected; - mIcon.setAlpha(mSelected ? mSelectedAlpha : mUnselectedAlpha); - mIcon.setImageResource(mSelected ? mSelectedIconResourceId : mIconResourceId); - if (mUseMoreIcon) { - mMoreIcon.setVisibility(showMoreIcon ? VISIBLE : GONE); - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index cfd53be8979bf..c303686f72fa7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -161,7 +161,6 @@ import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.Snoo import com.android.systemui.qs.QSFragment; import com.android.systemui.qs.QSPanel; import com.android.systemui.qs.QSTileHost; -import com.android.systemui.qs.car.CarQSFragment; import com.android.systemui.recents.Recents; import com.android.systemui.recents.ScreenPinningRequest; import com.android.systemui.shared.system.WindowManagerWrapper; @@ -918,8 +917,7 @@ public class StatusBar extends SystemUI implements DemoMode, Dependency.get(ExtensionController.class) .newExtension(QS.class) .withPlugin(QS.class) - .withFeature(PackageManager.FEATURE_AUTOMOTIVE, CarQSFragment::new) - .withDefault(QSFragment::new) + .withDefault(this::createDefaultQSFragment) .build()); final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this, mIconController); @@ -1007,6 +1005,10 @@ public class StatusBar extends SystemUI implements DemoMode, ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f)); } + protected QS createDefaultQSFragment() { + return new QSFragment(); + } + protected void setUpPresenter() { // Set up the initial notification state. mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel, diff --git a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java deleted file mode 100644 index 9b616e00a72fa..0000000000000 --- a/packages/SystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright (C) 2018 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.volume; - -import android.animation.Animator; -import android.animation.AnimatorInflater; -import android.animation.AnimatorSet; -import android.annotation.DrawableRes; -import android.annotation.Nullable; -import android.app.Dialog; -import android.app.KeyguardManager; -import android.car.Car; -import android.car.CarNotConnectedException; -import android.car.media.CarAudioManager; -import android.car.media.ICarVolumeCallback; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.ServiceConnection; -import android.content.res.TypedArray; -import android.content.res.XmlResourceParser; -import android.graphics.Color; -import android.graphics.PixelFormat; -import android.graphics.drawable.ColorDrawable; -import android.graphics.drawable.Drawable; -import android.media.AudioAttributes; -import android.media.AudioManager; -import android.os.Debug; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.util.AttributeSet; -import android.util.Log; -import android.util.SparseArray; -import android.util.Xml; -import android.view.ContextThemeWrapper; -import android.view.Gravity; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.view.WindowManager; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; - -import androidx.car.widget.ListItem; -import androidx.car.widget.ListItemAdapter; -import androidx.car.widget.ListItemAdapter.BackgroundStyle; -import androidx.car.widget.ListItemProvider.ListProvider; -import androidx.car.widget.PagedListView; -import androidx.car.widget.SeekbarListItem; - -import com.android.systemui.R; -import com.android.systemui.plugins.VolumeDialog; - -import org.xmlpull.v1.XmlPullParserException; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * Car version of the volume dialog. - * - * Methods ending in "H" must be called on the (ui) handler. - */ -public class CarVolumeDialogImpl implements VolumeDialog { - private static final String TAG = Util.logTag(CarVolumeDialogImpl.class); - - private static final String XML_TAG_VOLUME_ITEMS = "carVolumeItems"; - private static final String XML_TAG_VOLUME_ITEM = "item"; - private static final int HOVERING_TIMEOUT = 16000; - private static final int NORMAL_TIMEOUT = 3000; - private static final int LISTVIEW_ANIMATION_DURATION_IN_MILLIS = 250; - private static final int DISMISS_DELAY_IN_MILLIS = 50; - private static final int ARROW_FADE_IN_START_DELAY_IN_MILLIS = 100; - - private final Context mContext; - private final H mHandler = new H(); - - private Window mWindow; - private CustomDialog mDialog; - private PagedListView mListView; - private ListItemAdapter mPagedListAdapter; - // All the volume items. - private final SparseArray mVolumeItems = new SparseArray<>(); - // Available volume items in car audio manager. - private final List mAvailableVolumeItems = new ArrayList<>(); - // Volume items in the PagedListView. - private final List mVolumeLineItems = new ArrayList<>(); - private final KeyguardManager mKeyguard; - - private Car mCar; - private CarAudioManager mCarAudioManager; - - private boolean mHovering; - private boolean mShowing; - private boolean mExpanded; - - public CarVolumeDialogImpl(Context context) { - mContext = new ContextThemeWrapper(context, com.android.systemui.R.style.qs_theme); - mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); - mCar = Car.createCar(mContext, mServiceConnection); - } - - public void init(int windowType, Callback callback) { - initDialog(); - - mCar.connect(); - } - - @Override - public void destroy() { - mHandler.removeCallbacksAndMessages(null); - - cleanupAudioManager(); - // unregisterVolumeCallback is not being called when disconnect car, so we manually cleanup - // audio manager beforehand. - mCar.disconnect(); - } - - private void initDialog() { - loadAudioUsageItems(); - mVolumeLineItems.clear(); - mDialog = new CustomDialog(mContext); - - mHovering = false; - mShowing = false; - mExpanded = false; - mWindow = mDialog.getWindow(); - mWindow.requestFeature(Window.FEATURE_NO_TITLE); - mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND - | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); - mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED); - mWindow.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY); - mWindow.setWindowAnimations(com.android.internal.R.style.Animation_Toast); - final WindowManager.LayoutParams lp = mWindow.getAttributes(); - lp.format = PixelFormat.TRANSLUCENT; - lp.setTitle(VolumeDialogImpl.class.getSimpleName()); - lp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL; - lp.windowAnimations = -1; - mWindow.setAttributes(lp); - mWindow.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); - - mDialog.setCanceledOnTouchOutside(true); - mDialog.setContentView(R.layout.car_volume_dialog); - mDialog.setOnShowListener(dialog -> { - mListView.setTranslationY(-mListView.getHeight()); - mListView.setAlpha(0); - mListView.animate() - .alpha(1) - .translationY(0) - .setDuration(LISTVIEW_ANIMATION_DURATION_IN_MILLIS) - .setInterpolator(new SystemUIInterpolators.LogDecelerateInterpolator()) - .start(); - }); - mListView = (PagedListView) mWindow.findViewById(R.id.volume_list); - mListView.setOnHoverListener((v, event) -> { - int action = event.getActionMasked(); - mHovering = (action == MotionEvent.ACTION_HOVER_ENTER) - || (action == MotionEvent.ACTION_HOVER_MOVE); - rescheduleTimeoutH(); - return true; - }); - - mPagedListAdapter = new ListItemAdapter(mContext, new ListProvider(mVolumeLineItems), - BackgroundStyle.PANEL); - mListView.setAdapter(mPagedListAdapter); - mListView.setMaxPages(PagedListView.UNLIMITED_PAGES); - } - - public void show(int reason) { - mHandler.obtainMessage(H.SHOW, reason).sendToTarget(); - } - - public void dismiss(int reason) { - mHandler.obtainMessage(H.DISMISS, reason).sendToTarget(); - } - - private void showH(int reason) { - if (D.BUG) { - Log.d(TAG, "showH r=" + Events.DISMISS_REASONS[reason]); - } - - mHandler.removeMessages(H.SHOW); - mHandler.removeMessages(H.DISMISS); - rescheduleTimeoutH(); - // Refresh the data set before showing. - mPagedListAdapter.notifyDataSetChanged(); - if (mShowing) { - return; - } - mShowing = true; - - mDialog.show(); - Events.writeEvent(mContext, Events.EVENT_SHOW_DIALOG, reason, mKeyguard.isKeyguardLocked()); - } - - protected void rescheduleTimeoutH() { - mHandler.removeMessages(H.DISMISS); - final int timeout = computeTimeoutH(); - mHandler.sendMessageDelayed(mHandler - .obtainMessage(H.DISMISS, Events.DISMISS_REASON_TIMEOUT), timeout); - - if (D.BUG) { - Log.d(TAG, "rescheduleTimeout " + timeout + " " + Debug.getCaller()); - } - } - - private int computeTimeoutH() { - return mHovering ? HOVERING_TIMEOUT : NORMAL_TIMEOUT; - } - - protected void dismissH(int reason) { - if (D.BUG) { - Log.d(TAG, "dismissH r=" + Events.DISMISS_REASONS[reason]); - } - - mHandler.removeMessages(H.DISMISS); - mHandler.removeMessages(H.SHOW); - if (!mShowing) { - return; - } - - mListView.animate().cancel(); - - mListView.setTranslationY(0); - mListView.setAlpha(1); - mListView.animate() - .alpha(0) - .translationY(-mListView.getHeight()) - .setDuration(LISTVIEW_ANIMATION_DURATION_IN_MILLIS) - .setInterpolator(new SystemUIInterpolators.LogAccelerateInterpolator()) - .withEndAction(() -> mHandler.postDelayed(() -> { - if (D.BUG) { - Log.d(TAG, "mDialog.dismiss()"); - } - mDialog.dismiss(); - mShowing = false; - }, DISMISS_DELAY_IN_MILLIS)) - .start(); - - Events.writeEvent(mContext, Events.EVENT_DISMISS_DIALOG, reason); - } - - public void dump(PrintWriter writer) { - writer.println(VolumeDialogImpl.class.getSimpleName() + " state:"); - writer.print(" mShowing: "); writer.println(mShowing); - } - - private void loadAudioUsageItems() { - try (XmlResourceParser parser = mContext.getResources().getXml(R.xml.car_volume_items)) { - AttributeSet attrs = Xml.asAttributeSet(parser); - int type; - // Traverse to the first start tag - while ((type=parser.next()) != XmlResourceParser.END_DOCUMENT - && type != XmlResourceParser.START_TAG) { - } - - if (!XML_TAG_VOLUME_ITEMS.equals(parser.getName())) { - throw new RuntimeException("Meta-data does not start with carVolumeItems tag"); - } - int outerDepth = parser.getDepth(); - int rank = 0; - while ((type=parser.next()) != XmlResourceParser.END_DOCUMENT - && (type != XmlResourceParser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == XmlResourceParser.END_TAG) { - continue; - } - if (XML_TAG_VOLUME_ITEM.equals(parser.getName())) { - TypedArray item = mContext.getResources().obtainAttributes( - attrs, R.styleable.carVolumeItems_item); - int usage = item.getInt(R.styleable.carVolumeItems_item_usage, -1); - if (usage >= 0) { - VolumeItem volumeItem = new VolumeItem(); - volumeItem.usage = usage; - volumeItem.rank = rank; - volumeItem.icon = item.getResourceId(R.styleable.carVolumeItems_item_icon, 0); - mVolumeItems.put(usage, volumeItem); - rank++; - } - item.recycle(); - } - } - } catch (XmlPullParserException | IOException e) { - Log.e(TAG, "Error parsing volume groups configuration", e); - } - } - - private VolumeItem getVolumeItemForUsages(int[] usages) { - int rank = Integer.MAX_VALUE; - VolumeItem result = null; - for (int usage : usages) { - VolumeItem volumeItem = mVolumeItems.get(usage); - if (volumeItem.rank < rank) { - rank = volumeItem.rank; - result = volumeItem; - } - } - return result; - } - - private static int getSeekbarValue(CarAudioManager carAudioManager, int volumeGroupId) { - try { - return carAudioManager.getGroupVolume(volumeGroupId); - } catch (CarNotConnectedException e) { - Log.e(TAG, "Car is not connected!", e); - } - return 0; - } - - private static int getMaxSeekbarValue(CarAudioManager carAudioManager, int volumeGroupId) { - try { - return carAudioManager.getGroupMaxVolume(volumeGroupId); - } catch (CarNotConnectedException e) { - Log.e(TAG, "Car is not connected!", e); - } - return 0; - } - - private SeekbarListItem addSeekbarListItem(VolumeItem volumeItem, int volumeGroupId, - int supplementalIconId, @Nullable View.OnClickListener supplementalIconOnClickListener) { - SeekbarListItem listItem = new SeekbarListItem(mContext); - listItem.setMax(getMaxSeekbarValue(mCarAudioManager, volumeGroupId)); - int color = mContext.getResources().getColor(R.color.car_volume_dialog_tint); - int progress = getSeekbarValue(mCarAudioManager, volumeGroupId); - listItem.setProgress(progress); - listItem.setOnSeekBarChangeListener( - new CarVolumeDialogImpl.VolumeSeekBarChangeListener(volumeGroupId, mCarAudioManager)); - Drawable primaryIcon = mContext.getResources().getDrawable(volumeItem.icon); - primaryIcon.mutate().setTint(color); - listItem.setPrimaryActionIcon(primaryIcon); - if (supplementalIconId != 0) { - Drawable supplementalIcon = mContext.getResources().getDrawable(supplementalIconId); - supplementalIcon.mutate().setTint(color); - listItem.setSupplementalIcon(supplementalIcon, true); - listItem.setSupplementalIconListener(supplementalIconOnClickListener); - } else { - listItem.setSupplementalEmptyIcon(true); - listItem.setSupplementalIconListener(null); - } - - mVolumeLineItems.add(listItem); - volumeItem.listItem = listItem; - volumeItem.progress = progress; - return listItem; - } - - private VolumeItem findVolumeItem(SeekbarListItem targetItem) { - for (int i = 0; i < mVolumeItems.size(); ++i) { - VolumeItem volumeItem = mVolumeItems.valueAt(i); - if (volumeItem.listItem == targetItem) { - return volumeItem; - } - } - return null; - } - - private void cleanupAudioManager() { - try { - mCarAudioManager.unregisterVolumeCallback(mVolumeChangeCallback.asBinder()); - } catch (CarNotConnectedException e) { - Log.e(TAG, "Car is not connected!", e); - } - mVolumeLineItems.clear(); - mCarAudioManager = null; - } - - private final class H extends Handler { - private static final int SHOW = 1; - private static final int DISMISS = 2; - - public H() { - super(Looper.getMainLooper()); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case SHOW: - showH(msg.arg1); - break; - case DISMISS: - dismissH(msg.arg1); - break; - default: - } - } - } - - private final class CustomDialog extends Dialog implements DialogInterface { - public CustomDialog(Context context) { - super(context, com.android.systemui.R.style.qs_theme); - } - - @Override - public boolean dispatchTouchEvent(MotionEvent ev) { - rescheduleTimeoutH(); - return super.dispatchTouchEvent(ev); - } - - @Override - protected void onStart() { - super.setCanceledOnTouchOutside(true); - super.onStart(); - } - - @Override - protected void onStop() { - super.onStop(); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (isShowing()) { - if (event.getAction() == MotionEvent.ACTION_OUTSIDE) { - mHandler.obtainMessage( - H.DISMISS, Events.DISMISS_REASON_TOUCH_OUTSIDE).sendToTarget(); - return true; - } - } - return false; - } - } - - private final class ExpandIconListener implements View.OnClickListener { - @Override - public void onClick(final View v) { - mExpanded = !mExpanded; - Animator inAnimator; - if (mExpanded) { - for (int groupId = 0; groupId < mAvailableVolumeItems.size(); ++groupId) { - // Adding the items which are not coming from the default item. - VolumeItem volumeItem = mAvailableVolumeItems.get(groupId); - if (volumeItem.defaultItem) { - // Set progress here due to the progress of seekbar may not be updated. - volumeItem.listItem.setProgress(volumeItem.progress); - } else { - addSeekbarListItem(volumeItem, groupId, 0, null); - } - } - inAnimator = AnimatorInflater.loadAnimator( - mContext, R.anim.car_arrow_fade_in_rotate_up); - } else { - // Only keeping the default stream if it is not expended. - Iterator itr = mVolumeLineItems.iterator(); - while (itr.hasNext()) { - SeekbarListItem seekbarListItem = (SeekbarListItem) itr.next(); - VolumeItem volumeItem = findVolumeItem(seekbarListItem); - if (!volumeItem.defaultItem) { - itr.remove(); - } else { - // Set progress here due to the progress of seekbar may not be updated. - seekbarListItem.setProgress(volumeItem.progress); - } - } - inAnimator = AnimatorInflater.loadAnimator( - mContext, R.anim.car_arrow_fade_in_rotate_down); - } - - Animator outAnimator = AnimatorInflater.loadAnimator( - mContext, R.anim.car_arrow_fade_out); - inAnimator.setStartDelay(ARROW_FADE_IN_START_DELAY_IN_MILLIS); - AnimatorSet animators = new AnimatorSet(); - animators.playTogether(outAnimator, inAnimator); - animators.setTarget(v); - animators.start(); - mPagedListAdapter.notifyDataSetChanged(); - } - } - - private final class VolumeSeekBarChangeListener implements OnSeekBarChangeListener { - private final int mVolumeGroupId; - private final CarAudioManager mCarAudioManager; - - private VolumeSeekBarChangeListener(int volumeGroupId, CarAudioManager carAudioManager) { - mVolumeGroupId = volumeGroupId; - mCarAudioManager = carAudioManager; - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (!fromUser) { - // For instance, if this event is originated from AudioService, - // we can ignore it as it has already been handled and doesn't need to be - // sent back down again. - return; - } - try { - if (mCarAudioManager == null) { - Log.w(TAG, "Ignoring volume change event because the car isn't connected"); - return; - } - mAvailableVolumeItems.get(mVolumeGroupId).progress = progress; - mCarAudioManager.setGroupVolume(mVolumeGroupId, progress, 0); - } catch (CarNotConnectedException e) { - Log.e(TAG, "Car is not connected!", e); - } - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) {} - - @Override - public void onStopTrackingTouch(SeekBar seekBar) {} - } - - private final ICarVolumeCallback mVolumeChangeCallback = new ICarVolumeCallback.Stub() { - @Override - public void onGroupVolumeChanged(int groupId, int flags) { - VolumeItem volumeItem = mAvailableVolumeItems.get(groupId); - int value = getSeekbarValue(mCarAudioManager, groupId); - // Do not update the progress if it is the same as before. When car audio manager sets its - // group volume caused by the seekbar progress changed, it also triggers this callback. - // Updating the seekbar at the same time could block the continuous seeking. - if (value != volumeItem.progress) { - volumeItem.listItem.setProgress(value); - volumeItem.progress = value; - } - if ((flags & AudioManager.FLAG_SHOW_UI) != 0) { - show(Events.SHOW_REASON_VOLUME_CHANGED); - } - } - - @Override - public void onMasterMuteChanged(int flags) { - // ignored - } - }; - - private final ServiceConnection mServiceConnection = new ServiceConnection() { - @Override - public void onServiceConnected(ComponentName name, IBinder service) { - try { - mExpanded = false; - mCarAudioManager = (CarAudioManager) mCar.getCarManager(Car.AUDIO_SERVICE); - int volumeGroupCount = mCarAudioManager.getVolumeGroupCount(); - // Populates volume slider items from volume groups to UI. - for (int groupId = 0; groupId < volumeGroupCount; groupId++) { - VolumeItem volumeItem = getVolumeItemForUsages( - mCarAudioManager.getUsagesForVolumeGroupId(groupId)); - mAvailableVolumeItems.add(volumeItem); - // The first one is the default item. - if (groupId == 0) { - volumeItem.defaultItem = true; - addSeekbarListItem(volumeItem, groupId, R.drawable.car_ic_keyboard_arrow_down, - new ExpandIconListener()); - } - } - - // If list is already initiated, update its content. - if (mPagedListAdapter != null) { - mPagedListAdapter.notifyDataSetChanged(); - } - mCarAudioManager.registerVolumeCallback(mVolumeChangeCallback.asBinder()); - } catch (CarNotConnectedException e) { - Log.e(TAG, "Car is not connected!", e); - } - } - - /** - * This does not get called when service is properly disconnected. - * So we need to also handle cleanups in destroy(). - */ - @Override - public void onServiceDisconnected(ComponentName name) { - cleanupAudioManager(); - } - }; - - /** - * Wrapper class which contains information of each volume group. - */ - private static class VolumeItem { - private @AudioAttributes.AttributeUsage int usage; - private int rank; - private boolean defaultItem = false; - private @DrawableRes int icon; - private SeekbarListItem listItem; - private int progress; - } -} diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java index 2861dffe54605..080567739be7a 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java @@ -19,12 +19,10 @@ package com.android.systemui.volume; 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.media.AudioManager; import android.media.VolumePolicy; import android.os.Bundle; -import android.os.Handler; import android.view.WindowManager.LayoutParams; import com.android.settingslib.applications.InterestingConfigChanges; @@ -57,7 +55,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna public static final boolean DEFAULT_DO_NOT_DISTURB_WHEN_SILENT = false; private final SystemUI mSysui; - private final Context mContext; + protected final Context mContext; private final VolumeDialogControllerImpl mController; private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges( ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE @@ -70,7 +68,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna 400 // vibrateToSilentDebounce ); - public VolumeDialogComponent(SystemUI sysui, Context context, Handler handler) { + public VolumeDialogComponent(SystemUI sysui, Context context) { mSysui = sysui; mContext = context; mController = (VolumeDialogControllerImpl) Dependency.get(VolumeDialogController.class); @@ -81,7 +79,6 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna Dependency.get(ExtensionController.class).newExtension(VolumeDialog.class) .withPlugin(VolumeDialog.class) .withDefault(this::createDefault) - .withFeature(PackageManager.FEATURE_AUTOMOTIVE, this::createCarDefault) .withCallback(dialog -> { if (mDialog != null) { mDialog.destroy(); @@ -94,7 +91,7 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna VOLUME_SILENT_DO_NOT_DISTURB); } - private VolumeDialog createDefault() { + protected VolumeDialog createDefault() { VolumeDialogImpl impl = new VolumeDialogImpl(mContext); impl.setStreamImportant(AudioManager.STREAM_SYSTEM, false); impl.setAutomute(true); @@ -102,10 +99,6 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna return impl; } - private VolumeDialog createCarDefault() { - return new CarVolumeDialogImpl(mContext); - } - @Override public void onTuningChanged(String key, String newValue) { if (VOLUME_DOWN_SILENT.equals(key)) { diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java index e4f37decdf355..f8cf79322b40b 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java @@ -22,6 +22,7 @@ import android.util.Log; import com.android.systemui.R; import com.android.systemui.SystemUI; +import com.android.systemui.SystemUIFactory; import com.android.systemui.qs.tiles.DndTile; import java.io.FileDescriptor; @@ -43,7 +44,9 @@ public class VolumeUI extends SystemUI { mContext.getResources().getBoolean(R.bool.enable_safety_warning); mEnabled = enableVolumeUi || enableSafetyWarning; if (!mEnabled) return; - mVolumeComponent = new VolumeDialogComponent(this, mContext, null); + + mVolumeComponent = SystemUIFactory.getInstance() + .createVolumeDialogComponent(this, mContext); mVolumeComponent.setEnableDialogs(enableVolumeUi, enableSafetyWarning); putComponent(VolumeComponent.class, getVolumeComponent()); setDefaultVolumeController(); diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk index b32bf99ad53d7..83ec33c696299 100644 --- a/packages/SystemUI/tests/Android.mk +++ b/packages/SystemUI/tests/Android.mk @@ -38,8 +38,6 @@ LOCAL_JAVA_LIBRARIES := \ android.test.runner \ telephony-common \ android.test.base \ - android.car \ - android.car.userlib LOCAL_AAPT_FLAGS := --extra-packages com.android.systemui:com.android.keyguard diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java deleted file mode 100644 index f89a93264b0c3..0000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/car/CarQsFragmentTest.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2017 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.qs.car; - -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.mock; - -import android.content.Context; -import android.support.test.filters.SmallTest; -import android.testing.AndroidTestingRunner; -import android.testing.LayoutInflaterBuilder; -import android.testing.TestableLooper; -import android.testing.TestableLooper.RunWithLooper; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.keyguard.CarrierText; -import com.android.systemui.Dependency; -import com.android.systemui.SysuiBaseFragmentTest; -import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.policy.Clock; - -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; -import org.junit.runner.RunWith; - -/** - * Tests for {@link CarQSFragment}. - */ -@RunWith(AndroidTestingRunner.class) -@RunWithLooper(setAsMainLooper = true) -@SmallTest -@Ignore -public class CarQsFragmentTest extends SysuiBaseFragmentTest { - public CarQsFragmentTest() { - super(CarQSFragment.class); - } - - @Before - public void initDependencies() { - mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, - new LayoutInflaterBuilder(mContext) - .replace("com.android.systemui.statusbar.policy.SplitClockView", - FrameLayout.class) - .replace("TextClock", View.class) - .replace(CarrierText.class, View.class) - .replace(Clock.class, View.class) - .build()); - mSysuiContext.putComponent(CommandQueue.class, mock(CommandQueue.class)); - mDependency.injectTestDependency(Dependency.BG_LOOPER, - TestableLooper.get(this).getLooper()); - } - - @Test - @Ignore("Flaky") - public void testLayoutInflation() { - CarQSFragment fragment = (CarQSFragment) mFragment; - mFragments.dispatchResume(); - - assertNotNull(fragment.getHeader()); - assertNotNull(fragment.getFooter()); - } - - @Test - @Ignore("Flaky") - public void testListening() { - CarQSFragment qs = (CarQSFragment) mFragment; - mFragments.dispatchResume(); - processAllMessages(); - - qs.setListening(true); - processAllMessages(); - - qs.setListening(false); - processAllMessages(); - } -}