Use custom QS fragment for auto use-case.

Use a custom QS fragment if the UI mode is car. This fragment disables
the quick settings row and expansion. Remove the config options that
used to have disabled this in the phone QSFragment.

To accomplish this, introduce a new QSFooter interface. The old
QSFooter.java now implements this.

Test: boot on phone and Android Auto headunit
Bug: 33210494
Change-Id: I5accc2d27d6725380ca5e271d332a03991c9419b
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
new file mode 100644
index 0000000..94da5f7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -0,0 +1,414 @@
+/*
+ * 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;
+
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_DATE;
+
+import android.app.ActivityManager;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.PorterDuff.Mode;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.RippleDrawable;
+import android.os.UserManager;
+import android.provider.AlarmClock;
+import android.support.annotation.Nullable;
+import android.support.annotation.VisibleForTesting;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto;
+import com.android.keyguard.KeyguardStatusView;
+import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
+import com.android.systemui.FontSizeUtils;
+import com.android.systemui.R;
+import com.android.systemui.R.dimen;
+import com.android.systemui.R.id;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.qs.TouchAnimator.Builder;
+import com.android.systemui.qs.TouchAnimator.Listener;
+import com.android.systemui.qs.TouchAnimator.ListenerAdapter;
+import com.android.systemui.statusbar.phone.ExpandableIndicator;
+import com.android.systemui.statusbar.phone.MultiUserSwitch;
+import com.android.systemui.statusbar.phone.SettingsButton;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkController.EmergencyListener;
+import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmController.NextAlarmChangeCallback;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
+import com.android.systemui.tuner.TunerService;
+
+public class QSFooterImpl extends FrameLayout implements QSFooter,
+        NextAlarmChangeCallback, OnClickListener, OnUserInfoChangedListener, EmergencyListener,
+        SignalCallback {
+    private static final float EXPAND_INDICATOR_THRESHOLD = .93f;
+
+    private ActivityStarter mActivityStarter;
+    private NextAlarmController mNextAlarmController;
+    private UserInfoController mUserInfoController;
+    private SettingsButton mSettingsButton;
+    protected View mSettingsContainer;
+
+    private TextView mAlarmStatus;
+    private View mAlarmStatusCollapsed;
+    private View mDate;
+
+    private QSPanel mQsPanel;
+
+    private boolean mExpanded;
+    private boolean mAlarmShowing;
+
+    protected ExpandableIndicator mExpandIndicator;
+
+    private boolean mListening;
+    private AlarmManager.AlarmClockInfo mNextAlarm;
+
+    private boolean mShowEmergencyCallsOnly;
+    protected MultiUserSwitch mMultiUserSwitch;
+    private ImageView mMultiUserAvatar;
+
+    protected TouchAnimator mSettingsAlpha;
+    private float mExpansionAmount;
+
+    protected View mEdit;
+    private TouchAnimator mAnimator;
+    private View mDateTimeGroup;
+    private boolean mKeyguardShowing;
+    private TouchAnimator mAlarmAnimator;
+
+    public QSFooterImpl(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        Resources res = getResources();
+
+        mEdit = findViewById(android.R.id.edit);
+        mEdit.setOnClickListener(view ->
+                Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() ->
+                        mQsPanel.showEdit(view)));
+
+        mDateTimeGroup = findViewById(id.date_time_alarm_group);
+        mDate = findViewById(R.id.date);
+
+        mExpandIndicator = findViewById(R.id.expand_indicator);
+        mSettingsButton = findViewById(R.id.settings_button);
+        mSettingsContainer = findViewById(R.id.settings_button_container);
+        mSettingsButton.setOnClickListener(this);
+
+        mAlarmStatusCollapsed = findViewById(R.id.alarm_status_collapsed);
+        mAlarmStatus = findViewById(R.id.alarm_status);
+        mDateTimeGroup.setOnClickListener(this);
+
+        mMultiUserSwitch = findViewById(R.id.multi_user_switch);
+        mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar);
+
+        // RenderThread is doing more harm than good when touching the header (to expand quick
+        // settings), so disable it for this view
+        ((RippleDrawable) mSettingsButton.getBackground()).setForceSoftware(true);
+        ((RippleDrawable) mExpandIndicator.getBackground()).setForceSoftware(true);
+
+        updateResources();
+
+        mNextAlarmController = Dependency.get(NextAlarmController.class);
+        mUserInfoController = Dependency.get(UserInfoController.class);
+        mActivityStarter = Dependency.get(ActivityStarter.class);
+        addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
+                oldBottom) -> updateAnimator(right - left));
+    }
+
+    private void updateAnimator(int width) {
+        int numTiles = QuickQSPanel.getNumQuickTiles(mContext);
+        int size = mContext.getResources().getDimensionPixelSize(R.dimen.qs_quick_tile_size)
+                - mContext.getResources().getDimensionPixelSize(dimen.qs_quick_tile_padding);
+        int remaining = (width - numTiles * size) / (numTiles - 1);
+        int defSpace = mContext.getResources().getDimensionPixelOffset(R.dimen.default_gear_space);
+
+        mAnimator = new Builder()
+                .addFloat(mSettingsContainer, "translationX", -(remaining - defSpace), 0)
+                .addFloat(mSettingsButton, "rotation", -120, 0)
+                .build();
+        if (mAlarmShowing) {
+            mAlarmAnimator = new Builder().addFloat(mDate, "alpha", 1, 0)
+                    .addFloat(mDateTimeGroup, "translationX", 0, -mDate.getWidth())
+                    .addFloat(mAlarmStatus, "alpha", 0, 1)
+                    .setListener(new ListenerAdapter() {
+                        @Override
+                        public void onAnimationAtStart() {
+                            mAlarmStatus.setVisibility(View.GONE);
+                        }
+
+                        @Override
+                        public void onAnimationStarted() {
+                            mAlarmStatus.setVisibility(View.VISIBLE);
+                        }
+                    }).build();
+        } else {
+            mAlarmAnimator = null;
+            mAlarmStatus.setVisibility(View.GONE);
+            mDate.setAlpha(1);
+            mDateTimeGroup.setTranslationX(0);
+        }
+        setExpansion(mExpansionAmount);
+    }
+
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        updateResources();
+    }
+
+    @Override
+    public void onRtlPropertiesChanged(int layoutDirection) {
+        super.onRtlPropertiesChanged(layoutDirection);
+        updateResources();
+    }
+
+    private void updateResources() {
+        FontSizeUtils.updateFontSize(mAlarmStatus, R.dimen.qs_date_collapsed_size);
+
+        updateSettingsAnimator();
+    }
+
+    private void updateSettingsAnimator() {
+        mSettingsAlpha = createSettingsAlphaAnimator();
+
+        final boolean isRtl = isLayoutRtl();
+        if (isRtl && mDate.getWidth() == 0) {
+            mDate.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+                @Override
+                public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                        int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                    mDate.setPivotX(getWidth());
+                    mDate.removeOnLayoutChangeListener(this);
+                }
+            });
+        } else {
+            mDate.setPivotX(isRtl ? mDate.getWidth() : 0);
+        }
+    }
+
+    @Nullable
+    private TouchAnimator createSettingsAlphaAnimator() {
+        return new TouchAnimator.Builder()
+                .addFloat(mEdit, "alpha", 0, 1)
+                .addFloat(mMultiUserSwitch, "alpha", 0, 1)
+                .build();
+    }
+
+    @Override
+    public void setKeyguardShowing(boolean keyguardShowing) {
+        mKeyguardShowing = keyguardShowing;
+        setExpansion(mExpansionAmount);
+    }
+
+    @Override
+    public void setExpanded(boolean expanded) {
+        if (mExpanded == expanded) return;
+        mExpanded = expanded;
+        updateEverything();
+    }
+
+    @Override
+    public void onNextAlarmChanged(AlarmManager.AlarmClockInfo nextAlarm) {
+        mNextAlarm = nextAlarm;
+        if (nextAlarm != null) {
+            String alarmString = KeyguardStatusView.formatNextAlarm(getContext(), nextAlarm);
+            mAlarmStatus.setText(alarmString);
+            mAlarmStatus.setContentDescription(mContext.getString(
+                    R.string.accessibility_quick_settings_alarm, alarmString));
+            mAlarmStatusCollapsed.setContentDescription(mContext.getString(
+                    R.string.accessibility_quick_settings_alarm, alarmString));
+        }
+        if (mAlarmShowing != (nextAlarm != null)) {
+            mAlarmShowing = nextAlarm != null;
+            updateAnimator(getWidth());
+            updateEverything();
+        }
+    }
+
+    @Override
+    public void setExpansion(float headerExpansionFraction) {
+        mExpansionAmount = headerExpansionFraction;
+        if (mAnimator != null) mAnimator.setPosition(headerExpansionFraction);
+        if (mAlarmAnimator != null) mAlarmAnimator.setPosition(
+                mKeyguardShowing ? 0 : headerExpansionFraction);
+
+        if (mSettingsAlpha != null) {
+            mSettingsAlpha.setPosition(headerExpansionFraction);
+        }
+
+        updateAlarmVisibilities();
+
+        mExpandIndicator.setExpanded(headerExpansionFraction > EXPAND_INDICATOR_THRESHOLD);
+    }
+
+    @Override
+    @VisibleForTesting
+    public void onDetachedFromWindow() {
+        setListening(false);
+        super.onDetachedFromWindow();
+    }
+
+    private void updateAlarmVisibilities() {
+        mAlarmStatusCollapsed.setVisibility(mAlarmShowing ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public void setListening(boolean listening) {
+        if (listening == mListening) {
+            return;
+        }
+        mListening = listening;
+        updateListeners();
+    }
+
+    @Override
+    public View getExpandView() {
+        return findViewById(R.id.expand_indicator);
+    }
+
+    public void updateEverything() {
+        post(() -> {
+            updateVisibilities();
+            setClickable(false);
+        });
+    }
+
+    private void updateVisibilities() {
+        updateAlarmVisibilities();
+        mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
+                TunerService.isTunerEnabled(mContext) ? View.VISIBLE : View.INVISIBLE);
+        final boolean isDemo = UserManager.isDeviceInDemoMode(mContext);
+
+        mMultiUserSwitch.setVisibility(mExpanded && mMultiUserSwitch.hasMultipleUsers() && !isDemo
+                ? View.VISIBLE : View.INVISIBLE);
+
+        mEdit.setVisibility(isDemo || !mExpanded ? View.INVISIBLE : View.VISIBLE);
+    }
+
+    private void updateListeners() {
+        if (mListening) {
+            mNextAlarmController.addCallback(this);
+            mUserInfoController.addCallback(this);
+            if (Dependency.get(NetworkController.class).hasVoiceCallingFeature()) {
+                Dependency.get(NetworkController.class).addEmergencyListener(this);
+                Dependency.get(NetworkController.class).addCallback(this);
+            }
+        } else {
+            mNextAlarmController.removeCallback(this);
+            mUserInfoController.removeCallback(this);
+            Dependency.get(NetworkController.class).removeEmergencyListener(this);
+            Dependency.get(NetworkController.class).removeCallback(this);
+        }
+    }
+
+    @Override
+    public void setQSPanel(final QSPanel qsPanel) {
+        mQsPanel = qsPanel;
+        if (mQsPanel != null) {
+            mMultiUserSwitch.setQsPanel(qsPanel);
+        }
+    }
+
+    @Override
+    public void onClick(View v) {
+        if (v == mSettingsButton) {
+            if (!Dependency.get(DeviceProvisionedController.class).isCurrentUserSetup()) {
+                // If user isn't setup just unlock the device and dump them back at SUW.
+                mActivityStarter.postQSRunnableDismissingKeyguard(() -> { });
+                return;
+            }
+            MetricsLogger.action(mContext,
+                    mExpanded ? MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH
+                            : MetricsProto.MetricsEvent.ACTION_QS_COLLAPSED_SETTINGS_LAUNCH);
+            if (mSettingsButton.isTunerClick()) {
+                Dependency.get(ActivityStarter.class).postQSRunnableDismissingKeyguard(() -> {
+                    if (TunerService.isTunerEnabled(mContext)) {
+                        TunerService.showResetRequest(mContext, () -> {
+                            // Relaunch settings so that the tuner disappears.
+                            startSettingsActivity();
+                        });
+                    } else {
+                        Toast.makeText(getContext(), R.string.tuner_toast,
+                                Toast.LENGTH_LONG).show();
+                        TunerService.setTunerEnabled(mContext, true);
+                    }
+                    startSettingsActivity();
+
+                });
+            } else {
+                startSettingsActivity();
+            }
+        } else if (v == mDateTimeGroup) {
+            Dependency.get(MetricsLogger.class).action(ACTION_QS_DATE,
+                    mNextAlarm != null);
+            if (mNextAlarm != null) {
+                PendingIntent showIntent = mNextAlarm.getShowIntent();
+                mActivityStarter.startPendingIntentDismissingKeyguard(showIntent);
+            } else {
+                mActivityStarter.postStartActivityDismissingKeyguard(new Intent(
+                        AlarmClock.ACTION_SHOW_ALARMS), 0);
+            }
+        }
+    }
+
+    private void startSettingsActivity() {
+        mActivityStarter.startActivity(new Intent(android.provider.Settings.ACTION_SETTINGS),
+                true /* dismissShade */);
+    }
+
+    @Override
+    public void setEmergencyCallsOnly(boolean show) {
+        boolean changed = show != mShowEmergencyCallsOnly;
+        if (changed) {
+            mShowEmergencyCallsOnly = show;
+            if (mExpanded) {
+                updateEverything();
+            }
+        }
+    }
+
+    @Override
+    public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
+        if (picture != null &&
+                UserManager.get(mContext).isGuestUser(ActivityManager.getCurrentUser())) {
+            picture = picture.getConstantState().newDrawable().mutate();
+            picture.setColorFilter(
+                    Utils.getColorAttr(mContext, android.R.attr.colorForeground),
+                    Mode.SRC_IN);
+        }
+        mMultiUserAvatar.setImageDrawable(picture);
+    }
+}