Remove SignalClusterView in favor of IconManager

Refactors SignalClusterView into StatusBarSignalPolicy so that it can be
used in a StatusBarIconContainer and solve all of our status bar
problems.

- Remove all uses of SignalClusterView and references to
  R.id.signal_cluster. The class still exists it's just unused now

- Add StatusBarIconHolder, which can point to StatusBarIcon,
  WifiIconState, or PhoneIconState

- StatusBarIconList.Slot. Allows for easier indexing of icons now that
  there can be multiple icons per slot

- Add StatusBarWifiView to be inflated inside of the
  StatusBarIconController when needed

- StatusBarMobile view. similar to above

- Upgrade StatusBarIconControllerImpl and StatusBarIconList to
  understand the holders and added 2 new methods to specifically handle
  wifi / phone state changes

- Create IStatusBarIconView (todo: rename). Abstracts the properties we
  want away from StatusBarIconView so that we can use an arbitrary view
  type

- NeutralGoodDrawable. Draws a light and a dark icon when needed.

- Fixes a few demo mode bugs: multi sim was broken and also turning off
  demo mode was a little broken

TODO: More tests are needed for StatusBarSignalPolicy and maybe the
IconManagers

Test: runtest systemui; visual
Bug: 63772836
Bug: 73778753
Bug: 74985733
Fixes: 74427768
Fixes: 74338687
Fixes: 74388467

Change-Id: I5621b3013cdc9638b61552bd4d7211f211eddf1b
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
new file mode 100644
index 0000000..afd373e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarWifiView.java
@@ -0,0 +1,192 @@
+/*
+ * 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.statusbar;
+
+import static com.android.systemui.statusbar.policy.DarkIconDispatcher.getTint;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+
+import com.android.keyguard.AlphaOptimizedLinearLayout;
+import com.android.settingslib.Utils;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
+
+/**
+ * Start small: StatusBarWifiView will be able to layout from a WifiIconState
+ */
+public class StatusBarWifiView extends AlphaOptimizedLinearLayout implements DarkReceiver,
+        StatusIconDisplayable {
+    private static final String TAG = "StatusBarWifiView";
+
+    private ImageView mWifiIcon;
+    private ImageView mIn;
+    private ImageView mOut;
+    private View mInoutContainer;
+    private View mSignalSpacer;
+    private View mAirplaneSpacer;
+    private WifiIconState mState;
+    private String mSlot;
+    private float mDarkIntensity = 0;
+
+    private ContextThemeWrapper mDarkContext;
+    private ContextThemeWrapper mLightContext;
+
+    public static StatusBarWifiView fromContext(Context context) {
+        LayoutInflater inflater = LayoutInflater.from(context);
+        return (StatusBarWifiView) inflater.inflate(R.layout.status_bar_wifi_group, null);
+    }
+
+    public StatusBarWifiView(Context context) {
+        super(context);
+    }
+
+    public StatusBarWifiView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public StatusBarWifiView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public StatusBarWifiView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        init();
+    }
+
+    public void setSlot(String slot) {
+        mSlot = slot;
+    }
+
+    @Override
+    public void setStaticDrawableColor(int color) {
+        ColorStateList list = ColorStateList.valueOf(color);
+        mWifiIcon.setImageTintList(list);
+        mIn.setImageTintList(list);
+        mOut.setImageTintList(list);
+    }
+
+    @Override
+    public String getSlot() {
+        return mSlot;
+    }
+
+    @Override
+    public boolean isIconVisible() {
+        return mState != null && mState.visible;
+    }
+
+    private void init() {
+        int dualToneLightTheme = Utils.getThemeAttr(mContext, R.attr.lightIconTheme);
+        int dualToneDarkTheme = Utils.getThemeAttr(mContext, R.attr.darkIconTheme);
+        mLightContext = new ContextThemeWrapper(mContext, dualToneLightTheme);
+        mDarkContext = new ContextThemeWrapper(mContext, dualToneDarkTheme);
+
+        mWifiIcon = findViewById(R.id.wifi_signal);
+        mIn = findViewById(R.id.wifi_in);
+        mOut = findViewById(R.id.wifi_out);
+        mSignalSpacer = findViewById(R.id.wifi_signal_spacer);
+        mAirplaneSpacer = findViewById(R.id.wifi_airplane_spacer);
+        mInoutContainer = findViewById(R.id.inout_container);
+    }
+
+    public void applyWifiState(WifiIconState state) {
+        if (state == null) {
+            setVisibility(View.GONE);
+            mState = null;
+            return;
+        }
+
+        if (mState == null) {
+            mState = state;
+            initViewState();
+        }
+
+        if (!mState.equals(state)) {
+            updateState(state);
+        }
+    }
+
+    private void updateState(WifiIconState state) {
+        if (mState.resId != state.resId && state.resId >= 0) {
+            NeutralGoodDrawable drawable = NeutralGoodDrawable
+                    .create(mLightContext, mDarkContext, state.resId);
+            drawable.setDarkIntensity(mDarkIntensity);
+            mWifiIcon.setImageDrawable(drawable);
+        }
+
+        mIn.setVisibility(state.activityIn ? View.VISIBLE : View.GONE);
+        mOut.setVisibility(state.activityOut ? View.VISIBLE : View.GONE);
+        mInoutContainer.setVisibility(
+                (state.activityIn || state.activityOut) ? View.VISIBLE : View.GONE);
+        mAirplaneSpacer.setVisibility(state.airplaneSpacerVisible ? View.VISIBLE : View.GONE);
+        mSignalSpacer.setVisibility(state.signalSpacerVisible ? View.VISIBLE : View.GONE);
+        if (mState.visible != state.visible) {
+            setVisibility(state.visible ? View.VISIBLE : View.GONE);
+        }
+
+        mState = state;
+    }
+
+    private void initViewState() {
+        if (mState.resId >= 0) {
+            NeutralGoodDrawable drawable = NeutralGoodDrawable.create(
+                    mLightContext, mDarkContext, mState.resId);
+            drawable.setDarkIntensity(mDarkIntensity);
+            mWifiIcon.setImageDrawable(drawable);
+        }
+
+        mIn.setVisibility(mState.activityIn ? View.VISIBLE : View.GONE);
+        mOut.setVisibility(mState.activityOut ? View.VISIBLE : View.GONE);
+        mInoutContainer.setVisibility(
+                (mState.activityIn || mState.activityOut) ? View.VISIBLE : View.GONE);
+        mAirplaneSpacer.setVisibility(mState.airplaneSpacerVisible ? View.VISIBLE : View.GONE);
+        mSignalSpacer.setVisibility(mState.signalSpacerVisible ? View.VISIBLE : View.GONE);
+        setVisibility(mState.visible ? View.VISIBLE : View.GONE);
+    }
+
+    @Override
+    public void onDarkChanged(Rect area, float darkIntensity, int tint) {
+        mDarkIntensity = darkIntensity;
+        Drawable d = mWifiIcon.getDrawable();
+        if (d instanceof NeutralGoodDrawable) {
+            ((NeutralGoodDrawable)d).setDarkIntensity(darkIntensity);
+        }
+        mIn.setImageTintList(ColorStateList.valueOf(getTint(area, this, tint)));
+        mOut.setImageTintList(ColorStateList.valueOf(getTint(area, this, tint)));
+    }
+
+
+    @Override
+    public String toString() {
+        return "StatusBarWifiView(slot=" + mSlot + " state=" + mState + ")";
+    }
+}