diff --git a/res/layout/trusted_credentials.xml b/res/layout/trusted_credentials.xml
index 31f5f40..3663a79 100644
--- a/res/layout/trusted_credentials.xml
+++ b/res/layout/trusted_credentials.xml
@@ -13,78 +13,26 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<TabHost
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
+    <ProgressBar
+        android:id="@+id/progress"
+        style="?android:attr/progressBarStyleHorizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+        android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+        android:visibility="gone"/>
+
     <LinearLayout
+        android:id="@+id/content"
         android:orientation="vertical"
-        android:layout_width="fill_parent"
-        android:layout_height="fill_parent">
-
-        <TabWidget
-            android:id="@android:id/tabs"
-            android:layout_width="fill_parent"
-            android:layout_height="wrap_content" />
-
-        <FrameLayout
-            android:id="@android:id/tabcontent"
-            android:layout_width="fill_parent"
-            android:layout_height="fill_parent">
-
-            <FrameLayout
-                android:id="@+id/system_tab"
-                android:layout_width="fill_parent"
-                android:layout_height="fill_parent">
-
-                <ProgressBar
-                    android:id="@+id/system_progress"
-                    style="?android:attr/progressBarStyleHorizontal"
-                    android:layout_width="fill_parent"
-                    android:layout_height="wrap_content"
-                    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-                    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-                    android:visibility="gone" />
-
-                <LinearLayout
-                    android:id="@+id/system_content"
-                    android:orientation="vertical"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:visibility="gone"
-                    android:animateLayoutChanges="true">
-                </LinearLayout>
-
-            </FrameLayout>
-
-            <FrameLayout
-                android:id="@+id/user_tab"
-                android:layout_width="fill_parent"
-                android:layout_height="fill_parent">
-
-                <ProgressBar
-                    android:id="@+id/user_progress"
-                    style="?android:attr/progressBarStyleLarge"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-                    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-                    android:visibility="gone" />
-
-                <LinearLayout
-                    android:id="@+id/user_content"
-                    android:orientation="vertical"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:visibility="gone"
-                    android:animateLayoutChanges="true">
-                </LinearLayout>
-
-            </FrameLayout>
-
-        </FrameLayout>
-
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="gone">
     </LinearLayout>
 
-</TabHost>
+</FrameLayout>
\ No newline at end of file
diff --git a/src/com/android/settings/TrustedCredentialsDialogBuilder.java b/src/com/android/settings/TrustedCredentialsDialogBuilder.java
index 806da92..0dc8c25 100644
--- a/src/com/android/settings/TrustedCredentialsDialogBuilder.java
+++ b/src/com/android/settings/TrustedCredentialsDialogBuilder.java
@@ -34,7 +34,7 @@
 import androidx.appcompat.app.AlertDialog;
 
 import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.TrustedCredentialsSettings.CertHolder;
+import com.android.settings.TrustedCredentialsFragment.CertHolder;
 import com.android.settingslib.RestrictedLockUtils;
 
 import java.security.cert.X509Certificate;
diff --git a/src/com/android/settings/TrustedCredentialsFragment.java b/src/com/android/settings/TrustedCredentialsFragment.java
new file mode 100644
index 0000000..ca565a4
--- /dev/null
+++ b/src/com/android/settings/TrustedCredentialsFragment.java
@@ -0,0 +1,1030 @@
+/*
+ * Copyright (C) 2022 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.settings;
+
+import static android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_CATEGORY_HEADER;
+import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_CATEGORY_HEADER;
+import static android.widget.LinearLayout.LayoutParams.MATCH_PARENT;
+import static android.widget.LinearLayout.LayoutParams.WRAP_CONTENT;
+
+import android.annotation.UiThread;
+import android.app.Activity;
+import android.app.KeyguardManager;
+import android.app.admin.DevicePolicyManager;
+import android.app.settings.SettingsEnums;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.content.res.TypedArray;
+import android.database.DataSetObserver;
+import android.graphics.drawable.Drawable;
+import android.net.http.SslCertificate;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.security.IKeyChainService;
+import android.security.KeyChain;
+import android.security.KeyChain.KeyChainConnection;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.BaseExpandableListAdapter;
+import android.widget.ExpandableListView;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.ProgressBar;
+import android.widget.Switch;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.UnlaunchableAppActivity;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.settings.TrustedCredentialsSettings.Tab;
+import com.android.settings.core.InstrumentedFragment;
+
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.function.IntConsumer;
+
+/**
+ * Fragment to display trusted credentials settings for one tab.
+ */
+public class TrustedCredentialsFragment extends InstrumentedFragment
+        implements TrustedCredentialsDialogBuilder.DelegateInterface {
+
+    public static final String ARG_POSITION = "tab";
+    public static final String ARG_SHOW_NEW_FOR_USER = "ARG_SHOW_NEW_FOR_USER";
+
+    private static final String TAG = "TrustedCredentialsFragment";
+
+    private DevicePolicyManager mDevicePolicyManager;
+    private UserManager mUserManager;
+    private KeyguardManager mKeyguardManager;
+    private int mTrustAllCaUserId;
+
+    private static final String SAVED_CONFIRMED_CREDENTIAL_USERS = "ConfirmedCredentialUsers";
+    private static final String SAVED_CONFIRMING_CREDENTIAL_USER = "ConfirmingCredentialUser";
+    private static final int REQUEST_CONFIRM_CREDENTIALS = 1;
+
+    private GroupAdapter mGroupAdapter;
+    private AliasOperation mAliasOperation;
+    private ArraySet<Integer> mConfirmedCredentialUsers;
+    private int mConfirmingCredentialUser;
+    private IntConsumer mConfirmingCredentialListener;
+    private final Set<AdapterData.AliasLoader> mAliasLoaders = new ArraySet<>(2);
+    @GuardedBy("mKeyChainConnectionByProfileId")
+    private final SparseArray<KeyChainConnection>
+            mKeyChainConnectionByProfileId = new SparseArray<>();
+    private ViewGroup mFragmentView;
+
+    private final BroadcastReceiver mWorkProfileChangedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action)
+                    || Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action)
+                    || Intent.ACTION_MANAGED_PROFILE_UNLOCKED.equals(action)) {
+                mGroupAdapter.load();
+            }
+        }
+    };
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Activity activity = getActivity();
+        mDevicePolicyManager = activity.getSystemService(DevicePolicyManager.class);
+        mUserManager = activity.getSystemService(UserManager.class);
+        mKeyguardManager = activity.getSystemService(KeyguardManager.class);
+        mTrustAllCaUserId = activity.getIntent().getIntExtra(ARG_SHOW_NEW_FOR_USER,
+                UserHandle.USER_NULL);
+        mConfirmedCredentialUsers = new ArraySet<>(2);
+        mConfirmingCredentialUser = UserHandle.USER_NULL;
+        if (savedInstanceState != null) {
+            mConfirmingCredentialUser = savedInstanceState.getInt(SAVED_CONFIRMING_CREDENTIAL_USER,
+                    UserHandle.USER_NULL);
+            ArrayList<Integer> users = savedInstanceState.getIntegerArrayList(
+                    SAVED_CONFIRMED_CREDENTIAL_USERS);
+            if (users != null) {
+                mConfirmedCredentialUsers.addAll(users);
+            }
+        }
+
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
+        filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
+        filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
+        activity.registerReceiver(mWorkProfileChangedReceiver, filter);
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putIntegerArrayList(SAVED_CONFIRMED_CREDENTIAL_USERS, new ArrayList<>(
+                mConfirmedCredentialUsers));
+        outState.putInt(SAVED_CONFIRMING_CREDENTIAL_USER, mConfirmingCredentialUser);
+        mGroupAdapter.saveState(outState);
+    }
+
+    @Override
+    public View onCreateView(
+            LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
+        mFragmentView = (ViewGroup) inflater.inflate(R.layout.trusted_credentials, parent, false);
+
+        ViewGroup contentView = mFragmentView.findViewById(R.id.content);
+
+        mGroupAdapter = new GroupAdapter(
+                requireArguments().getInt(ARG_POSITION) == 0 ? Tab.SYSTEM : Tab.USER);
+        int profilesSize = mGroupAdapter.getGroupCount();
+        for (int i = 0; i < profilesSize; i++) {
+            Bundle childState = savedInstanceState == null ? null
+                    : savedInstanceState.getBundle(mGroupAdapter.getKey(i));
+            createChildView(inflater, contentView, childState, i);
+        }
+        return mFragmentView;
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        return SettingsEnums.TRUSTED_CREDENTIALS;
+    }
+
+    private void createChildView(
+            LayoutInflater inflater, ViewGroup parent, Bundle childState, int i) {
+        boolean isWork = mGroupAdapter.getUserInfoByGroup(i).isManagedProfile();
+        ChildAdapter adapter = mGroupAdapter.createChildAdapter(i);
+
+        LinearLayout containerView = (LinearLayout) inflater.inflate(
+                R.layout.trusted_credential_list_container, parent, false);
+        adapter.setContainerView(containerView, childState);
+
+        int profilesSize = mGroupAdapter.getGroupCount();
+        adapter.showHeader(profilesSize > 1);
+        adapter.showDivider(isWork);
+        adapter.setExpandIfAvailable(profilesSize <= 2 || !isWork, childState);
+        if (isWork) {
+            parent.addView(containerView);
+        } else {
+            parent.addView(containerView, 0);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        mFragmentView.requestLayout();
+    }
+
+    @Override
+    public void onDestroy() {
+        getActivity().unregisterReceiver(mWorkProfileChangedReceiver);
+        for (AdapterData.AliasLoader aliasLoader : mAliasLoaders) {
+            aliasLoader.cancel(true);
+        }
+        mAliasLoaders.clear();
+        if (mAliasOperation != null) {
+            mAliasOperation.cancel(true);
+            mAliasOperation = null;
+        }
+        closeKeyChainConnections();
+        super.onDestroy();
+    }
+
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == REQUEST_CONFIRM_CREDENTIALS) {
+            int userId = mConfirmingCredentialUser;
+            IntConsumer listener = mConfirmingCredentialListener;
+            // reset them before calling the listener because the listener may call back to start
+            // activity again. (though it should never happen.)
+            mConfirmingCredentialUser = UserHandle.USER_NULL;
+            mConfirmingCredentialListener = null;
+            if (resultCode == Activity.RESULT_OK) {
+                mConfirmedCredentialUsers.add(userId);
+                if (listener != null) {
+                    listener.accept(userId);
+                }
+            }
+        }
+    }
+
+    private void closeKeyChainConnections() {
+        synchronized (mKeyChainConnectionByProfileId) {
+            int n = mKeyChainConnectionByProfileId.size();
+            for (int i = 0; i < n; ++i) {
+                mKeyChainConnectionByProfileId.valueAt(i).close();
+            }
+            mKeyChainConnectionByProfileId.clear();
+        }
+    }
+
+    /**
+     * Start work challenge activity.
+     *
+     * @return true if screenlock exists
+     */
+    private boolean startConfirmCredential(int userId) {
+        Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null, userId);
+        if (newIntent == null) {
+            return false;
+        }
+        mConfirmingCredentialUser = userId;
+        startActivityForResult(newIntent, REQUEST_CONFIRM_CREDENTIALS);
+        return true;
+    }
+
+    /**
+     * Adapter for expandable list view of certificates. Groups in the view correspond to profiles
+     * whereas children correspond to certificates.
+     */
+    private class GroupAdapter extends BaseExpandableListAdapter implements
+            ExpandableListView.OnGroupClickListener, ExpandableListView.OnChildClickListener {
+        private final AdapterData mData;
+        private final ArrayList<ChildAdapter> mChildAdapters = new ArrayList<>();
+
+        private GroupAdapter(Tab tab) {
+            mData = new AdapterData(tab, this);
+            load();
+        }
+
+        @Override
+        public int getGroupCount() {
+            return mData.mCertHoldersByUserId.size();
+        }
+
+        @Override
+        public int getChildrenCount(int groupPosition) {
+            List<CertHolder> certHolders = mData.mCertHoldersByUserId.valueAt(groupPosition);
+            if (certHolders != null) {
+                return certHolders.size();
+            }
+            return 0;
+        }
+
+        @Override
+        public UserHandle getGroup(int groupPosition) {
+            return new UserHandle(mData.mCertHoldersByUserId.keyAt(groupPosition));
+        }
+
+        @Override
+        public CertHolder getChild(int groupPosition, int childPosition) {
+            return mData.mCertHoldersByUserId.get(getUserIdByGroup(groupPosition)).get(
+                    childPosition);
+        }
+
+        @Override
+        public long getGroupId(int groupPosition) {
+            return getUserIdByGroup(groupPosition);
+        }
+
+        private int getUserIdByGroup(int groupPosition) {
+            return mData.mCertHoldersByUserId.keyAt(groupPosition);
+        }
+
+        public UserInfo getUserInfoByGroup(int groupPosition) {
+            return mUserManager.getUserInfo(getUserIdByGroup(groupPosition));
+        }
+
+        @Override
+        public long getChildId(int groupPosition, int childPosition) {
+            return childPosition;
+        }
+
+        @Override
+        public boolean hasStableIds() {
+            return false;
+        }
+
+        @Override
+        public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
+                ViewGroup parent) {
+            if (convertView == null) {
+                LayoutInflater inflater = (LayoutInflater) getActivity()
+                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+                convertView = Utils.inflateCategoryHeader(inflater, parent);
+            }
+
+            TextView title = convertView.findViewById(android.R.id.title);
+            if (getUserInfoByGroup(groupPosition).isManagedProfile()) {
+                title.setText(mDevicePolicyManager.getResources().getString(WORK_CATEGORY_HEADER,
+                        () -> getString(R.string.category_work)));
+            } else {
+                title.setText(mDevicePolicyManager.getResources().getString(
+                        PERSONAL_CATEGORY_HEADER,
+                        () -> getString(R.string.category_personal)));
+
+            }
+            title.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
+
+            return convertView;
+        }
+
+        @Override
+        public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
+                View convertView, ViewGroup parent) {
+            return getViewForCertificate(getChild(groupPosition, childPosition), mData.mTab,
+                    convertView, parent);
+        }
+
+        @Override
+        public boolean isChildSelectable(int groupPosition, int childPosition) {
+            return true;
+        }
+
+        @Override
+        public boolean onChildClick(ExpandableListView expandableListView, View view,
+                int groupPosition, int childPosition, long id) {
+            showCertDialog(getChild(groupPosition, childPosition));
+            return true;
+        }
+
+        @Override
+        public boolean onGroupClick(ExpandableListView expandableListView, View view,
+                int groupPosition, long id) {
+            return !checkGroupExpandableAndStartWarningActivity(groupPosition);
+        }
+
+        public void load() {
+            mData.new AliasLoader().execute();
+        }
+
+        public void remove(CertHolder certHolder) {
+            mData.remove(certHolder);
+        }
+
+        ChildAdapter createChildAdapter(int groupPosition) {
+            ChildAdapter childAdapter = new ChildAdapter(this, groupPosition);
+            mChildAdapters.add(childAdapter);
+            return childAdapter;
+        }
+
+        public boolean checkGroupExpandableAndStartWarningActivity(int groupPosition) {
+            return checkGroupExpandableAndStartWarningActivity(groupPosition, true);
+        }
+
+        public boolean checkGroupExpandableAndStartWarningActivity(int groupPosition,
+                boolean startActivity) {
+            UserHandle groupUser = getGroup(groupPosition);
+            int groupUserId = groupUser.getIdentifier();
+            if (mUserManager.isQuietModeEnabled(groupUser)) {
+                if (startActivity) {
+                    Intent intent =
+                            UnlaunchableAppActivity.createInQuietModeDialogIntent(groupUserId);
+                    getActivity().startActivity(intent);
+                }
+                return false;
+            } else if (!mUserManager.isUserUnlocked(groupUser)) {
+                LockPatternUtils lockPatternUtils = new LockPatternUtils(getActivity());
+                if (lockPatternUtils.isSeparateProfileChallengeEnabled(groupUserId)) {
+                    if (startActivity) {
+                        startConfirmCredential(groupUserId);
+                    }
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private View getViewForCertificate(CertHolder certHolder, Tab mTab, View convertView,
+                ViewGroup parent) {
+            ViewHolder holder;
+            if (convertView == null) {
+                holder = new ViewHolder();
+                LayoutInflater inflater = LayoutInflater.from(getActivity());
+                convertView = inflater.inflate(R.layout.trusted_credential, parent, false);
+                convertView.setTag(holder);
+                holder.mSubjectPrimaryView =
+                        convertView.findViewById(R.id.trusted_credential_subject_primary);
+                holder.mSubjectSecondaryView =
+                        convertView.findViewById(R.id.trusted_credential_subject_secondary);
+                holder.mSwitch = convertView.findViewById(R.id.trusted_credential_status);
+                holder.mSwitch.setOnClickListener(view -> {
+                    removeOrInstallCert((CertHolder) view.getTag());
+                });
+            } else {
+                holder = (ViewHolder) convertView.getTag();
+            }
+            holder.mSubjectPrimaryView.setText(certHolder.mSubjectPrimary);
+            holder.mSubjectSecondaryView.setText(certHolder.mSubjectSecondary);
+            if (mTab.mSwitch) {
+                holder.mSwitch.setChecked(!certHolder.mDeleted);
+                holder.mSwitch.setEnabled(!mUserManager.hasUserRestriction(
+                        UserManager.DISALLOW_CONFIG_CREDENTIALS,
+                        new UserHandle(certHolder.mProfileId)));
+                holder.mSwitch.setVisibility(View.VISIBLE);
+                holder.mSwitch.setTag(certHolder);
+            }
+            return convertView;
+        }
+
+        private void saveState(Bundle outState) {
+            for (int groupPosition = 0, mChildAdaptersSize = mChildAdapters.size();
+                    groupPosition < mChildAdaptersSize; groupPosition++) {
+                ChildAdapter childAdapter = mChildAdapters.get(groupPosition);
+                outState.putBundle(getKey(groupPosition), childAdapter.saveState());
+            }
+        }
+
+        @NonNull
+        private String getKey(int groupPosition) {
+            return "Group" + getUserIdByGroup(groupPosition);
+        }
+
+        private class ViewHolder {
+            private TextView mSubjectPrimaryView;
+            private TextView mSubjectSecondaryView;
+            private Switch mSwitch;
+        }
+    }
+
+    private class ChildAdapter extends BaseAdapter implements View.OnClickListener,
+            AdapterView.OnItemClickListener {
+        private static final String KEY_CONTAINER = "Container";
+        private static final String KEY_IS_LIST_EXPANDED = "IsListExpanded";
+        private final int[] mGroupExpandedStateSet = {com.android.internal.R.attr.state_expanded};
+        private final int[] mEmptyStateSet = {};
+        private final LinearLayout.LayoutParams mHideContainerLayoutParams =
+                new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT, 0f);
+        private final LinearLayout.LayoutParams mHideListLayoutParams =
+                new LinearLayout.LayoutParams(MATCH_PARENT, 0);
+        private final LinearLayout.LayoutParams mShowLayoutParams = new LinearLayout.LayoutParams(
+                LinearLayout.LayoutParams.MATCH_PARENT, MATCH_PARENT, 1f);
+        private final GroupAdapter mParent;
+        private final int mGroupPosition;
+        /*
+         * This class doesn't hold the actual data. Events should notify parent.
+         * When notifying DataSet events in this class, events should be forwarded to mParent.
+         * i.e. this.notifyDataSetChanged -> mParent.notifyDataSetChanged -> mObserver.onChanged
+         * -> outsideObservers.onChanged() (e.g. ListView)
+         */
+        private final DataSetObserver mObserver = new DataSetObserver() {
+            @Override
+            public void onChanged() {
+                super.onChanged();
+                TrustedCredentialsFragment.ChildAdapter.super.notifyDataSetChanged();
+            }
+
+            @Override
+            public void onInvalidated() {
+                super.onInvalidated();
+                TrustedCredentialsFragment.ChildAdapter.super.notifyDataSetInvalidated();
+            }
+        };
+
+        private boolean mIsListExpanded = true;
+        private LinearLayout mContainerView;
+        private ViewGroup mHeaderView;
+        private ListView mListView;
+        private ImageView mIndicatorView;
+
+        private ChildAdapter(GroupAdapter parent, int groupPosition) {
+            mParent = parent;
+            mGroupPosition = groupPosition;
+            mParent.registerDataSetObserver(mObserver);
+        }
+
+        @Override
+        public int getCount() {
+            return mParent.getChildrenCount(mGroupPosition);
+        }
+
+        @Override
+        public CertHolder getItem(int position) {
+            return mParent.getChild(mGroupPosition, position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return mParent.getChildId(mGroupPosition, position);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            return mParent.getChildView(mGroupPosition, position, false, convertView, parent);
+        }
+
+        // DataSet events
+        @Override
+        public void notifyDataSetChanged() {
+            // Don't call super as the parent will propagate this event back later in mObserver
+            mParent.notifyDataSetChanged();
+        }
+
+        @Override
+        public void notifyDataSetInvalidated() {
+            // Don't call super as the parent will propagate this event back later in mObserver
+            mParent.notifyDataSetInvalidated();
+        }
+
+        // View related codes
+        @Override
+        public void onClick(View view) {
+            mIsListExpanded = checkGroupExpandableAndStartWarningActivity() && !mIsListExpanded;
+            refreshViews();
+        }
+
+        @Override
+        public void onItemClick(AdapterView<?> adapterView, View view, int pos, long id) {
+            showCertDialog(getItem(pos));
+        }
+
+        public void setContainerView(LinearLayout containerView, Bundle savedState) {
+            mContainerView = containerView;
+            // Handle manually because multiple groups with same id elements.
+            mContainerView.setSaveFromParentEnabled(false);
+
+            mListView = mContainerView.findViewById(R.id.cert_list);
+            mListView.setAdapter(this);
+            mListView.setOnItemClickListener(this);
+            mListView.setItemsCanFocus(true);
+
+            mHeaderView = mContainerView.findViewById(R.id.header_view);
+            mHeaderView.setOnClickListener(this);
+
+            mIndicatorView = mHeaderView.findViewById(R.id.group_indicator);
+            mIndicatorView.setImageDrawable(getGroupIndicator());
+
+            FrameLayout headerContentContainer =
+                    mHeaderView.findViewById(R.id.header_content_container);
+            headerContentContainer.addView(
+                    mParent.getGroupView(mGroupPosition, true /* parent ignores it */, null,
+                            headerContentContainer));
+
+            if (savedState != null) {
+                SparseArray<Parcelable> containerStates =
+                        savedState.getSparseParcelableArray(KEY_CONTAINER, Parcelable.class);
+                if (containerStates != null) {
+                    mContainerView.restoreHierarchyState(containerStates);
+                }
+            }
+        }
+
+        public void showHeader(boolean showHeader) {
+            mHeaderView.setVisibility(showHeader ? View.VISIBLE : View.GONE);
+        }
+
+        public void showDivider(boolean showDivider) {
+            View dividerView = mHeaderView.findViewById(R.id.header_divider);
+            dividerView.setVisibility(showDivider ? View.VISIBLE : View.GONE);
+        }
+
+        public void setExpandIfAvailable(boolean expanded, Bundle savedState) {
+            if (savedState != null) {
+                expanded = savedState.getBoolean(KEY_IS_LIST_EXPANDED);
+            }
+            mIsListExpanded = expanded && mParent.checkGroupExpandableAndStartWarningActivity(
+                    mGroupPosition, false /* startActivity */);
+            refreshViews();
+        }
+
+        private boolean checkGroupExpandableAndStartWarningActivity() {
+            return mParent.checkGroupExpandableAndStartWarningActivity(mGroupPosition);
+        }
+
+        private void refreshViews() {
+            mIndicatorView.setImageState(mIsListExpanded ? mGroupExpandedStateSet
+                    : mEmptyStateSet, false);
+            mListView.setLayoutParams(mIsListExpanded ? mShowLayoutParams
+                    : mHideListLayoutParams);
+            mContainerView.setLayoutParams(mIsListExpanded ? mShowLayoutParams
+                    : mHideContainerLayoutParams);
+        }
+
+        // Get group indicator from styles of ExpandableListView
+        private Drawable getGroupIndicator() {
+            TypedArray a = getActivity().obtainStyledAttributes(null,
+                    com.android.internal.R.styleable.ExpandableListView,
+                    com.android.internal.R.attr.expandableListViewStyle, 0);
+            Drawable groupIndicator = a.getDrawable(
+                    com.android.internal.R.styleable.ExpandableListView_groupIndicator);
+            a.recycle();
+            return groupIndicator;
+        }
+
+        private Bundle saveState() {
+            Bundle bundle = new Bundle();
+            SparseArray<Parcelable> states = new SparseArray<>();
+            mContainerView.saveHierarchyState(states);
+            bundle.putSparseParcelableArray(KEY_CONTAINER, states);
+            bundle.putBoolean(KEY_IS_LIST_EXPANDED, mIsListExpanded);
+            return bundle;
+        }
+    }
+
+    private class AdapterData {
+        private final SparseArray<List<CertHolder>> mCertHoldersByUserId =
+                new SparseArray<>();
+        private final Tab mTab;
+        private final GroupAdapter mAdapter;
+
+        private AdapterData(Tab tab, GroupAdapter adapter) {
+            mAdapter = adapter;
+            mTab = tab;
+        }
+
+        private class AliasLoader extends AsyncTask<Void, Integer, SparseArray<List<CertHolder>>> {
+            private ProgressBar mProgressBar;
+            private View mContentView;
+            private Context mContext;
+
+            AliasLoader() {
+                mContext = getActivity();
+                mAliasLoaders.add(this);
+                List<UserHandle> profiles = mUserManager.getUserProfiles();
+                for (UserHandle profile : profiles) {
+                    mCertHoldersByUserId.put(profile.getIdentifier(), new ArrayList<>());
+                }
+            }
+
+            private boolean shouldSkipProfile(UserHandle userHandle) {
+                return mUserManager.isQuietModeEnabled(userHandle)
+                        || !mUserManager.isUserUnlocked(userHandle.getIdentifier());
+            }
+
+            @Override
+            protected void onPreExecute() {
+                mProgressBar = mFragmentView.findViewById(R.id.progress);
+                mContentView = mFragmentView.findViewById(R.id.content);
+                mProgressBar.setVisibility(View.VISIBLE);
+                mContentView.setVisibility(View.GONE);
+            }
+
+            @Override
+            protected SparseArray<List<CertHolder>> doInBackground(Void... params) {
+                SparseArray<List<CertHolder>> certHoldersByProfile =
+                        new SparseArray<>();
+                try {
+                    synchronized (mKeyChainConnectionByProfileId) {
+                        List<UserHandle> profiles = mUserManager.getUserProfiles();
+                        // First we get all aliases for all profiles in order to show progress
+                        // correctly. Otherwise this could all be in a single loop.
+                        SparseArray<List<String>> aliasesByProfileId =
+                                new SparseArray<>(profiles.size());
+                        int max = 0;
+                        int progress = 0;
+                        for (UserHandle profile : profiles) {
+                            int profileId = profile.getIdentifier();
+                            if (shouldSkipProfile(profile)) {
+                                continue;
+                            }
+                            KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext,
+                                    profile);
+                            // Saving the connection for later use on the certificate dialog.
+                            mKeyChainConnectionByProfileId.put(profileId, keyChainConnection);
+                            IKeyChainService service = keyChainConnection.getService();
+                            List<String> aliases = mTab.getAliases(service);
+                            if (isCancelled()) {
+                                return new SparseArray<>();
+                            }
+                            max += aliases.size();
+                            aliasesByProfileId.put(profileId, aliases);
+                        }
+                        for (UserHandle profile : profiles) {
+                            int profileId = profile.getIdentifier();
+                            List<String> aliases = aliasesByProfileId.get(profileId);
+                            if (isCancelled()) {
+                                return new SparseArray<>();
+                            }
+                            KeyChainConnection keyChainConnection =
+                                    mKeyChainConnectionByProfileId.get(
+                                            profileId);
+                            if (shouldSkipProfile(profile) || aliases == null
+                                    || keyChainConnection == null) {
+                                certHoldersByProfile.put(profileId, new ArrayList<>(0));
+                                continue;
+                            }
+                            IKeyChainService service = keyChainConnection.getService();
+                            List<CertHolder> certHolders = new ArrayList<>(max);
+                            for (String alias : aliases) {
+                                byte[] encodedCertificate = service.getEncodedCaCertificate(alias,
+                                        true);
+                                X509Certificate cert = KeyChain.toCertificate(encodedCertificate);
+                                certHolders.add(new CertHolder(service, mAdapter,
+                                        mTab, alias, cert, profileId));
+                                publishProgress(++progress, max);
+                            }
+                            Collections.sort(certHolders);
+                            certHoldersByProfile.put(profileId, certHolders);
+                        }
+                        return certHoldersByProfile;
+                    }
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Remote exception while loading aliases.", e);
+                    return new SparseArray<>();
+                } catch (InterruptedException e) {
+                    Log.e(TAG, "InterruptedException while loading aliases.", e);
+                    return new SparseArray<>();
+                }
+            }
+
+            @Override
+            protected void onProgressUpdate(Integer... progressAndMax) {
+                int progress = progressAndMax[0];
+                int max = progressAndMax[1];
+                if (max != mProgressBar.getMax()) {
+                    mProgressBar.setMax(max);
+                }
+                mProgressBar.setProgress(progress);
+            }
+
+            @Override
+            protected void onPostExecute(SparseArray<List<CertHolder>> certHolders) {
+                mCertHoldersByUserId.clear();
+                int n = certHolders.size();
+                for (int i = 0; i < n; ++i) {
+                    mCertHoldersByUserId.put(certHolders.keyAt(i), certHolders.valueAt(i));
+                }
+                mAdapter.notifyDataSetChanged();
+                mProgressBar.setVisibility(View.GONE);
+                mContentView.setVisibility(View.VISIBLE);
+                mProgressBar.setProgress(0);
+                mAliasLoaders.remove(this);
+                showTrustAllCaDialogIfNeeded();
+            }
+
+            private boolean isUserTabAndTrustAllCertMode() {
+                return isTrustAllCaCertModeInProgress() && mTab == Tab.USER;
+            }
+
+            @UiThread
+            private void showTrustAllCaDialogIfNeeded() {
+                if (!isUserTabAndTrustAllCertMode()) {
+                    return;
+                }
+                List<CertHolder> certHolders = mCertHoldersByUserId.get(mTrustAllCaUserId);
+                if (certHolders == null) {
+                    return;
+                }
+
+                List<CertHolder> unapprovedUserCertHolders = new ArrayList<>();
+                DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+                for (CertHolder cert : certHolders) {
+                    if (cert != null && !dpm.isCaCertApproved(cert.mAlias, mTrustAllCaUserId)) {
+                        unapprovedUserCertHolders.add(cert);
+                    }
+                }
+
+                if (unapprovedUserCertHolders.size() == 0) {
+                    Log.w(TAG, "no cert is pending approval for user " + mTrustAllCaUserId);
+                    return;
+                }
+                showTrustAllCaDialog(unapprovedUserCertHolders);
+            }
+        }
+
+        public void remove(CertHolder certHolder) {
+            if (mCertHoldersByUserId != null) {
+                List<CertHolder> certs = mCertHoldersByUserId.get(certHolder.mProfileId);
+                if (certs != null) {
+                    certs.remove(certHolder);
+                }
+            }
+        }
+    }
+
+    /* package */ static class CertHolder implements Comparable<CertHolder> {
+        public int mProfileId;
+        private final IKeyChainService mService;
+        private final GroupAdapter mAdapter;
+        private final Tab mTab;
+        private final String mAlias;
+        private final X509Certificate mX509Cert;
+
+        private final SslCertificate mSslCert;
+        private final String mSubjectPrimary;
+        private final String mSubjectSecondary;
+        private boolean mDeleted;
+
+        private CertHolder(IKeyChainService service,
+                GroupAdapter adapter,
+                Tab tab,
+                String alias,
+                X509Certificate x509Cert,
+                int profileId) {
+            mProfileId = profileId;
+            mService = service;
+            mAdapter = adapter;
+            mTab = tab;
+            mAlias = alias;
+            mX509Cert = x509Cert;
+
+            mSslCert = new SslCertificate(x509Cert);
+
+            String cn = mSslCert.getIssuedTo().getCName();
+            String o = mSslCert.getIssuedTo().getOName();
+            String ou = mSslCert.getIssuedTo().getUName();
+            // if we have a O, use O as primary subject, secondary prefer CN over OU
+            // if we don't have an O, use CN as primary, empty secondary
+            // if we don't have O or CN, use DName as primary, empty secondary
+            if (!o.isEmpty()) {
+                if (!cn.isEmpty()) {
+                    mSubjectPrimary = o;
+                    mSubjectSecondary = cn;
+                } else {
+                    mSubjectPrimary = o;
+                    mSubjectSecondary = ou;
+                }
+            } else {
+                if (!cn.isEmpty()) {
+                    mSubjectPrimary = cn;
+                    mSubjectSecondary = "";
+                } else {
+                    mSubjectPrimary = mSslCert.getIssuedTo().getDName();
+                    mSubjectSecondary = "";
+                }
+            }
+            try {
+                mDeleted = mTab.deleted(mService, mAlias);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Remote exception while checking if alias " + mAlias + " is deleted.",
+                        e);
+                mDeleted = false;
+            }
+        }
+
+        @Override
+        public int compareTo(CertHolder o) {
+            int primary = this.mSubjectPrimary.compareToIgnoreCase(o.mSubjectPrimary);
+            if (primary != 0) {
+                return primary;
+            }
+            return this.mSubjectSecondary.compareToIgnoreCase(o.mSubjectSecondary);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (!(o instanceof CertHolder)) {
+                return false;
+            }
+            CertHolder other = (CertHolder) o;
+            return mAlias.equals(other.mAlias);
+        }
+
+        @Override
+        public int hashCode() {
+            return mAlias.hashCode();
+        }
+
+        public int getUserId() {
+            return mProfileId;
+        }
+
+        public String getAlias() {
+            return mAlias;
+        }
+
+        public boolean isSystemCert() {
+            return mTab == Tab.SYSTEM;
+        }
+
+        public boolean isDeleted() {
+            return mDeleted;
+        }
+    }
+
+
+    private boolean isTrustAllCaCertModeInProgress() {
+        return mTrustAllCaUserId != UserHandle.USER_NULL;
+    }
+
+    private void showTrustAllCaDialog(List<CertHolder> unapprovedCertHolders) {
+        CertHolder[] arr =
+                unapprovedCertHolders.toArray(new CertHolder[unapprovedCertHolders.size()]);
+        new TrustedCredentialsDialogBuilder(getActivity(), this)
+                .setCertHolders(arr)
+                .setOnDismissListener(dialogInterface -> {
+                    // Avoid starting dialog again after Activity restart.
+                    getActivity().getIntent().removeExtra(ARG_SHOW_NEW_FOR_USER);
+                    mTrustAllCaUserId = UserHandle.USER_NULL;
+                })
+                .show();
+    }
+
+    private void showCertDialog(final CertHolder certHolder) {
+        new TrustedCredentialsDialogBuilder(getActivity(), this)
+                .setCertHolder(certHolder)
+                .show();
+    }
+
+    @Override
+    public List<X509Certificate> getX509CertsFromCertHolder(CertHolder certHolder) {
+        List<X509Certificate> certificates = null;
+        try {
+            synchronized (mKeyChainConnectionByProfileId) {
+                KeyChainConnection keyChainConnection = mKeyChainConnectionByProfileId.get(
+                        certHolder.mProfileId);
+                IKeyChainService service = keyChainConnection.getService();
+                List<String> chain = service.getCaCertificateChainAliases(certHolder.mAlias, true);
+                certificates = new ArrayList<>(chain.size());
+                for (String s : chain) {
+                    byte[] encodedCertificate = service.getEncodedCaCertificate(s, true);
+                    X509Certificate certificate = KeyChain.toCertificate(encodedCertificate);
+                    certificates.add(certificate);
+                }
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "RemoteException while retrieving certificate chain for root "
+                    + certHolder.mAlias, ex);
+        }
+        return certificates;
+    }
+
+    @Override
+    public void removeOrInstallCert(CertHolder certHolder) {
+        new AliasOperation(certHolder).execute();
+    }
+
+    @Override
+    public boolean startConfirmCredentialIfNotConfirmed(int userId,
+            IntConsumer onCredentialConfirmedListener) {
+        if (mConfirmedCredentialUsers.contains(userId)) {
+            // Credential has been confirmed. Don't start activity.
+            return false;
+        }
+
+        boolean result = startConfirmCredential(userId);
+        if (result) {
+            mConfirmingCredentialListener = onCredentialConfirmedListener;
+        }
+        return result;
+    }
+
+    private class AliasOperation extends AsyncTask<Void, Void, Boolean> {
+        private final CertHolder mCertHolder;
+
+        private AliasOperation(CertHolder certHolder) {
+            mCertHolder = certHolder;
+            mAliasOperation = this;
+        }
+
+        @Override
+        protected Boolean doInBackground(Void... params) {
+            try {
+                synchronized (mKeyChainConnectionByProfileId) {
+                    KeyChainConnection keyChainConnection = mKeyChainConnectionByProfileId.get(
+                            mCertHolder.mProfileId);
+                    IKeyChainService service = keyChainConnection.getService();
+                    if (mCertHolder.mDeleted) {
+                        byte[] bytes = mCertHolder.mX509Cert.getEncoded();
+                        service.installCaCertificate(bytes);
+                        return true;
+                    } else {
+                        return service.deleteCaCertificate(mCertHolder.mAlias);
+                    }
+                }
+            } catch (CertificateEncodingException | SecurityException | IllegalStateException
+                    | RemoteException e) {
+                Log.w(TAG, "Error while toggling alias " + mCertHolder.mAlias, e);
+                return false;
+            }
+        }
+
+        @Override
+        protected void onPostExecute(Boolean ok) {
+            if (ok) {
+                if (mCertHolder.mTab.mSwitch) {
+                    mCertHolder.mDeleted = !mCertHolder.mDeleted;
+                } else {
+                    mCertHolder.mAdapter.remove(mCertHolder);
+                }
+                mCertHolder.mAdapter.notifyDataSetChanged();
+            } else {
+                // bail, reload to reset to known state
+                mCertHolder.mAdapter.load();
+            }
+            mAliasOperation = null;
+        }
+    }
+}
diff --git a/src/com/android/settings/TrustedCredentialsSettings.java b/src/com/android/settings/TrustedCredentialsSettings.java
index 735cb3b..a88019e 100644
--- a/src/com/android/settings/TrustedCredentialsSettings.java
+++ b/src/com/android/settings/TrustedCredentialsSettings.java
@@ -16,121 +16,114 @@
 
 package com.android.settings;
 
-import static android.app.admin.DevicePolicyResources.Strings.Settings.PERSONAL_CATEGORY_HEADER;
-import static android.app.admin.DevicePolicyResources.Strings.Settings.WORK_CATEGORY_HEADER;
-import static android.widget.LinearLayout.LayoutParams.MATCH_PARENT;
-import static android.widget.LinearLayout.LayoutParams.WRAP_CONTENT;
-
-import android.animation.LayoutTransition;
-import android.annotation.UiThread;
-import android.app.Activity;
-import android.app.KeyguardManager;
-import android.app.admin.DevicePolicyManager;
 import android.app.settings.SettingsEnums;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.UserInfo;
-import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.graphics.drawable.Drawable;
-import android.net.http.SslCertificate;
-import android.os.AsyncTask;
 import android.os.Bundle;
 import android.os.RemoteException;
-import android.os.UserHandle;
-import android.os.UserManager;
 import android.security.IKeyChainService;
-import android.security.KeyChain;
-import android.security.KeyChain.KeyChainConnection;
-import android.util.ArraySet;
-import android.util.Log;
-import android.util.SparseArray;
-import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AdapterView;
-import android.widget.BaseAdapter;
-import android.widget.BaseExpandableListAdapter;
-import android.widget.ExpandableListView;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ListView;
-import android.widget.ProgressBar;
-import android.widget.Switch;
-import android.widget.TabHost;
-import android.widget.TextView;
 
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.app.UnlaunchableAppActivity;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.settings.core.InstrumentedFragment;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.viewpager2.adapter.FragmentStateAdapter;
+import androidx.viewpager2.widget.ViewPager2;
 
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
-import java.util.ArrayList;
-import java.util.Collections;
+import com.android.settings.dashboard.DashboardFragment;
+
+import com.google.android.material.tabs.TabLayout;
+import com.google.android.material.tabs.TabLayoutMediator;
+import com.google.common.collect.ImmutableList;
+
 import java.util.List;
-import java.util.Set;
-import java.util.function.IntConsumer;
 
-public class TrustedCredentialsSettings extends InstrumentedFragment
-        implements TrustedCredentialsDialogBuilder.DelegateInterface {
-
-    public static final String ARG_SHOW_NEW_FOR_USER = "ARG_SHOW_NEW_FOR_USER";
+/**
+ * Main fragment to display trusted credentials settings.
+ */
+public class TrustedCredentialsSettings extends DashboardFragment {
 
     private static final String TAG = "TrustedCredentialsSettings";
 
-    private DevicePolicyManager mDevicePolicyManager;
-    private UserManager mUserManager;
-    private KeyguardManager mKeyguardManager;
-    private int mTrustAllCaUserId;
+    public static final String ARG_SHOW_NEW_FOR_USER = "ARG_SHOW_NEW_FOR_USER";
 
-    private static final String SAVED_CONFIRMED_CREDENTIAL_USERS = "ConfirmedCredentialUsers";
-    private static final String SAVED_CONFIRMING_CREDENTIAL_USER = "ConfirmingCredentialUser";
+    static final ImmutableList<Tab> TABS = ImmutableList.of(Tab.SYSTEM, Tab.USER);
+
     private static final String USER_ACTION = "com.android.settings.TRUSTED_CREDENTIALS_USER";
-    private static final int REQUEST_CONFIRM_CREDENTIALS = 1;
 
     @Override
     public int getMetricsCategory() {
         return SettingsEnums.TRUSTED_CREDENTIALS;
     }
 
-    private enum Tab {
-        SYSTEM("system",
-                R.string.trusted_credentials_system_tab,
-                R.id.system_tab,
-                R.id.system_progress,
-                R.id.system_content,
-                true),
-        USER("user",
-                R.string.trusted_credentials_user_tab,
-                R.id.user_tab,
-                R.id.user_progress,
-                R.id.user_content,
-                false);
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getActivity().setTitle(R.string.trusted_credentials);
+    }
 
-        private final String mTag;
+    @Override
+    protected int getPreferenceScreenResId() {
+        return R.xml.placeholder_preference_screen;
+    }
+
+    @Override
+    protected String getLogTag() {
+        return TAG;
+    }
+
+    @Override
+    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
+        View tabContainer = view.findViewById(R.id.tab_container);
+        tabContainer.setVisibility(View.VISIBLE);
+
+        ViewPager2 viewPager = tabContainer.findViewById(R.id.view_pager);
+        viewPager.setAdapter(new FragmentAdapter(this));
+        viewPager.setUserInputEnabled(false);
+
+        Intent intent = getActivity().getIntent();
+        if (intent != null && USER_ACTION.equals(intent.getAction())) {
+            viewPager.setCurrentItem(TABS.indexOf(Tab.USER), false);
+        }
+
+        TabLayout tabLayout = tabContainer.findViewById(R.id.tabs);
+        new TabLayoutMediator(tabLayout, viewPager, false, false,
+                (tab, position) -> tab.setText(TABS.get(position).mLabel)).attach();
+    }
+
+    private static class FragmentAdapter extends FragmentStateAdapter {
+        FragmentAdapter(Fragment fragment) {
+            super(fragment);
+        }
+
+        @NonNull
+        @Override
+        public Fragment createFragment(int position) {
+            TrustedCredentialsFragment fragment = new TrustedCredentialsFragment();
+            Bundle args = new Bundle();
+            args.putInt(TrustedCredentialsFragment.ARG_POSITION, position);
+            fragment.setArguments(args);
+            return fragment;
+        }
+
+        @Override
+        public int getItemCount() {
+            return TrustedCredentialsSettings.TABS.size();
+        }
+    }
+
+    enum Tab {
+        SYSTEM(R.string.trusted_credentials_system_tab, true),
+        USER(R.string.trusted_credentials_user_tab, false);
+
         private final int mLabel;
-        private final int mView;
-        private final int mProgress;
-        private final int mContentView;
-        private final boolean mSwitch;
+        final boolean mSwitch;
 
-        private Tab(String tag, int label, int view, int progress, int contentView,
-                boolean withSwitch) {
-            mTag = tag;
+        Tab(int label, boolean withSwitch) {
             mLabel = label;
-            mView = view;
-            mProgress = progress;
-            mContentView = contentView;
             mSwitch = withSwitch;
         }
 
-        private List<String> getAliases(IKeyChainService service) throws RemoteException {
+        List<String> getAliases(IKeyChainService service) throws RemoteException {
             switch (this) {
                 case SYSTEM: {
                     return service.getSystemCaAliases().getList();
@@ -140,7 +133,8 @@
             }
             throw new AssertionError();
         }
-        private boolean deleted(IKeyChainService service, String alias) throws RemoteException {
+
+        boolean deleted(IKeyChainService service, String alias) throws RemoteException {
             switch (this) {
                 case SYSTEM:
                     return !service.containsCaAlias(alias);
@@ -150,895 +144,4 @@
             throw new AssertionError();
         }
     }
-
-    private TabHost mTabHost;
-    private ArrayList<GroupAdapter> mGroupAdapters = new ArrayList<>(2);
-    private AliasOperation mAliasOperation;
-    private ArraySet<Integer> mConfirmedCredentialUsers;
-    private int mConfirmingCredentialUser;
-    private IntConsumer mConfirmingCredentialListener;
-    private Set<AdapterData.AliasLoader> mAliasLoaders = new ArraySet<AdapterData.AliasLoader>(2);
-    @GuardedBy("mKeyChainConnectionByProfileId")
-    private final SparseArray<KeyChainConnection>
-            mKeyChainConnectionByProfileId = new SparseArray<KeyChainConnection>();
-
-    private BroadcastReceiver mWorkProfileChangedReceiver = new BroadcastReceiver() {
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE.equals(action) ||
-                    Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE.equals(action) ||
-                    Intent.ACTION_MANAGED_PROFILE_UNLOCKED.equals(action)) {
-                for (GroupAdapter adapter : mGroupAdapters) {
-                    adapter.load();
-                }
-            }
-        }
-
-    };
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        final Activity activity = getActivity();
-        mDevicePolicyManager = activity.getSystemService(DevicePolicyManager.class);
-        mUserManager = (UserManager) activity.getSystemService(Context.USER_SERVICE);
-        mKeyguardManager = (KeyguardManager) activity
-                .getSystemService(Context.KEYGUARD_SERVICE);
-        mTrustAllCaUserId = activity.getIntent().getIntExtra(ARG_SHOW_NEW_FOR_USER,
-                UserHandle.USER_NULL);
-        mConfirmedCredentialUsers = new ArraySet<>(2);
-        mConfirmingCredentialUser = UserHandle.USER_NULL;
-        if (savedInstanceState != null) {
-            mConfirmingCredentialUser = savedInstanceState.getInt(SAVED_CONFIRMING_CREDENTIAL_USER,
-                    UserHandle.USER_NULL);
-            ArrayList<Integer> users = savedInstanceState.getIntegerArrayList(
-                    SAVED_CONFIRMED_CREDENTIAL_USERS);
-            if (users != null) {
-                mConfirmedCredentialUsers.addAll(users);
-            }
-        }
-
-        mConfirmingCredentialListener = null;
-
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
-        filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
-        filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
-        activity.registerReceiver(mWorkProfileChangedReceiver, filter);
-
-        activity.setTitle(R.string.trusted_credentials);
-    }
-
-    @Override
-    public void onSaveInstanceState(Bundle outState) {
-        super.onSaveInstanceState(outState);
-        outState.putIntegerArrayList(SAVED_CONFIRMED_CREDENTIAL_USERS, new ArrayList<>(
-                mConfirmedCredentialUsers));
-        outState.putInt(SAVED_CONFIRMING_CREDENTIAL_USER, mConfirmingCredentialUser);
-    }
-
-    @Override public View onCreateView(
-            LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
-        mTabHost = (TabHost) inflater.inflate(R.layout.trusted_credentials, parent, false);
-        mTabHost.setup();
-        addTab(Tab.SYSTEM);
-        // TODO add Install button on Tab.USER to go to CertInstaller like KeyChainActivity
-        addTab(Tab.USER);
-        if (getActivity().getIntent() != null &&
-                USER_ACTION.equals(getActivity().getIntent().getAction())) {
-            mTabHost.setCurrentTabByTag(Tab.USER.mTag);
-        }
-        return mTabHost;
-    }
-    @Override
-    public void onDestroy() {
-        getActivity().unregisterReceiver(mWorkProfileChangedReceiver);
-        for (AdapterData.AliasLoader aliasLoader : mAliasLoaders) {
-            aliasLoader.cancel(true);
-        }
-        mAliasLoaders.clear();
-        mGroupAdapters.clear();
-        if (mAliasOperation != null) {
-            mAliasOperation.cancel(true);
-            mAliasOperation = null;
-        }
-        closeKeyChainConnections();
-        super.onDestroy();
-    }
-
-    @Override
-    public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        if (requestCode == REQUEST_CONFIRM_CREDENTIALS) {
-            int userId = mConfirmingCredentialUser;
-            IntConsumer listener = mConfirmingCredentialListener;
-            // reset them before calling the listener because the listener may call back to start
-            // activity again. (though it should never happen.)
-            mConfirmingCredentialUser = UserHandle.USER_NULL;
-            mConfirmingCredentialListener = null;
-            if (resultCode == Activity.RESULT_OK) {
-                mConfirmedCredentialUsers.add(userId);
-                if (listener != null) {
-                    listener.accept(userId);
-                }
-            }
-        }
-    }
-
-    private void closeKeyChainConnections() {
-        synchronized (mKeyChainConnectionByProfileId) {
-            final int n = mKeyChainConnectionByProfileId.size();
-            for (int i = 0; i < n; ++i) {
-                mKeyChainConnectionByProfileId.valueAt(i).close();
-            }
-            mKeyChainConnectionByProfileId.clear();
-        }
-    }
-
-    private void addTab(Tab tab) {
-        TabHost.TabSpec systemSpec = mTabHost.newTabSpec(tab.mTag)
-                .setIndicator(getActivity().getString(tab.mLabel))
-                .setContent(tab.mView);
-        mTabHost.addTab(systemSpec);
-
-        final GroupAdapter groupAdapter = new GroupAdapter(tab);
-        mGroupAdapters.add(groupAdapter);
-        final int profilesSize = groupAdapter.getGroupCount();
-
-        // Add a transition for non-visibility events like resizing the pane.
-        final ViewGroup contentView = (ViewGroup) mTabHost.findViewById(tab.mContentView);
-        contentView.getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
-
-        final LayoutInflater inflater = LayoutInflater.from(getActivity());
-        for (int i = 0; i < groupAdapter.getGroupCount(); i++) {
-            final boolean isWork = groupAdapter.getUserInfoByGroup(i).isManagedProfile();
-            final ChildAdapter adapter = groupAdapter.getChildAdapter(i);
-
-            final LinearLayout containerView = (LinearLayout) inflater
-                    .inflate(R.layout.trusted_credential_list_container, contentView, false);
-            adapter.setContainerView(containerView);
-
-            adapter.showHeader(profilesSize > 1);
-            adapter.showDivider(isWork);
-            adapter.setExpandIfAvailable(profilesSize <= 2 ? true : !isWork);
-            if (isWork) {
-                contentView.addView(containerView);
-            } else {
-                contentView.addView(containerView, 0);
-            }
-        }
-    }
-
-    /**
-     * Start work challenge activity.
-     * @return true if screenlock exists
-     */
-    private boolean startConfirmCredential(int userId) {
-        final Intent newIntent = mKeyguardManager.createConfirmDeviceCredentialIntent(null, null,
-                userId);
-        if (newIntent == null) {
-            return false;
-        }
-        mConfirmingCredentialUser = userId;
-        startActivityForResult(newIntent, REQUEST_CONFIRM_CREDENTIALS);
-        return true;
-    }
-
-    /**
-     * Adapter for expandable list view of certificates. Groups in the view correspond to profiles
-     * whereas children correspond to certificates.
-     */
-    private class GroupAdapter extends BaseExpandableListAdapter implements
-            ExpandableListView.OnGroupClickListener, ExpandableListView.OnChildClickListener,
-            View.OnClickListener {
-        private final AdapterData mData;
-
-        private GroupAdapter(Tab tab) {
-            mData = new AdapterData(tab, this);
-            load();
-        }
-
-        @Override
-        public int getGroupCount() {
-            return mData.mCertHoldersByUserId.size();
-        }
-        @Override
-        public int getChildrenCount(int groupPosition) {
-            List<CertHolder> certHolders = mData.mCertHoldersByUserId.valueAt(groupPosition);
-            if (certHolders != null) {
-                return certHolders.size();
-            }
-            return 0;
-        }
-        @Override
-        public UserHandle getGroup(int groupPosition) {
-            return new UserHandle(mData.mCertHoldersByUserId.keyAt(groupPosition));
-        }
-        @Override
-        public CertHolder getChild(int groupPosition, int childPosition) {
-            return mData.mCertHoldersByUserId.get(getUserIdByGroup(groupPosition)).get(
-                    childPosition);
-        }
-        @Override
-        public long getGroupId(int groupPosition) {
-            return getUserIdByGroup(groupPosition);
-        }
-        private int getUserIdByGroup(int groupPosition) {
-            return mData.mCertHoldersByUserId.keyAt(groupPosition);
-        }
-        public UserInfo getUserInfoByGroup(int groupPosition) {
-            return mUserManager.getUserInfo(getUserIdByGroup(groupPosition));
-        }
-        @Override
-        public long getChildId(int groupPosition, int childPosition) {
-            return childPosition;
-        }
-        @Override
-        public boolean hasStableIds() {
-            return false;
-        }
-        @Override
-        public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
-                ViewGroup parent) {
-            if (convertView == null) {
-                LayoutInflater inflater = (LayoutInflater) getActivity()
-                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-                convertView = Utils.inflateCategoryHeader(inflater, parent);
-            }
-
-            final TextView title = (TextView) convertView.findViewById(android.R.id.title);
-            if (getUserInfoByGroup(groupPosition).isManagedProfile()) {
-                title.setText(mDevicePolicyManager.getResources().getString(WORK_CATEGORY_HEADER,
-                        () -> getString(R.string.category_work)));
-            } else {
-                title.setText(mDevicePolicyManager.getResources().getString(
-                        PERSONAL_CATEGORY_HEADER,
-                        () -> getString(R.string.category_personal)));
-
-            }
-            title.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
-
-            return convertView;
-        }
-        @Override
-        public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
-                View convertView, ViewGroup parent) {
-            return getViewForCertificate(getChild(groupPosition, childPosition), mData.mTab,
-                    convertView, parent);
-        }
-        @Override
-        public boolean isChildSelectable(int groupPosition, int childPosition) {
-            return true;
-        }
-
-        @Override
-        public boolean onChildClick(ExpandableListView expandableListView, View view,
-                int groupPosition, int childPosition, long id) {
-            showCertDialog(getChild(groupPosition, childPosition));
-            return true;
-        }
-
-        /**
-         * Called when the switch on a system certificate is clicked. This will toggle whether it
-         * is trusted as a credential.
-         */
-        @Override
-        public void onClick(View view) {
-            CertHolder holder = (CertHolder) view.getTag();
-            removeOrInstallCert(holder);
-        }
-
-        @Override
-        public boolean onGroupClick(ExpandableListView expandableListView, View view,
-                int groupPosition, long id) {
-            return !checkGroupExpandableAndStartWarningActivity(groupPosition);
-        }
-
-        public void load() {
-            mData.new AliasLoader().execute();
-        }
-
-        public void remove(CertHolder certHolder) {
-            mData.remove(certHolder);
-        }
-
-        public void setExpandableListView(ExpandableListView lv) {
-            lv.setAdapter(this);
-            lv.setOnGroupClickListener(this);
-            lv.setOnChildClickListener(this);
-            lv.setVisibility(View.VISIBLE);
-        }
-
-        public ChildAdapter getChildAdapter(int groupPosition) {
-            return new ChildAdapter(this, groupPosition);
-        }
-
-        public boolean checkGroupExpandableAndStartWarningActivity(int groupPosition) {
-            return checkGroupExpandableAndStartWarningActivity(groupPosition, true);
-        }
-
-        public boolean checkGroupExpandableAndStartWarningActivity(int groupPosition,
-                boolean startActivity) {
-            final UserHandle groupUser = getGroup(groupPosition);
-            final int groupUserId = groupUser.getIdentifier();
-            if (mUserManager.isQuietModeEnabled(groupUser)) {
-                final Intent intent = UnlaunchableAppActivity.createInQuietModeDialogIntent(
-                        groupUserId);
-                if (startActivity) {
-                    getActivity().startActivity(intent);
-                }
-                return false;
-            } else if (!mUserManager.isUserUnlocked(groupUser)) {
-                final LockPatternUtils lockPatternUtils = new LockPatternUtils(
-                        getActivity());
-                if (lockPatternUtils.isSeparateProfileChallengeEnabled(groupUserId)) {
-                    if (startActivity) {
-                        startConfirmCredential(groupUserId);
-                    }
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        private View getViewForCertificate(CertHolder certHolder, Tab mTab, View convertView,
-                ViewGroup parent) {
-            ViewHolder holder;
-            if (convertView == null) {
-                holder = new ViewHolder();
-                LayoutInflater inflater = LayoutInflater.from(getActivity());
-                convertView = inflater.inflate(R.layout.trusted_credential, parent, false);
-                convertView.setTag(holder);
-                holder.mSubjectPrimaryView = (TextView)
-                        convertView.findViewById(R.id.trusted_credential_subject_primary);
-                holder.mSubjectSecondaryView = (TextView)
-                        convertView.findViewById(R.id.trusted_credential_subject_secondary);
-                holder.mSwitch = (Switch) convertView.findViewById(
-                        R.id.trusted_credential_status);
-                holder.mSwitch.setOnClickListener(this);
-            } else {
-                holder = (ViewHolder) convertView.getTag();
-            }
-            holder.mSubjectPrimaryView.setText(certHolder.mSubjectPrimary);
-            holder.mSubjectSecondaryView.setText(certHolder.mSubjectSecondary);
-            if (mTab.mSwitch) {
-                holder.mSwitch.setChecked(!certHolder.mDeleted);
-                holder.mSwitch.setEnabled(!mUserManager.hasUserRestriction(
-                        UserManager.DISALLOW_CONFIG_CREDENTIALS,
-                        new UserHandle(certHolder.mProfileId)));
-                holder.mSwitch.setVisibility(View.VISIBLE);
-                holder.mSwitch.setTag(certHolder);
-            }
-            return convertView;
-        }
-
-        private class ViewHolder {
-            private TextView mSubjectPrimaryView;
-            private TextView mSubjectSecondaryView;
-            private Switch mSwitch;
-        }
-    }
-
-    private class ChildAdapter extends BaseAdapter implements View.OnClickListener,
-            AdapterView.OnItemClickListener {
-        private final int[] GROUP_EXPANDED_STATE_SET = {com.android.internal.R.attr.state_expanded};
-        private final int[] EMPTY_STATE_SET = {};
-        private final LinearLayout.LayoutParams HIDE_CONTAINER_LAYOUT_PARAMS =
-                new LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT, 0f);
-        private final LinearLayout.LayoutParams HIDE_LIST_LAYOUT_PARAMS =
-                new LinearLayout.LayoutParams(MATCH_PARENT, 0);
-        private final LinearLayout.LayoutParams SHOW_LAYOUT_PARAMS = new LinearLayout.LayoutParams(
-                LinearLayout.LayoutParams.MATCH_PARENT, MATCH_PARENT, 1f);
-        private final GroupAdapter mParent;
-        private final int mGroupPosition;
-        /*
-         * This class doesn't hold the actual data. Events should notify parent.
-         * When notifying DataSet events in this class, events should be forwarded to mParent.
-         * i.e. this.notifyDataSetChanged -> mParent.notifyDataSetChanged -> mObserver.onChanged
-         * -> outsideObservers.onChanged() (e.g. ListView)
-         */
-        private final DataSetObserver mObserver = new DataSetObserver() {
-            @Override
-            public void onChanged() {
-                super.onChanged();
-                ChildAdapter.super.notifyDataSetChanged();
-            }
-            @Override
-            public void onInvalidated() {
-                super.onInvalidated();
-                ChildAdapter.super.notifyDataSetInvalidated();
-            }
-        };
-
-        private boolean mIsListExpanded = true;
-        private LinearLayout mContainerView;
-        private ViewGroup mHeaderView;
-        private ListView mListView;
-        private ImageView mIndicatorView;
-
-        private ChildAdapter(GroupAdapter parent, int groupPosition) {
-            mParent = parent;
-            mGroupPosition = groupPosition;
-            mParent.registerDataSetObserver(mObserver);
-        }
-
-        @Override public int getCount() {
-            return mParent.getChildrenCount(mGroupPosition);
-        }
-        @Override public CertHolder getItem(int position) {
-            return mParent.getChild(mGroupPosition, position);
-        }
-        @Override public long getItemId(int position) {
-            return mParent.getChildId(mGroupPosition, position);
-        }
-        @Override public View getView(int position, View convertView, ViewGroup parent) {
-            return mParent.getChildView(mGroupPosition, position, false, convertView, parent);
-        }
-        // DataSet events
-        @Override
-        public void notifyDataSetChanged() {
-            // Don't call super as the parent will propagate this event back later in mObserver
-            mParent.notifyDataSetChanged();
-        }
-        @Override
-        public void notifyDataSetInvalidated() {
-            // Don't call super as the parent will propagate this event back later in mObserver
-            mParent.notifyDataSetInvalidated();
-        }
-
-        // View related codes
-        @Override
-        public void onClick(View view) {
-            mIsListExpanded = checkGroupExpandableAndStartWarningActivity() && !mIsListExpanded;
-            refreshViews();
-        }
-
-        @Override
-        public void onItemClick(AdapterView<?> adapterView, View view, int pos, long id) {
-            showCertDialog(getItem(pos));
-        }
-
-        public void setContainerView(LinearLayout containerView) {
-            mContainerView = containerView;
-
-            mListView = (ListView) mContainerView.findViewById(R.id.cert_list);
-            mListView.setAdapter(this);
-            mListView.setOnItemClickListener(this);
-            mListView.setItemsCanFocus(true);
-
-            mHeaderView = (ViewGroup) mContainerView.findViewById(R.id.header_view);
-            mHeaderView.setOnClickListener(this);
-
-            mIndicatorView = (ImageView) mHeaderView.findViewById(R.id.group_indicator);
-            mIndicatorView.setImageDrawable(getGroupIndicator());
-
-            FrameLayout headerContentContainer = (FrameLayout)
-                    mHeaderView.findViewById(R.id.header_content_container);
-            headerContentContainer.addView(
-                    mParent.getGroupView(mGroupPosition, true /* parent ignores it */, null,
-                            headerContentContainer));
-        }
-
-        public void showHeader(boolean showHeader) {
-            mHeaderView.setVisibility(showHeader ? View.VISIBLE : View.GONE);
-        }
-
-        public void showDivider(boolean showDivider) {
-            View dividerView = mHeaderView.findViewById(R.id.header_divider);
-            dividerView.setVisibility(showDivider ? View.VISIBLE : View.GONE );
-        }
-
-        public void setExpandIfAvailable(boolean expanded) {
-            mIsListExpanded = expanded && mParent.checkGroupExpandableAndStartWarningActivity(
-                    mGroupPosition, false /* startActivity */);
-            refreshViews();
-        }
-
-        private boolean checkGroupExpandableAndStartWarningActivity() {
-            return mParent.checkGroupExpandableAndStartWarningActivity(mGroupPosition);
-        }
-
-        private void refreshViews() {
-            mIndicatorView.setImageState(mIsListExpanded ? GROUP_EXPANDED_STATE_SET
-                    : EMPTY_STATE_SET, false);
-            mListView.setLayoutParams(mIsListExpanded ? SHOW_LAYOUT_PARAMS
-                    : HIDE_LIST_LAYOUT_PARAMS);
-            mContainerView.setLayoutParams(mIsListExpanded ? SHOW_LAYOUT_PARAMS
-                    : HIDE_CONTAINER_LAYOUT_PARAMS);
-        }
-
-        // Get group indicator from styles of ExpandableListView
-        private Drawable getGroupIndicator() {
-            final TypedArray a = getActivity().obtainStyledAttributes(null,
-                    com.android.internal.R.styleable.ExpandableListView,
-                    com.android.internal.R.attr.expandableListViewStyle, 0);
-            Drawable groupIndicator = a.getDrawable(
-                    com.android.internal.R.styleable.ExpandableListView_groupIndicator);
-            a.recycle();
-            return groupIndicator;
-        }
-    }
-
-    private class AdapterData {
-        private final SparseArray<List<CertHolder>> mCertHoldersByUserId =
-                new SparseArray<List<CertHolder>>();
-        private final Tab mTab;
-        private final GroupAdapter mAdapter;
-
-        private AdapterData(Tab tab, GroupAdapter adapter) {
-            mAdapter = adapter;
-            mTab = tab;
-        }
-
-        private class AliasLoader extends AsyncTask<Void, Integer, SparseArray<List<CertHolder>>> {
-            private ProgressBar mProgressBar;
-            private View mContentView;
-            private Context mContext;
-
-            public AliasLoader() {
-                mContext = getActivity();
-                mAliasLoaders.add(this);
-                List<UserHandle> profiles = mUserManager.getUserProfiles();
-                for (UserHandle profile : profiles) {
-                    mCertHoldersByUserId.put(profile.getIdentifier(), new ArrayList<CertHolder>());
-                }
-            }
-
-            private boolean shouldSkipProfile(UserHandle userHandle) {
-                return mUserManager.isQuietModeEnabled(userHandle)
-                        || !mUserManager.isUserUnlocked(userHandle.getIdentifier());
-            }
-
-            @Override protected void onPreExecute() {
-                View content = mTabHost.getTabContentView();
-                mProgressBar = (ProgressBar) content.findViewById(mTab.mProgress);
-                mContentView = content.findViewById(mTab.mContentView);
-                mProgressBar.setVisibility(View.VISIBLE);
-                mContentView.setVisibility(View.GONE);
-            }
-            @Override protected SparseArray<List<CertHolder>> doInBackground(Void... params) {
-                SparseArray<List<CertHolder>> certHoldersByProfile =
-                        new SparseArray<List<CertHolder>>();
-                try {
-                    synchronized(mKeyChainConnectionByProfileId) {
-                        List<UserHandle> profiles = mUserManager.getUserProfiles();
-                        final int n = profiles.size();
-                        // First we get all aliases for all profiles in order to show progress
-                        // correctly. Otherwise this could all be in a single loop.
-                        SparseArray<List<String>> aliasesByProfileId = new SparseArray<
-                                List<String>>(n);
-                        int max = 0;
-                        int progress = 0;
-                        for (int i = 0; i < n; ++i) {
-                            UserHandle profile = profiles.get(i);
-                            int profileId = profile.getIdentifier();
-                            if (shouldSkipProfile(profile)) {
-                                continue;
-                            }
-                            KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext,
-                                    profile);
-                            // Saving the connection for later use on the certificate dialog.
-                            mKeyChainConnectionByProfileId.put(profileId, keyChainConnection);
-                            IKeyChainService service = keyChainConnection.getService();
-                            List<String> aliases = mTab.getAliases(service);
-                            if (isCancelled()) {
-                                return new SparseArray<List<CertHolder>>();
-                            }
-                            max += aliases.size();
-                            aliasesByProfileId.put(profileId, aliases);
-                        }
-                        for (int i = 0; i < n; ++i) {
-                            UserHandle profile = profiles.get(i);
-                            int profileId = profile.getIdentifier();
-                            List<String> aliases = aliasesByProfileId.get(profileId);
-                            if (isCancelled()) {
-                                return new SparseArray<List<CertHolder>>();
-                            }
-                            KeyChainConnection keyChainConnection = mKeyChainConnectionByProfileId.get(
-                                    profileId);
-                            if (shouldSkipProfile(profile) || aliases == null
-                                    || keyChainConnection == null) {
-                                certHoldersByProfile.put(profileId, new ArrayList<CertHolder>(0));
-                                continue;
-                            }
-                            IKeyChainService service = keyChainConnection.getService();
-                            List<CertHolder> certHolders = new ArrayList<CertHolder>(max);
-                            final int aliasMax = aliases.size();
-                            for (int j = 0; j < aliasMax; ++j) {
-                                String alias = aliases.get(j);
-                                byte[] encodedCertificate = service.getEncodedCaCertificate(alias,
-                                        true);
-                                X509Certificate cert = KeyChain.toCertificate(encodedCertificate);
-                                certHolders.add(new CertHolder(service, mAdapter,
-                                        mTab, alias, cert, profileId));
-                                publishProgress(++progress, max);
-                            }
-                            Collections.sort(certHolders);
-                            certHoldersByProfile.put(profileId, certHolders);
-                        }
-                        return certHoldersByProfile;
-                    }
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Remote exception while loading aliases.", e);
-                    return new SparseArray<List<CertHolder>>();
-                } catch (InterruptedException e) {
-                    Log.e(TAG, "InterruptedException while loading aliases.", e);
-                    return new SparseArray<List<CertHolder>>();
-                }
-            }
-            @Override protected void onProgressUpdate(Integer... progressAndMax) {
-                int progress = progressAndMax[0];
-                int max = progressAndMax[1];
-                if (max != mProgressBar.getMax()) {
-                    mProgressBar.setMax(max);
-                }
-                mProgressBar.setProgress(progress);
-            }
-            @Override protected void onPostExecute(SparseArray<List<CertHolder>> certHolders) {
-                mCertHoldersByUserId.clear();
-                final int n = certHolders.size();
-                for (int i = 0; i < n; ++i) {
-                    mCertHoldersByUserId.put(certHolders.keyAt(i), certHolders.valueAt(i));
-                }
-                mAdapter.notifyDataSetChanged();
-                mProgressBar.setVisibility(View.GONE);
-                mContentView.setVisibility(View.VISIBLE);
-                mProgressBar.setProgress(0);
-                mAliasLoaders.remove(this);
-                showTrustAllCaDialogIfNeeded();
-            }
-
-            private boolean isUserTabAndTrustAllCertMode() {
-                return isTrustAllCaCertModeInProgress() && mTab == Tab.USER;
-            }
-
-            @UiThread
-            private void showTrustAllCaDialogIfNeeded() {
-                if (!isUserTabAndTrustAllCertMode()) {
-                    return;
-                }
-                List<CertHolder> certHolders = mCertHoldersByUserId.get(mTrustAllCaUserId);
-                if (certHolders == null) {
-                    return;
-                }
-
-                List<CertHolder> unapprovedUserCertHolders = new ArrayList<>();
-                final DevicePolicyManager dpm = mContext.getSystemService(
-                        DevicePolicyManager.class);
-                for (CertHolder cert : certHolders) {
-                    if (cert != null && !dpm.isCaCertApproved(cert.mAlias, mTrustAllCaUserId)) {
-                        unapprovedUserCertHolders.add(cert);
-                    }
-                }
-
-                if (unapprovedUserCertHolders.size() == 0) {
-                    Log.w(TAG, "no cert is pending approval for user " + mTrustAllCaUserId);
-                    return;
-                }
-                showTrustAllCaDialog(unapprovedUserCertHolders);
-            }
-        }
-
-        public void remove(CertHolder certHolder) {
-            if (mCertHoldersByUserId != null) {
-                final List<CertHolder> certs = mCertHoldersByUserId.get(certHolder.mProfileId);
-                if (certs != null) {
-                    certs.remove(certHolder);
-                }
-            }
-        }
-    }
-
-    /* package */ static class CertHolder implements Comparable<CertHolder> {
-        public int mProfileId;
-        private final IKeyChainService mService;
-        private final GroupAdapter mAdapter;
-        private final Tab mTab;
-        private final String mAlias;
-        private final X509Certificate mX509Cert;
-
-        private final SslCertificate mSslCert;
-        private final String mSubjectPrimary;
-        private final String mSubjectSecondary;
-        private boolean mDeleted;
-
-        private CertHolder(IKeyChainService service,
-                           GroupAdapter adapter,
-                           Tab tab,
-                           String alias,
-                           X509Certificate x509Cert,
-                           int profileId) {
-            mProfileId = profileId;
-            mService = service;
-            mAdapter = adapter;
-            mTab = tab;
-            mAlias = alias;
-            mX509Cert = x509Cert;
-
-            mSslCert = new SslCertificate(x509Cert);
-
-            String cn = mSslCert.getIssuedTo().getCName();
-            String o = mSslCert.getIssuedTo().getOName();
-            String ou = mSslCert.getIssuedTo().getUName();
-            // if we have a O, use O as primary subject, secondary prefer CN over OU
-            // if we don't have an O, use CN as primary, empty secondary
-            // if we don't have O or CN, use DName as primary, empty secondary
-            if (!o.isEmpty()) {
-                if (!cn.isEmpty()) {
-                    mSubjectPrimary = o;
-                    mSubjectSecondary = cn;
-                } else {
-                    mSubjectPrimary = o;
-                    mSubjectSecondary = ou;
-                }
-            } else {
-                if (!cn.isEmpty()) {
-                    mSubjectPrimary = cn;
-                    mSubjectSecondary = "";
-                } else {
-                    mSubjectPrimary = mSslCert.getIssuedTo().getDName();
-                    mSubjectSecondary = "";
-                }
-            }
-            try {
-                mDeleted = mTab.deleted(mService, mAlias);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Remote exception while checking if alias " + mAlias + " is deleted.",
-                        e);
-                mDeleted = false;
-            }
-        }
-        @Override public int compareTo(CertHolder o) {
-            int primary = this.mSubjectPrimary.compareToIgnoreCase(o.mSubjectPrimary);
-            if (primary != 0) {
-                return primary;
-            }
-            return this.mSubjectSecondary.compareToIgnoreCase(o.mSubjectSecondary);
-        }
-        @Override public boolean equals(Object o) {
-            if (!(o instanceof CertHolder)) {
-                return false;
-            }
-            CertHolder other = (CertHolder) o;
-            return mAlias.equals(other.mAlias);
-        }
-        @Override public int hashCode() {
-            return mAlias.hashCode();
-        }
-
-        public int getUserId() {
-            return mProfileId;
-        }
-
-        public String getAlias() {
-            return mAlias;
-        }
-
-        public boolean isSystemCert() {
-            return mTab == Tab.SYSTEM;
-        }
-
-        public boolean isDeleted() {
-            return mDeleted;
-        }
-    }
-
-
-    private boolean isTrustAllCaCertModeInProgress() {
-        return mTrustAllCaUserId != UserHandle.USER_NULL;
-    }
-
-    private void showTrustAllCaDialog(List<CertHolder> unapprovedCertHolders) {
-        final CertHolder[] arr = unapprovedCertHolders.toArray(
-                new CertHolder[unapprovedCertHolders.size()]);
-        new TrustedCredentialsDialogBuilder(getActivity(), this)
-                .setCertHolders(arr)
-                .setOnDismissListener(new DialogInterface.OnDismissListener() {
-                    @Override
-                    public void onDismiss(DialogInterface dialogInterface) {
-                        // Avoid starting dialog again after Activity restart.
-                        getActivity().getIntent().removeExtra(ARG_SHOW_NEW_FOR_USER);
-                        mTrustAllCaUserId = UserHandle.USER_NULL;
-                    }
-                })
-                .show();
-    }
-
-    private void showCertDialog(final CertHolder certHolder) {
-        new TrustedCredentialsDialogBuilder(getActivity(), this)
-                .setCertHolder(certHolder)
-                .show();
-    }
-
-    @Override
-    public List<X509Certificate> getX509CertsFromCertHolder(CertHolder certHolder) {
-        List<X509Certificate> certificates = null;
-        try {
-            synchronized (mKeyChainConnectionByProfileId) {
-                KeyChainConnection keyChainConnection = mKeyChainConnectionByProfileId.get(
-                        certHolder.mProfileId);
-                IKeyChainService service = keyChainConnection.getService();
-                List<String> chain = service.getCaCertificateChainAliases(certHolder.mAlias, true);
-                final int n = chain.size();
-                certificates = new ArrayList<X509Certificate>(n);
-                for (int i = 0; i < n; ++i) {
-                    byte[] encodedCertificate = service.getEncodedCaCertificate(chain.get(i), true);
-                    X509Certificate certificate = KeyChain.toCertificate(encodedCertificate);
-                    certificates.add(certificate);
-                }
-            }
-        } catch (RemoteException ex) {
-            Log.e(TAG, "RemoteException while retrieving certificate chain for root "
-                    + certHolder.mAlias, ex);
-        }
-        return certificates;
-    }
-
-    @Override
-    public void removeOrInstallCert(CertHolder certHolder) {
-        new AliasOperation(certHolder).execute();
-    }
-
-    @Override
-    public boolean startConfirmCredentialIfNotConfirmed(int userId,
-            IntConsumer onCredentialConfirmedListener) {
-        if (mConfirmedCredentialUsers.contains(userId)) {
-            // Credential has been confirmed. Don't start activity.
-            return false;
-        }
-
-        boolean result = startConfirmCredential(userId);
-        if (result) {
-            mConfirmingCredentialListener = onCredentialConfirmedListener;
-        }
-        return result;
-    }
-
-    private class AliasOperation extends AsyncTask<Void, Void, Boolean> {
-        private final CertHolder mCertHolder;
-
-        private AliasOperation(CertHolder certHolder) {
-            mCertHolder = certHolder;
-            mAliasOperation = this;
-        }
-
-        @Override
-        protected Boolean doInBackground(Void... params) {
-            try {
-                synchronized (mKeyChainConnectionByProfileId) {
-                    KeyChainConnection keyChainConnection = mKeyChainConnectionByProfileId.get(
-                            mCertHolder.mProfileId);
-                    IKeyChainService service = keyChainConnection.getService();
-                    if (mCertHolder.mDeleted) {
-                        byte[] bytes = mCertHolder.mX509Cert.getEncoded();
-                        service.installCaCertificate(bytes);
-                        return true;
-                    } else {
-                        return service.deleteCaCertificate(mCertHolder.mAlias);
-                    }
-                }
-            } catch (CertificateEncodingException | SecurityException | IllegalStateException
-                    | RemoteException e) {
-                Log.w(TAG, "Error while toggling alias " + mCertHolder.mAlias, e);
-                return false;
-            }
-        }
-
-        @Override
-        protected void onPostExecute(Boolean ok) {
-            if (ok) {
-                if (mCertHolder.mTab.mSwitch) {
-                    mCertHolder.mDeleted = !mCertHolder.mDeleted;
-                } else {
-                    mCertHolder.mAdapter.remove(mCertHolder);
-                }
-                mCertHolder.mAdapter.notifyDataSetChanged();
-            } else {
-                // bail, reload to reset to known state
-                mCertHolder.mAdapter.load();
-            }
-            mAliasOperation = null;
-        }
-    }
 }
