Add separated emergency option on power menu

 - Add a separated button on power menu to launch emergency dialer.
 - Change HardwareUiLayout.java FrameLayout to LinearLayout, let it can
display separated button.
 - Add a flag to recognize separated button should show/hide, if
EmergencyAffordance(India) enabled, separated button will hide,
otherwise power menu will display separated button & power
menu last item won't get white background.

Test: Manually, use "adb shell settings put global faster_emergency_phone_call_enabled 1" to show/hide separated emergency option, press emergency option will go to emergency dialer.
Change-Id: I1140fa412b655c16f3052cbabd118df278fd7f23
Merged-In: I8e6bb72ce7b8cecdb6bd01150b53f61f1515dbb1
Merged-In: I1140fa412b655c16f3052cbabd118df278fd7f23

Bug: 112168722
Bug: 80376488
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 50220e5..db03eee 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2623,8 +2623,8 @@
         <item>lockdown</item>
         <item>logout</item>
         <item>bugreport</item>
-        <item>emergency</item>
         <item>screenshot</item>
+        <item>emergency</item>
     </string-array>
 
     <!-- Number of milliseconds to hold a wake lock to ensure that drawing is fully
diff --git a/packages/SystemUI/res/drawable/faster_emergency_icon.xml b/packages/SystemUI/res/drawable/faster_emergency_icon.xml
new file mode 100644
index 0000000..208ff41
--- /dev/null
+++ b/packages/SystemUI/res/drawable/faster_emergency_icon.xml
@@ -0,0 +1,30 @@
+<!--
+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.
+-->
+<!-- TODO: For demo only, will change content after UI team provide new faster emergency icon. -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24.0dp"
+        android:height="24.0dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="#D93025"
+        android:pathData="M0,0h24v24H0z" />
+    <path
+        android:fillColor="#FFFFFFFF"
+        android:pathData="M19,3H5c-1.1,0-1.99,0.9,-1.99,2L3,19c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V5c0-1.1-0.9-2-2-2zm-1,11h-4v4h-4v-4H6v-4h4V6h4v4h4v4z" />
+
+</vector>
diff --git a/packages/SystemUI/res/layout/global_actions_wrapped.xml b/packages/SystemUI/res/layout/global_actions_wrapped.xml
index b715def..7f4e0d2 100644
--- a/packages/SystemUI/res/layout/global_actions_wrapped.xml
+++ b/packages/SystemUI/res/layout/global_actions_wrapped.xml
@@ -3,7 +3,9 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
+    android:layout_gravity="top|right"
     android:layout_marginBottom="0dp"
+    android:orientation="vertical"
     android:paddingTop="@dimen/global_actions_top_padding"
     android:clipToPadding="false"
     android:theme="@style/qs_theme"
@@ -17,7 +19,19 @@
         android:layout_gravity="top|right"
         android:gravity="center"
         android:orientation="vertical"
-        android:padding="12dp"
-        android:translationZ="9dp" />
+        android:padding="@dimen/global_actions_padding"
+        android:translationZ="@dimen/global_actions_translate" />
+
+    <!-- For separated button-->
+    <FrameLayout
+        android:id="@+id/separated_button"
+        android:layout_width="@dimen/global_actions_panel_width"
+        android:layout_height="wrap_content"
+        android:layout_gravity="top|right"
+        android:layout_marginTop="6dp"
+        android:gravity="center"
+        android:orientation="vertical"
+        android:padding="@dimen/global_actions_padding"
+        android:translationZ="@dimen/global_actions_translate" />
 
 </com.android.systemui.HardwareUiLayout>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 7d90e02..79e1fae 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -922,6 +922,10 @@
 
     <dimen name="global_actions_top_padding">120dp</dimen>
 
+    <dimen name="global_actions_padding">12dp</dimen>
+
+    <dimen name="global_actions_translate">9dp</dimen>
+
     <!-- The maximum offset in either direction that elements are moved horizontally to prevent
          burn-in on AOD. -->
     <dimen name="burn_in_prevention_offset_x">8dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index 98dc321..7742c55 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -27,24 +27,22 @@
 import android.view.ViewGroup;
 import android.view.ViewOutlineProvider;
 import android.view.ViewTreeObserver;
-import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
 import com.android.systemui.util.leak.RotationUtils;
 
-import java.util.ArrayList;
-
 import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
 import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
 import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
 
-public class HardwareUiLayout extends FrameLayout implements Tunable {
+public class HardwareUiLayout extends LinearLayout implements Tunable {
 
     private static final String EDGE_BLEED = "sysui_hwui_edge_bleed";
     private static final String ROUNDED_DIVIDER = "sysui_hwui_rounded_divider";
     private final int[] mTmp2 = new int[2];
     private View mChild;
+    private View mSeparatedView;
     private int mOldHeight;
     private boolean mAnimating;
     private AnimatorSet mAnimation;
@@ -53,6 +51,7 @@
     private HardwareBgDrawable mBackground;
     private Animator mAnimator;
     private boolean mCollapse;
+    private boolean mHasSeparatedButton;
     private int mEndPoint;
     private boolean mEdgeBleed;
     private boolean mRoundedDivider;
@@ -94,6 +93,7 @@
         mBackground = new HardwareBgDrawable(mRoundedDivider, !mEdgeBleed, getContext());
         if (mChild != null) {
             mChild.setBackground(mBackground);
+            mSeparatedView.setBackground(mBackground);
             requestLayout();
         }
     }
@@ -110,6 +110,18 @@
             }
             mChild.setLayoutParams(params);
         }
+
+        if (mSeparatedView != null) {
+            MarginLayoutParams params = (MarginLayoutParams) mSeparatedView.getLayoutParams();
+            if (mRotation == ROTATION_LANDSCAPE) {
+                params.topMargin = edge;
+            } else if (mRotation == ROTATION_SEASCAPE) {
+                params.bottomMargin = edge;
+            } else {
+                params.rightMargin = edge;
+            }
+            mSeparatedView.setLayoutParams(params);
+        }
     }
 
     private int getEdgePadding() {
@@ -123,6 +135,8 @@
             if (getChildCount() != 0) {
                 mChild = getChildAt(0);
                 mChild.setBackground(mBackground);
+                mSeparatedView = getChildAt(1);
+                mSeparatedView.setBackground(mBackground);
                 updateEdgeMargin(mEdgeBleed ? 0 : getEdgePadding());
                 mOldHeight = mChild.getMeasuredHeight();
                 mChild.addOnLayoutChangeListener(
@@ -170,6 +184,17 @@
         } else {
             rotateLeft();
         }
+        if (mHasSeparatedButton) {
+            if (from == ROTATION_SEASCAPE || to == ROTATION_SEASCAPE) {
+                // Separated view has top margin, so seascape separated view need special rotation,
+                // not a full left or right rotation.
+                swapLeftAndTop(mSeparatedView);
+            } else if (from == ROTATION_LANDSCAPE) {
+                rotateRight(mSeparatedView);
+            } else {
+                rotateLeft(mSeparatedView);
+            }
+        }
         if (to != ROTATION_NONE) {
             if (mChild instanceof LinearLayout) {
                 mRotatedBackground = true;
@@ -177,8 +202,10 @@
                 LinearLayout linearLayout = (LinearLayout) mChild;
                 if (mSwapOrientation) {
                     linearLayout.setOrientation(LinearLayout.HORIZONTAL);
+                    setOrientation(LinearLayout.HORIZONTAL);
                 }
-                swapDimens(this.mChild);
+                swapDimens(mChild);
+                swapDimens(mSeparatedView);
             }
         } else {
             if (mChild instanceof LinearLayout) {
@@ -187,8 +214,10 @@
                 LinearLayout linearLayout = (LinearLayout) mChild;
                 if (mSwapOrientation) {
                     linearLayout.setOrientation(LinearLayout.VERTICAL);
+                    setOrientation(LinearLayout.VERTICAL);
                 }
                 swapDimens(mChild);
+                swapDimens(mSeparatedView);
             }
         }
     }
@@ -201,6 +230,12 @@
         LayoutParams p = (LayoutParams) mChild.getLayoutParams();
         p.gravity = rotateGravityRight(p.gravity);
         mChild.setLayoutParams(p);
+
+        LayoutParams separatedViewLayoutParams = (LayoutParams) mSeparatedView.getLayoutParams();
+        separatedViewLayoutParams.gravity = rotateGravityRight(separatedViewLayoutParams.gravity);
+        mSeparatedView.setLayoutParams(separatedViewLayoutParams);
+
+        setGravity(p.gravity);
     }
 
     private void swapDimens(View v) {
@@ -253,6 +288,12 @@
         LayoutParams p = (LayoutParams) mChild.getLayoutParams();
         p.gravity = rotateGravityLeft(p.gravity);
         mChild.setLayoutParams(p);
+
+        LayoutParams separatedViewLayoutParams = (LayoutParams) mSeparatedView.getLayoutParams();
+        separatedViewLayoutParams.gravity = rotateGravityLeft(separatedViewLayoutParams.gravity);
+        mSeparatedView.setLayoutParams(separatedViewLayoutParams);
+
+        setGravity(p.gravity);
     }
 
     private int rotateGravityLeft(int gravity) {
@@ -310,6 +351,15 @@
         v.setLayoutParams(params);
     }
 
+    private void swapLeftAndTop(View v) {
+        v.setPadding(v.getPaddingTop(), v.getPaddingLeft(), v.getPaddingBottom(),
+                v.getPaddingRight());
+        MarginLayoutParams params = (MarginLayoutParams) v.getLayoutParams();
+        params.setMargins(params.topMargin, params.leftMargin, params.bottomMargin,
+                params.rightMargin);
+        v.setLayoutParams(params);
+    }
+
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
         super.onLayout(changed, left, top, right, bottom);
@@ -351,6 +401,9 @@
 
     private void updatePosition() {
         if (mChild == null) return;
+        // If got separated button, setRotatedBackground to false,
+        // all items won't get white background.
+        mBackground.setRotatedBackground(mHasSeparatedButton);
         if (mDivision != null && mDivision.getVisibility() == VISIBLE) {
             int index = mRotatedBackground ? 0 : 1;
             mDivision.getLocationOnScreen(mTmp2);
@@ -404,6 +457,10 @@
         mCollapse = true;
     }
 
+    public void setHasSeparatedButton(boolean hasSeparatedButton) {
+        mHasSeparatedButton = hasSeparatedButton;
+    }
+
     public static HardwareUiLayout get(View v) {
         if (v instanceof HardwareUiLayout) return (HardwareUiLayout) v;
         if (v.getParent() instanceof View) {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 92674d4..532fa034a 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -28,12 +28,10 @@
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.TrustManager;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.ServiceConnection;
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.graphics.Point;
@@ -42,9 +40,7 @@
 import android.net.ConnectivityManager;
 import android.os.Build;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.Message;
-import android.os.Messenger;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
@@ -68,9 +64,9 @@
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.accessibility.AccessibilityEvent;
-import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemLongClickListener;
 import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.ImageView.ScaleType;
 import android.widget.LinearLayout;
@@ -150,6 +146,7 @@
     private boolean mDeviceProvisioned = false;
     private ToggleAction.State mAirplaneState = ToggleAction.State.Off;
     private boolean mIsWaitingForEcmExit = false;
+    private boolean mHasFasterEmergencyButton;
     private boolean mHasTelephony;
     private boolean mHasVibrator;
     private boolean mHasLogoutButton;
@@ -320,6 +317,7 @@
         ArraySet<String> addedKeys = new ArraySet<String>();
         mHasLogoutButton = false;
         mHasLockdownButton = false;
+        mHasFasterEmergencyButton = false;
         for (int i = 0; i < defaultActions.length; i++) {
             String actionKey = defaultActions[i];
             if (addedKeys.contains(actionKey)) {
@@ -363,6 +361,7 @@
                         Settings.Global.FASTER_EMERGENCY_PHONE_CALL_ENABLED, 0) != 0
                         && !mEmergencyAffordanceManager.needsEmergencyAffordance()) {
                     mItems.add(new EmergencyAction());
+                    mHasFasterEmergencyButton = true;
                 }
             } else if (GLOBAL_ACTION_KEY_SCREENSHOT.equals(actionKey)) {
                 mItems.add(new ScreenshotAction());
@@ -393,7 +392,8 @@
             }
             return false;
         };
-        ActionsDialog dialog = new ActionsDialog(mContext, this, mAdapter, onItemLongClickListener);
+        ActionsDialog dialog = new ActionsDialog(mContext, this, mAdapter, onItemLongClickListener,
+                mHasFasterEmergencyButton);
         dialog.setCanceledOnTouchOutside(false); // Handled by the custom class.
         dialog.setKeyguardShowing(mKeyguardShowing);
 
@@ -453,7 +453,8 @@
                 "com.android.phone.EmergencyDialer.DIAL";
 
         private EmergencyAction() {
-            super(R.drawable.emergency_icon, R.string.global_action_emergency);
+            super(com.android.systemui.R.drawable.faster_emergency_icon,
+                    R.string.global_action_emergency);
         }
 
         @Override
@@ -1387,15 +1388,17 @@
         private final Context mContext;
         private final MyAdapter mAdapter;
         private final LinearLayout mListView;
+        private final FrameLayout mSeparatedView;
         private final HardwareUiLayout mHardwareLayout;
         private final OnClickListener mClickListener;
         private final OnItemLongClickListener mLongClickListener;
         private final GradientDrawable mGradientDrawable;
         private final ColorExtractor mColorExtractor;
         private boolean mKeyguardShowing;
+        private boolean mShouldDisplaySeparatedButton;
 
         public ActionsDialog(Context context, OnClickListener clickListener, MyAdapter adapter,
-                OnItemLongClickListener longClickListener) {
+                OnItemLongClickListener longClickListener, boolean shouldDisplaySeparatedButton) {
             super(context, com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
             mContext = context;
             mAdapter = adapter;
@@ -1403,6 +1406,7 @@
             mLongClickListener = longClickListener;
             mGradientDrawable = new GradientDrawable(mContext);
             mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+            mShouldDisplaySeparatedButton = shouldDisplaySeparatedButton;
 
             // Window initialization
             Window window = getWindow();
@@ -1426,8 +1430,13 @@
 
             setContentView(com.android.systemui.R.layout.global_actions_wrapped);
             mListView = findViewById(android.R.id.list);
+            mSeparatedView = findViewById(com.android.systemui.R.id.separated_button);
+            if (!mShouldDisplaySeparatedButton) {
+                mSeparatedView.setVisibility(View.GONE);
+            }
             mHardwareLayout = HardwareUiLayout.get(mListView);
             mHardwareLayout.setOutsideTouchListener(view -> dismiss());
+            mHardwareLayout.setHasSeparatedButton(mShouldDisplaySeparatedButton);
             setTitle(R.string.global_actions);
             mListView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
                 @Override
@@ -1442,13 +1451,16 @@
 
         private void updateList() {
             mListView.removeAllViews();
+            mSeparatedView.removeAllViews();
             for (int i = 0; i < mAdapter.getCount(); i++) {
-                View v = mAdapter.getView(i, null, mListView);
+                ViewGroup parentView = mShouldDisplaySeparatedButton && i == mAdapter.getCount() - 1
+                        ? mSeparatedView : mListView;
+                View v = mAdapter.getView(i, null, parentView);
                 final int pos = i;
                 v.setOnClickListener(view -> mClickListener.onClick(this, pos));
                 v.setOnLongClickListener(view ->
                         mLongClickListener.onItemLongClick(null, v, pos, 0));
-                mListView.addView(v);
+                parentView.addView(v);
             }
         }