Merge "Fix robo test build error"
diff --git a/res/layout/panel_layout.xml b/res/layout/panel_layout.xml
index abe8f41..7a60dad 100644
--- a/res/layout/panel_layout.xml
+++ b/res/layout/panel_layout.xml
@@ -27,6 +27,51 @@
         android:layout_height="wrap_content"
         android:orientation="vertical">
 
+        <LinearLayout
+            android:id="@+id/panel_header"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="start|center_vertical"
+            android:orientation="horizontal"
+            android:visibility="gone">
+
+            <LinearLayout
+                android:layout_width="49dp"
+                android:layout_height="49dp"
+                android:gravity="center_vertical|center_horizontal"
+                android:orientation="horizontal"
+                android:layout_marginStart="10dp">
+                <ImageView
+                    android:id="@+id/title_icon"
+                    android:layout_height="wrap_content"
+                    android:layout_width="wrap_content"/>
+            </LinearLayout>
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginStart="25dp"
+                android:gravity="center_vertical"
+                android:orientation="vertical"
+                android:paddingBottom="9dp"
+                android:paddingTop="9dp">
+                <TextView
+                    android:id="@+id/header_title"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:textColor="?android:attr/textColorPrimary"
+                    android:textSize="20sp"/>
+
+                <TextView
+                    android:id="@+id/header_subtitle"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:ellipsize="end"
+                    android:maxLines="1" />
+
+            </LinearLayout>
+        </LinearLayout>
+
         <TextView
             android:id="@+id/panel_title"
             android:layout_width="match_parent"
diff --git a/src/com/android/settings/AllInOneTetherSettings.java b/src/com/android/settings/AllInOneTetherSettings.java
index d6366b2..fbf0280 100644
--- a/src/com/android/settings/AllInOneTetherSettings.java
+++ b/src/com/android/settings/AllInOneTetherSettings.java
@@ -20,21 +20,20 @@
 import static android.net.ConnectivityManager.TETHERING_WIFI;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_CHANGED_ACTION;
 
-import static com.android.settings.network.WifiTetherDisablePreferenceController
-        .KEY_ENABLE_WIFI_TETHERING;
+import static com.android.settings.network.WifiTetherDisablePreferenceController.KEY_ENABLE_WIFI_TETHERING;
 
 import android.app.settings.SettingsEnums;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothPan;
+import android.bluetooth.BluetoothProfile;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
-import android.net.ConnectivityManager;
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
 import android.os.UserManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -47,6 +46,8 @@
 import com.android.settings.datausage.DataSaverBackend;
 import com.android.settings.network.TetherEnabler;
 import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.widget.SwitchBar;
+import com.android.settings.widget.SwitchBarController;
 import com.android.settings.wifi.tether.WifiTetherApBandPreferenceController;
 import com.android.settings.wifi.tether.WifiTetherAutoOffPreferenceController;
 import com.android.settings.wifi.tether.WifiTetherBasePreferenceController;
@@ -59,10 +60,10 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
- * Displays preferences for Tethering.
- * TODO(b/147322704): Use TetherEnabler in this fragment to manage tethering switch on/off.
+ * Displays preferences for all Tethering options.
  * TODO(b/147323306): Add tether option preferences into this fragment after controllers created.
  */
 @SearchIndexable
@@ -96,6 +97,7 @@
 
     private WifiManager mWifiManager;
     private boolean mRestartWifiApAfterConfigChange;
+    private final AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<>();
 
     private WifiTetherSSIDPreferenceController mSSIDPreferenceController;
     private WifiTetherPasswordPreferenceController mPasswordPreferenceController;
@@ -103,8 +105,8 @@
     private WifiTetherSecurityPreferenceController mSecurityPreferenceController;
     private PreferenceGroup mWifiTetherGroup;
     private SharedPreferences mSharedPreferences;
-    private ConnectivityManager mConnectivityManager;
     private boolean mWifiTetherChosen;
+    private TetherEnabler mTetherEnabler;
 
     private final BroadcastReceiver mTetherChangeReceiver = new BroadcastReceiver() {
         @Override
@@ -118,19 +120,30 @@
                 if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED
                         && mRestartWifiApAfterConfigChange) {
                     mRestartWifiApAfterConfigChange = false;
-                    startTether();
+                    mTetherEnabler.startTethering(TETHERING_WIFI);
                 }
             } else if (TextUtils.equals(action, WIFI_AP_STATE_CHANGED_ACTION)) {
                 int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0);
                 if (state == WifiManager.WIFI_AP_STATE_DISABLED
                         && mRestartWifiApAfterConfigChange) {
                     mRestartWifiApAfterConfigChange = false;
-                    startTether();
+                    mTetherEnabler.startTethering(TETHERING_WIFI);
                 }
             }
         }
     };
 
+    private final BluetoothProfile.ServiceListener mProfileServiceListener =
+            new BluetoothProfile.ServiceListener() {
+                public void onServiceConnected(int profile, BluetoothProfile proxy) {
+                    mBluetoothPan.set((BluetoothPan) proxy);
+                }
+
+                public void onServiceDisconnected(int profile) {
+                    mBluetoothPan.set(null);
+                }
+            };
+
     @Override
     public int getMetricsCategory() {
         return SettingsEnums.TETHER;
@@ -144,8 +157,6 @@
     public void onAttach(Context context) {
         super.onAttach(context);
         mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
-        mConnectivityManager =
-                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
         mSharedPreferences =
                 context.getSharedPreferences(TetherEnabler.SHARED_PREF, Context.MODE_PRIVATE);
 
@@ -182,6 +193,27 @@
     }
 
     @Override
+    public void onActivityCreated(Bundle savedInstanceState) {
+        super.onActivityCreated(savedInstanceState);
+        if (mUnavailable) {
+            return;
+        }
+        // Assume we are in a SettingsActivity. This is only safe because we currently use
+        // SettingsActivity as base for all preference fragments.
+        final SettingsActivity activity = (SettingsActivity) getActivity();
+        BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+        if (adapter != null) {
+            adapter.getProfileProxy(activity.getApplicationContext(), mProfileServiceListener,
+                    BluetoothProfile.PAN);
+        }
+        final SwitchBar switchBar = activity.getSwitchBar();
+        mTetherEnabler = new TetherEnabler(activity,
+                new SwitchBarController(switchBar), mBluetoothPan);
+        getSettingsLifecycle().addObserver(mTetherEnabler);
+        switchBar.show();
+    }
+
+    @Override
     public void onStart() {
         super.onStart();
 
@@ -297,8 +329,7 @@
                 Log.d(TAG, "Wifi AP config changed while enabled, stop and restart");
             }
             mRestartWifiApAfterConfigChange = true;
-            // TODO(b/147322704): Use TethetEnabler to stop tethering.
-            mConnectivityManager.stopTethering(TETHERING_WIFI);
+            mTetherEnabler.stopTethering(TETHERING_WIFI);
         }
 
         if (controller instanceof WifiTetherSecurityPreferenceController) {
@@ -335,23 +366,6 @@
         }
     }
 
-    private void startTether() {
-        // TODO(b/147322704): Use TetherEnabler to start tethering.
-        if (mWifiManager.isWifiApEnabled()) {
-            return;
-        }
-        mConnectivityManager.startTethering(ConnectivityManager.TETHERING_WIFI,
-                true /*showProvisioningUi*/,
-                new ConnectivityManager.OnStartTetheringCallback() {
-                    @Override
-                    public void onTetheringFailed() {
-                        super.onTetheringFailed();
-                        // Do nothing. There is no UI to update at this point.
-                    }
-                },
-                new Handler(Looper.getMainLooper()));
-    }
-
     private void reConfigInitialExpandedChildCount() {
         getPreferenceScreen().setInitialExpandedChildrenCount(getInitialExpandedChildCount());
     }
diff --git a/src/com/android/settings/network/BluetoothTetherPreferenceController.java b/src/com/android/settings/network/BluetoothTetherPreferenceController.java
index 10849a0..327b6ac 100644
--- a/src/com/android/settings/network/BluetoothTetherPreferenceController.java
+++ b/src/com/android/settings/network/BluetoothTetherPreferenceController.java
@@ -47,8 +47,7 @@
 
     private static final String TAG = "BluetoothTetherPreferenceController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    @VisibleForTesting
-    static final String PREF_KEY = "enable_bluetooth_tethering";
+    public static final String PREF_KEY = "enable_bluetooth_tethering";
     private final ConnectivityManager mCm;
     private int mBluetoothState;
     private Preference mPreference;
diff --git a/src/com/android/settings/network/TetherEnabler.java b/src/com/android/settings/network/TetherEnabler.java
index 9021a26..e2b4c68 100644
--- a/src/com/android/settings/network/TetherEnabler.java
+++ b/src/com/android/settings/network/TetherEnabler.java
@@ -42,6 +42,7 @@
 import com.android.settings.datausage.DataSaverBackend;
 import com.android.settings.widget.SwitchWidgetController;
 
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.concurrent.atomic.AtomicReference;
 
@@ -78,14 +79,7 @@
     private final Context mContext;
 
     @VisibleForTesting
-    final ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback =
-            new ConnectivityManager.OnStartTetheringCallback() {
-                @Override
-                public void onTetheringFailed() {
-                    super.onTetheringFailed();
-                    mSwitchWidgetController.setChecked(false);
-                }
-            };
+    ConnectivityManager.OnStartTetheringCallback mOnStartTetheringCallback;
     private final AtomicReference<BluetoothPan> mBluetoothPan;
     private final SharedPreferences mSharedPreferences;
     private boolean mBluetoothEnableForTether;
@@ -110,11 +104,15 @@
         mDataSaverBackend.addListener(this);
         mSwitchWidgetController.setListener(this);
         mSwitchWidgetController.startListening();
-        IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
+
+        final IntentFilter filter = new IntentFilter(
+                ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
+        filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
         mContext.registerReceiver(mTetherChangeReceiver, filter);
-        mSwitchWidgetController.setChecked(isTethering());
-        setSwitchWidgetEnabled(true);
+
+        mOnStartTetheringCallback = new OnStartTetheringCallback(this);
+        updateState();
     }
 
     @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@@ -134,8 +132,14 @@
         mContext.unregisterReceiver(mTetherChangeReceiver);
     }
 
-    private void setSwitchWidgetEnabled(boolean enabled) {
-        mSwitchWidgetController.setEnabled(enabled && !mDataSaverEnabled);
+    private void updateState() {
+        mSwitchWidgetController.setChecked(isTethering());
+        mSwitchWidgetController.setEnabled(!mDataSaverEnabled);
+    }
+
+    private void updateState(String[] tethered) {
+        mSwitchWidgetController.setChecked(isTethering(tethered));
+        mSwitchWidgetController.setEnabled(!mDataSaverEnabled);
     }
 
     private boolean isTethering() {
@@ -148,6 +152,10 @@
             return true;
         }
 
+        if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
+            return true;
+        }
+
         final BluetoothPan pan = mBluetoothPan.get();
 
         return pan != null && pan.isTetheringOn();
@@ -155,31 +163,41 @@
 
     @Override
     public boolean onSwitchToggled(boolean isChecked) {
-        if (isChecked) {
+        if (isChecked && !isTethering()) {
             startTether();
-        } else {
+        }
+
+        if (!isChecked && isTethering()) {
             stopTether();
         }
         return true;
     }
 
-    @VisibleForTesting
-    void stopTether() {
+    private void stopTether() {
 
         // Wi-Fi tether is selected by default.
         if (mSharedPreferences.getBoolean(WIFI_TETHER_KEY, true)) {
-            mConnectivityManager.stopTethering(TETHERING_WIFI);
+            stopTethering(TETHERING_WIFI);
         }
 
         if (mSharedPreferences.getBoolean(USB_TETHER_KEY, false)) {
-            mConnectivityManager.stopTethering(TETHERING_USB);
+            stopTethering(TETHERING_USB);
         }
 
         if (mSharedPreferences.getBoolean(BLUETOOTH_TETHER_KEY, false)) {
-            mConnectivityManager.stopTethering(TETHERING_BLUETOOTH);
+            stopTethering(TETHERING_BLUETOOTH);
         }
     }
 
+    /**
+     * Use this method to stop a single choice of tethering.
+     *
+     * @param choice The choice of tethering to stop.
+     */
+    public void stopTethering(int choice) {
+        mConnectivityManager.stopTethering(choice);
+    }
+
     @VisibleForTesting
     void startTether() {
 
@@ -197,8 +215,16 @@
         }
     }
 
-    @VisibleForTesting
-    void startTethering(int choice) {
+    /**
+     * Use this method to start a single choice of tethering.
+     * For bluetooth tethering, it will first turn on bluetooth if bluetooth is off.
+     * For Wi-Fi tethering, it will be no-op if Wi-Fi tethering already active.
+     *
+     * @param choice The choice of tethering to start.
+     */
+    public void startTethering(int choice) {
+        mSwitchWidgetController.setEnabled(false);
+
         if (choice == TETHERING_WIFI && mWifiManager.isWifiApEnabled()) {
             if (DEBUG) {
                 Log.d(TAG, "Wifi tether already active!");
@@ -224,36 +250,67 @@
     private final BroadcastReceiver mTetherChangeReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
+            final String action = intent.getAction();
+            ArrayList<String> active = null;
+            boolean shouldUpdateState = false;
             if (TextUtils.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED, action)) {
-                ArrayList<String> active = intent.getStringArrayListExtra(
-                        ConnectivityManager.EXTRA_ACTIVE_TETHER);
-                mSwitchWidgetController.setChecked(
-                        isTethering(active.toArray(new String[active.size()])));
+                active = intent.getStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER);
+                shouldUpdateState = true;
+            } else if (TextUtils.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION, action)) {
+                shouldUpdateState = handleWifiApStateChanged(intent.getIntExtra(
+                        WifiManager.EXTRA_WIFI_AP_STATE, WifiManager.WIFI_AP_STATE_FAILED));
             } else if (TextUtils.equals(BluetoothAdapter.ACTION_STATE_CHANGED, action)) {
-                switch (intent
-                        .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
-                    case BluetoothAdapter.STATE_ON:
-                        if (mBluetoothEnableForTether) {
-                            startTethering(TETHERING_BLUETOOTH);
-                        }
-                        // Fall through.
-                    case BluetoothAdapter.STATE_OFF:
-                        // Fall through.
-                    case BluetoothAdapter.ERROR:
-                        mBluetoothEnableForTether = false;
-                        break;
-                    default:
-                        // ignore transition states
+                shouldUpdateState = handleBluetoothStateChanged(intent
+                        .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR));
+            }
+
+            if (shouldUpdateState) {
+                if (active != null) {
+                    updateState(active.toArray(new String[0]));
+                } else {
+                    updateState();
                 }
             }
         }
     };
 
+    private boolean handleBluetoothStateChanged(int state) {
+        switch (state) {
+            case BluetoothAdapter.STATE_ON:
+                if (mBluetoothEnableForTether) {
+                    startTethering(TETHERING_BLUETOOTH);
+                }
+                // Fall through.
+            case BluetoothAdapter.STATE_OFF:
+                // Fall through.
+            case BluetoothAdapter.ERROR:
+                mBluetoothEnableForTether = false;
+                return true;
+            default:
+                // Return false for transition states.
+                return false;
+        }
+    }
+
+    private boolean handleWifiApStateChanged(int state) {
+        switch (state) {
+            case WifiManager.WIFI_AP_STATE_FAILED:
+                Log.e(TAG, "Wifi AP is failed!");
+                // fall through
+            case WifiManager.WIFI_AP_STATE_ENABLED:
+                // fall through
+            case WifiManager.WIFI_AP_STATE_DISABLED:
+                return true;
+            default:
+                // return false for transition state
+                return false;
+        }
+    }
+
     @Override
     public void onDataSaverChanged(boolean isDataSaving) {
         mDataSaverEnabled = isDataSaving;
-        setSwitchWidgetEnabled(!isDataSaving);
+        mSwitchWidgetController.setEnabled(!isDataSaving);
     }
 
     @Override
@@ -291,4 +348,30 @@
             }
         }
     }
+
+    private static final class OnStartTetheringCallback extends
+            ConnectivityManager.OnStartTetheringCallback {
+        final WeakReference<TetherEnabler> mTetherEnabler;
+
+        OnStartTetheringCallback(TetherEnabler enabler) {
+            mTetherEnabler = new WeakReference<>(enabler);
+        }
+
+        @Override
+        public void onTetheringStarted() {
+            update();
+        }
+
+        @Override
+        public void onTetheringFailed() {
+            update();
+        }
+
+        private void update() {
+            TetherEnabler enabler = mTetherEnabler.get();
+            if (enabler != null) {
+                enabler.updateState();
+            }
+        }
+    }
 }
diff --git a/src/com/android/settings/network/UsbTetherPreferenceController.java b/src/com/android/settings/network/UsbTetherPreferenceController.java
index 74e8be8..5722480 100644
--- a/src/com/android/settings/network/UsbTetherPreferenceController.java
+++ b/src/com/android/settings/network/UsbTetherPreferenceController.java
@@ -49,8 +49,7 @@
 
     private static final String TAG = "UsbTetherPrefController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-    @VisibleForTesting
-    static final String PREF_KEY = "enable_usb_tethering";
+    public static final String PREF_KEY = "enable_usb_tethering";
 
     private final ConnectivityManager mCm;
     private boolean mUsbConnected;
diff --git a/src/com/android/settings/panel/PanelContent.java b/src/com/android/settings/panel/PanelContent.java
index 496bac3..de3dc89 100644
--- a/src/com/android/settings/panel/PanelContent.java
+++ b/src/com/android/settings/panel/PanelContent.java
@@ -29,6 +29,20 @@
 public interface PanelContent extends Instrumentable {
 
     /**
+     * @return a icon resource for the title of the Panel.
+     */
+    default int getIcon() {
+        return -1;
+    }
+
+    /**
+     * @return a string for the subtitle of the Panel.
+     */
+    default CharSequence getSubTitle() {
+        return null;
+    }
+
+    /**
      * @return a string for the title of the Panel.
      */
     CharSequence getTitle();
diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java
index 0eda36f..db01a28 100644
--- a/src/com/android/settings/panel/PanelFragment.java
+++ b/src/com/android/settings/panel/PanelFragment.java
@@ -32,6 +32,8 @@
 import android.view.ViewTreeObserver;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import androidx.annotation.NonNull;
@@ -77,15 +79,19 @@
      */
     private static final int DURATION_SLICE_BINDING_TIMEOUT_MS = 250;
 
-    private View mLayoutView;
+    @VisibleForTesting
+    View mLayoutView;
     private TextView mTitleView;
     private Button mSeeMoreButton;
     private Button mDoneButton;
     private RecyclerView mPanelSlices;
-
     private PanelContent mPanel;
     private MetricsFeatureProvider mMetricsProvider;
     private String mPanelClosedKey;
+    private LinearLayout mPanelHeader;
+    private ImageView mTitleIcon;
+    private TextView mHeaderTitle;
+    private TextView mHeaderSubtitle;
 
     private final Map<Uri, LiveData<Slice>> mSliceLiveData = new LinkedHashMap<>();
 
@@ -155,6 +161,10 @@
         mSeeMoreButton = mLayoutView.findViewById(R.id.see_more);
         mDoneButton = mLayoutView.findViewById(R.id.done);
         mTitleView = mLayoutView.findViewById(R.id.panel_title);
+        mPanelHeader = mLayoutView.findViewById(R.id.panel_header);
+        mTitleIcon = mLayoutView.findViewById(R.id.title_icon);
+        mHeaderTitle = mLayoutView.findViewById(R.id.header_title);
+        mHeaderSubtitle = mLayoutView.findViewById(R.id.header_subtitle);
 
         // Make the panel layout gone here, to avoid janky animation when updating from old panel.
         // We will make it visible once the panel is ready to load.
@@ -182,7 +192,16 @@
         // Start loading Slices. When finished, the Panel will animate in.
         loadAllSlices();
 
-        mTitleView.setText(mPanel.getTitle());
+        final int iconRes = mPanel.getIcon();
+        if (iconRes == -1) {
+            mTitleView.setText(mPanel.getTitle());
+        } else {
+            mTitleView.setVisibility(View.GONE);
+            mPanelHeader.setVisibility(View.VISIBLE);
+            mTitleIcon.setImageResource(iconRes);
+            mHeaderTitle.setText(mPanel.getTitle());
+            mHeaderSubtitle.setText(mPanel.getSubTitle());
+        }
         mSeeMoreButton.setOnClickListener(getSeeMoreListener());
         mDoneButton.setOnClickListener(getCloseListener());
 
diff --git a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
index 9dcfa89..a2d55dc 100644
--- a/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
+++ b/tests/robotests/src/com/android/settings/network/TetherEnablerTest.java
@@ -109,8 +109,10 @@
     @Test
     public void startTether_fail_resetSwitchBar() {
         when(mNetworkPolicyManager.getRestrictBackground()).thenReturn(false);
-
+        mEnabler.onStart();
         mEnabler.startTether();
+
+        when(mConnectivityManager.getTetheredIfaces()).thenReturn(new String[0]);
         mEnabler.mOnStartTetheringCallback.onTetheringFailed();
 
         assertThat(mSwitchBar.isChecked()).isFalse();
diff --git a/tests/robotests/src/com/android/settings/panel/FakePanelContent.java b/tests/robotests/src/com/android/settings/panel/FakePanelContent.java
index 8f54115..3b4d2c4 100644
--- a/tests/robotests/src/com/android/settings/panel/FakePanelContent.java
+++ b/tests/robotests/src/com/android/settings/panel/FakePanelContent.java
@@ -40,6 +40,27 @@
 
     public static final Intent INTENT = new Intent();
 
+    private CharSequence mSubTitle;
+    private int mIconRes = -1;
+
+    @Override
+    public int getIcon() {
+        return mIconRes;
+    }
+
+    @Override
+    public CharSequence getSubTitle() {
+        return mSubTitle;
+    }
+
+    public void setIcon(int iconRes) {
+        mIconRes = iconRes;
+    }
+
+    public void setSubTitle(CharSequence subTitle) {
+        mSubTitle = subTitle;
+    }
+
     @Override
     public CharSequence getTitle() {
         return TITLE;
diff --git a/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java b/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
index cbeff97..ee4131e 100644
--- a/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/panel/PanelFragmentTest.java
@@ -31,6 +31,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.LinearLayout;
+import android.widget.TextView;
 
 import com.android.settings.R;
 import com.android.settings.testutils.FakeFeatureFactory;
@@ -41,10 +42,15 @@
 import org.robolectric.Robolectric;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
+import org.robolectric.android.controller.ActivityController;
+
+import java.util.Objects;
 
 @RunWith(RobolectricTestRunner.class)
 public class PanelFragmentTest {
 
+    private static final String SUBTITLE = "subtitle";
+
     private Context mContext;
     private PanelFragment mPanelFragment;
     private FakeSettingsPanelActivity mActivity;
@@ -141,4 +147,38 @@
                 0
         );
     }
+
+    @Test
+    public void supportIcon_displayIconHeaderLayout() {
+        mFakePanelContent.setIcon(R.drawable.ic_android);
+        mFakePanelContent.setSubTitle(SUBTITLE);
+        final ActivityController<FakeSettingsPanelActivity> activityController =
+                Robolectric.buildActivity(FakeSettingsPanelActivity.class);
+        activityController.setup();
+        final PanelFragment panelFragment = (PanelFragment)
+                Objects.requireNonNull(activityController
+                        .get()
+                        .getSupportFragmentManager()
+                        .findFragmentById(R.id.main_content));
+        final View titleView = panelFragment.mLayoutView.findViewById(R.id.panel_title);
+        final LinearLayout panelHeader = panelFragment.mLayoutView.findViewById(R.id.panel_header);
+        final TextView headerTitle = panelFragment.mLayoutView.findViewById(R.id.header_title);
+        final TextView headerSubtitle = panelFragment.mLayoutView.findViewById(
+                R.id.header_subtitle);
+        // Check visibility
+        assertThat(panelHeader.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(titleView.getVisibility()).isEqualTo(View.GONE);
+        // Check content
+        assertThat(headerTitle.getText()).isEqualTo(FakePanelContent.TITLE);
+        assertThat(headerSubtitle.getText()).isEqualTo(SUBTITLE);
+    }
+
+    @Test
+    public void notSupportIcon_displayDefaultHeaderLayout() {
+        final View titleView = mPanelFragment.mLayoutView.findViewById(R.id.panel_title);
+        final View panelHeader = mPanelFragment.mLayoutView.findViewById(R.id.panel_header);
+
+        assertThat(panelHeader.getVisibility()).isEqualTo(View.GONE);
+        assertThat(titleView.getVisibility()).isEqualTo(View.VISIBLE);
+    }
 }
\ No newline at end of file