Merge "Change "Previously connected devices" string to "Saved devices"" into tm-dev
diff --git a/res/layout/preference_expand_divider.xml b/res/layout/preference_expand_divider.xml
index ce3d2e7..9b76688 100644
--- a/res/layout/preference_expand_divider.xml
+++ b/res/layout/preference_expand_divider.xml
@@ -34,7 +34,6 @@
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:paddingEnd="4dp"
-        android:singleLine="true"
         android:textAlignment="viewStart"
         style="@style/PreferenceCategoryTitleTextStyle"/>
 
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;
-        }
-    }
 }
diff --git a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
index b397e18..34edf98 100644
--- a/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
+++ b/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetail.java
@@ -172,7 +172,7 @@
         launchArgs.mPackageName = entry.getDefaultPackageName();
         launchArgs.mAppLabel = entry.getLabel();
         launchArgs.mUid = entry.getUid();
-        launchArgs.mIconId = entry.iconId;
+        launchArgs.mIconId = entry.mIconId;
         launchArgs.mConsumedPower = (int) entry.getConsumedPower();
         launchArgs.mForegroundTimeMs = isValidToShowSummary ? entry.getTimeInForegroundMs() : 0;
         launchArgs.mBackgroundTimeMs = isValidToShowSummary ? entry.getTimeInBackgroundMs() : 0;
diff --git a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
index 8dbce79..8fb0d1e 100644
--- a/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryAppListPreferenceController.java
@@ -127,9 +127,9 @@
                         final int userId = UserHandle.getUserId(entry.getUid());
                         final UserHandle userHandle = new UserHandle(userId);
                         pgp.setIcon(mUserManager.getBadgedIconForUser(entry.getIcon(), userHandle));
-                        pgp.setTitle(entry.name);
+                        pgp.setTitle(entry.mName);
                         if (entry.isAppEntry()) {
-                            pgp.setContentDescription(entry.name);
+                            pgp.setContentDescription(entry.mName);
                         }
                     }
                     break;
@@ -249,7 +249,7 @@
                             contentDescription, entry);
                     pref.setKey(key);
                 }
-                entry.percent = percentOfTotal;
+                entry.mPercent = percentOfTotal;
                 pref.setTitle(entry.getLabel());
                 pref.setOrder(i + 1);
                 pref.setPercent(percentOfTotal);
@@ -288,7 +288,7 @@
             final BatteryEntry entry = usageList.get(i);
             final double percentOfTotal = mBatteryUtils.calculateBatteryPercent(
                     entry.getConsumedPower(), totalPower, dischargePercentage);
-            entry.percent = percentOfTotal;
+            entry.mPercent = percentOfTotal;
         }
         return usageList;
     }
diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
index 249ee49..02248c9 100644
--- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java
@@ -508,7 +508,9 @@
             mBatteryHistoryKeys[mTrapezoidIndex * 2], mIs24HourFormat);
         final String toHour = ConvertUtils.utcToLocalTimeHour(mPrefContext,
             mBatteryHistoryKeys[(mTrapezoidIndex + 1) * 2], mIs24HourFormat);
-        return String.format("%s - %s", fromHour, toHour);
+        return mIs24HourFormat
+            ? String.format("%s–%s", fromHour, toHour)
+            : String.format("%s – %s", fromHour, toHour);
     }
 
     @VisibleForTesting
diff --git a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java
index ca29cfe..5ef1110 100644
--- a/src/com/android/settings/fuelgauge/BatteryDiffEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryDiffEntry.java
@@ -171,9 +171,9 @@
         // Checks whether we have cached data or not first before fetching.
         final BatteryEntry.NameAndIcon nameAndIcon = getCache();
         if (nameAndIcon != null) {
-            mAppLabel = nameAndIcon.name;
-            mAppIcon = nameAndIcon.icon;
-            mAppIconId = nameAndIcon.iconId;
+            mAppLabel = nameAndIcon.mName;
+            mAppIcon = nameAndIcon.mIcon;
+            mAppIconId = nameAndIcon.mIconId;
         }
         final Boolean validForRestriction = sValidForRestriction.get(getKey());
         if (validForRestriction != null) {
@@ -196,8 +196,8 @@
                     BatteryEntry.getNameAndIconFromUserId(
                         mContext, (int) mBatteryHistEntry.mUserId);
                 if (nameAndIconForUser != null) {
-                    mAppIcon = nameAndIconForUser.icon;
-                    mAppLabel = nameAndIconForUser.name;
+                    mAppIcon = nameAndIconForUser.mIcon;
+                    mAppLabel = nameAndIconForUser.mName;
                     sResourceCache.put(
                         getKey(),
                         new BatteryEntry.NameAndIcon(mAppLabel, mAppIcon, /*iconId=*/ 0));
@@ -208,10 +208,10 @@
                     BatteryEntry.getNameAndIconFromPowerComponent(
                         mContext, mBatteryHistEntry.mDrainType);
                 if (nameAndIconForSystem != null) {
-                    mAppLabel = nameAndIconForSystem.name;
-                    if (nameAndIconForSystem.iconId != 0) {
-                        mAppIconId = nameAndIconForSystem.iconId;
-                        mAppIcon = mContext.getDrawable(nameAndIconForSystem.iconId);
+                    mAppLabel = nameAndIconForSystem.mName;
+                    if (nameAndIconForSystem.mIconId != 0) {
+                        mAppIconId = nameAndIconForSystem.mIconId;
+                        mAppIcon = mContext.getDrawable(nameAndIconForSystem.mIconId);
                     }
                     sResourceCache.put(
                         getKey(),
@@ -308,8 +308,8 @@
         if (packages == null || packages.length == 0) {
             final BatteryEntry.NameAndIcon nameAndIcon =
                 BatteryEntry.getNameAndIconFromUid(mContext, mAppLabel, uid);
-            mAppLabel = nameAndIcon.name;
-            mAppIcon = nameAndIcon.icon;
+            mAppLabel = nameAndIcon.mName;
+            mAppIcon = nameAndIcon.mIcon;
         }
 
         final BatteryEntry.NameAndIcon nameAndIcon =
@@ -319,13 +319,13 @@
         // Clears BatteryEntry internal cache since we will have another one.
         BatteryEntry.clearUidCache();
         if (nameAndIcon != null) {
-            mAppLabel = nameAndIcon.name;
-            mAppIcon = nameAndIcon.icon;
-            mDefaultPackageName = nameAndIcon.packageName;
+            mAppLabel = nameAndIcon.mName;
+            mAppIcon = nameAndIcon.mIcon;
+            mDefaultPackageName = nameAndIcon.mPackageName;
             if (mDefaultPackageName != null
-                    && !mDefaultPackageName.equals(nameAndIcon.packageName)) {
+                    && !mDefaultPackageName.equals(nameAndIcon.mPackageName)) {
                 Log.w(TAG, String.format("found different package: %s | %s",
-                    mDefaultPackageName, nameAndIcon.packageName));
+                    mDefaultPackageName, nameAndIcon.mPackageName));
             }
         }
     }
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
index 5c9d071..c9acc4c 100644
--- a/src/com/android/settings/fuelgauge/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -53,10 +53,10 @@
 public class BatteryEntry {
 
     public static final class NameAndIcon {
-        public final String name;
-        public final String packageName;
-        public final Drawable icon;
-        public final int iconId;
+        public final String mName;
+        public final String mPackageName;
+        public final Drawable mIcon;
+        public final int mIconId;
 
         public NameAndIcon(String name, Drawable icon, int iconId) {
             this(name, /*packageName=*/ null, icon, iconId);
@@ -64,10 +64,10 @@
 
         public NameAndIcon(
                 String name, String packageName, Drawable icon, int iconId) {
-            this.name = name;
-            this.icon = icon;
-            this.iconId = iconId;
-            this.packageName = packageName;
+            this.mName = name;
+            this.mIcon = icon;
+            this.mIconId = iconId;
+            this.mPackageName = packageName;
         }
     }
 
@@ -111,11 +111,11 @@
                 final NameAndIcon nameAndIcon =
                     BatteryEntry.loadNameAndIcon(
                         be.mContext, be.getUid(), sHandler, be,
-                        be.mDefaultPackageName, be.name, be.icon);
+                        be.mDefaultPackageName, be.mName, be.mIcon);
                 if (nameAndIcon != null) {
-                    be.icon = nameAndIcon.icon;
-                    be.name = nameAndIcon.name;
-                    be.mDefaultPackageName = nameAndIcon.packageName;
+                    be.mIcon = nameAndIcon.mIcon;
+                    be.mName = nameAndIcon.mName;
+                    be.mDefaultPackageName = nameAndIcon.mPackageName;
                 }
             }
         }
@@ -169,27 +169,27 @@
     private long mTimeInForegroundMs;
     private long mTimeInBackgroundMs;
 
-    public String name;
-    public Drawable icon;
-    public int iconId; // For passing to the detail screen.
-    public double percent;
+    public String mName;
+    public Drawable mIcon;
+    public int mIconId;
+    public double mPercent;
     private String mDefaultPackageName;
     private double mConsumedPower;
 
     static class UidToDetail {
-        String name;
-        String packageName;
-        Drawable icon;
+        String mName;
+        String mPackageName;
+        Drawable mIcon;
     }
 
     public BatteryEntry(Context context, Handler handler, UserManager um,
-            @NonNull BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
+            BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
             String packageName) {
         this(context, handler, um, batteryConsumer, isHidden, uid, packages, packageName, true);
     }
 
     public BatteryEntry(Context context, Handler handler, UserManager um,
-            @NonNull BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
+            BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
             String packageName, boolean loadDataInBackground) {
         sHandler = handler;
         mContext = context;
@@ -217,11 +217,11 @@
                 try {
                     ApplicationInfo appInfo =
                             pm.getApplicationInfo(mDefaultPackageName, 0 /* no flags */);
-                    name = pm.getApplicationLabel(appInfo).toString();
+                    mName = pm.getApplicationLabel(appInfo).toString();
                 } catch (NameNotFoundException e) {
                     Log.d(TAG, "PackageManager failed to retrieve ApplicationInfo for: "
                             + mDefaultPackageName);
-                    name = mDefaultPackageName;
+                    mName = mDefaultPackageName;
                 }
             }
             getQuickNameIconForUid(uid, packages, loadDataInBackground);
@@ -235,10 +235,10 @@
             mConsumedPower = batteryConsumer.getConsumedPower();
             final NameAndIcon nameAndIcon = getNameAndIconFromUserId(
                     context, ((UserBatteryConsumer) batteryConsumer).getUserId());
-            icon = nameAndIcon.icon;
-            name = nameAndIcon.name;
+            mIcon = nameAndIcon.mIcon;
+            mName = nameAndIcon.mName;
         } else {
-            throw new IllegalArgumentException("Unsupported battery consumer: " + batteryConsumer);
+            throw new IllegalArgumentException("Unsupported: " + batteryConsumer);
         }
     }
 
@@ -257,11 +257,12 @@
         mUsageDurationMs = usageDurationMs;
         mConsumerType = ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY;
 
-        final NameAndIcon nameAndIcon = getNameAndIconFromPowerComponent(context, powerComponentId);
-        iconId = nameAndIcon.iconId;
-        name = nameAndIcon.name;
-        if (iconId != 0) {
-            icon = context.getDrawable(iconId);
+        final NameAndIcon nameAndIcon =
+            getNameAndIconFromPowerComponent(context, powerComponentId);
+        mIconId = nameAndIcon.mIconId;
+        mName = nameAndIcon.mName;
+        if (mIconId != 0) {
+            mIcon = context.getDrawable(mIconId);
         }
     }
 
@@ -274,9 +275,9 @@
         mIsHidden = false;
         mPowerComponentId = powerComponentId;
 
-        iconId = R.drawable.ic_power_system;
-        icon = context.getDrawable(iconId);
-        name = powerComponentName;
+        mIconId = R.drawable.ic_power_system;
+        mIcon = context.getDrawable(mIconId);
+        mName = powerComponentName;
         mConsumedPower =
             powerComponentId == BatteryConsumer.POWER_COMPONENT_SCREEN
                 ? devicePowerMah
@@ -285,14 +286,11 @@
     }
 
     public Drawable getIcon() {
-        return icon;
+        return mIcon;
     }
 
-    /**
-     * Gets the application name
-     */
     public String getLabel() {
-        return name;
+        return mName;
     }
 
     @ConvertUtils.ConsumerType
@@ -317,18 +315,18 @@
         final String uidString = Integer.toString(uid);
         if (sUidCache.containsKey(uidString)) {
             UidToDetail utd = sUidCache.get(uidString);
-            mDefaultPackageName = utd.packageName;
-            name = utd.name;
-            icon = utd.icon;
+            mDefaultPackageName = utd.mPackageName;
+            mName = utd.mName;
+            mIcon = utd.mIcon;
             return;
         }
 
         if (packages == null || packages.length == 0) {
-            final NameAndIcon nameAndIcon = getNameAndIconFromUid(mContext, name, uid);
-            icon = nameAndIcon.icon;
-            name = nameAndIcon.name;
+            final NameAndIcon nameAndIcon = getNameAndIconFromUid(mContext, mName, uid);
+            mIcon = nameAndIcon.mIcon;
+            mName = nameAndIcon.mName;
         } else {
-            icon = mContext.getPackageManager().getDefaultActivityIcon();
+            mIcon = mContext.getPackageManager().getDefaultActivityIcon();
         }
 
         // Avoids post the loading icon and label in the background request.
@@ -339,9 +337,7 @@
         }
     }
 
-    /**
-     * Loads the app label and icon image and stores into the cache.
-     */
+    /** Loads the app label and icon image and stores into the cache. */
     public static NameAndIcon loadNameAndIcon(
             Context context,
             int uid,
@@ -400,7 +396,7 @@
                 // Look for an official name for this UID.
                 for (String pkgName : packages) {
                     try {
-                        final PackageInfo pi = ipm.getPackageInfo(pkgName, 0 /* no flags */, userId);
+                        final PackageInfo pi = ipm.getPackageInfo(pkgName, 0, userId);
                         if (pi == null) {
                             Log.d(TAG, "Retrieving null package info for package "
                                     + pkgName + ", user " + userId);
@@ -432,9 +428,9 @@
         }
 
         UidToDetail utd = new UidToDetail();
-        utd.name = name;
-        utd.icon = icon;
-        utd.packageName = defaultPackageName;
+        utd.mName = name;
+        utd.mIcon = icon;
+        utd.mPackageName = defaultPackageName;
 
         sUidCache.put(uidString, utd);
         if (handler != null) {
@@ -443,9 +439,7 @@
         return new NameAndIcon(name, defaultPackageName, icon, /*iconId=*/ 0);
     }
 
-    /**
-     * Returns a string that uniquely identifies this battery consumer.
-     */
+    /** Returns a string that uniquely identifies this battery consumer. */
     public String getKey() {
         if (mBatteryConsumer instanceof UidBatteryConsumer) {
             return Integer.toString(mUid);
@@ -456,23 +450,17 @@
         }
     }
 
-    /**
-     * Returns true if the entry is hidden from the battery usage summary list.
-     */
+    /** Returns true if the entry is hidden from the battery usage summary list. */
     public boolean isHidden() {
         return mIsHidden;
     }
 
-    /**
-     * Returns true if this entry describes an app (UID)
-     */
+    /** Returns true if this entry describes an app (UID). */
     public boolean isAppEntry() {
         return mBatteryConsumer instanceof UidBatteryConsumer;
     }
 
-    /**
-     * Returns true if this entry describes a User.
-     */
+    /** Returns true if this entry describes a User. */
     public boolean isUserEntry() {
         if (mBatteryConsumer instanceof UserBatteryConsumer) {
             return true;
@@ -495,9 +483,7 @@
         return mUid;
     }
 
-    /**
-     * Returns foreground foreground time (in milliseconds) that is attributed to this entry.
-     */
+    /** Returns foreground foreground time/ms that is attributed to this entry. */
     public long getTimeInForegroundMs() {
         if (mBatteryConsumer instanceof UidBatteryConsumer) {
             return mTimeInForegroundMs;
@@ -506,9 +492,7 @@
         }
     }
 
-    /**
-     * Returns background activity time (in milliseconds) that is attributed to this entry.
-     */
+    /** Returns background activity time/ms that is attributed to this entry. */
     public long getTimeInBackgroundMs() {
         if (mBatteryConsumer instanceof UidBatteryConsumer) {
             return mTimeInBackgroundMs;
@@ -542,9 +526,7 @@
         }
     }
 
-    /**
-     * Gets name and icon resource from UserBatteryConsumer userId.
-     */
+    /** Gets name and icon resource from UserBatteryConsumer userId. */
     public static NameAndIcon getNameAndIconFromUserId(
             Context context, final int userId) {
         UserManager um = context.getSystemService(UserManager.class);
@@ -562,9 +544,7 @@
         return new NameAndIcon(name, icon, 0 /* iconId */);
     }
 
-    /**
-     * Gets name and icon resource from UidBatteryConsumer uid.
-     */
+    /** Gets name and icon resource from UidBatteryConsumer uid. */
     public static NameAndIcon getNameAndIconFromUid(
             Context context, String name, final int uid) {
         Drawable icon = context.getDrawable(R.drawable.ic_power_system);
@@ -579,9 +559,7 @@
         return new NameAndIcon(name, icon, 0 /* iconId */);
     }
 
-    /**
-     * Gets name and icon resource from BatteryConsumer power component ID.
-     */
+    /** Gets name and icon resource from BatteryConsumer power component ID. */
     public static NameAndIcon getNameAndIconFromPowerComponent(
             Context context, @BatteryConsumer.PowerComponent int powerComponentId) {
         String name;
@@ -625,8 +603,9 @@
                 iconId = R.drawable.ic_settings_phone_idle;
                 break;
             default:
-                name = DebugUtils.constantToString(BatteryConsumer.class, "POWER_COMPONENT_",
-                        powerComponentId);
+                Log.w(TAG, "unknown attribute:" + DebugUtils.constantToString(
+                        BatteryConsumer.class, "POWER_COMPONENT_", powerComponentId));
+                name = null;
                 iconId = R.drawable.ic_power_system;
                 break;
         }
diff --git a/src/com/android/settings/fuelgauge/ConvertUtils.java b/src/com/android/settings/fuelgauge/ConvertUtils.java
index 946c910..696147b 100644
--- a/src/com/android/settings/fuelgauge/ConvertUtils.java
+++ b/src/com/android/settings/fuelgauge/ConvertUtils.java
@@ -101,7 +101,7 @@
             values.put(BatteryHistEntry.KEY_CONSUME_POWER,
                 Double.valueOf(entry.getConsumedPower()));
             values.put(BatteryHistEntry.KEY_PERCENT_OF_TOTAL,
-                Double.valueOf(entry.percent));
+                Double.valueOf(entry.mPercent));
             values.put(BatteryHistEntry.KEY_FOREGROUND_USAGE_TIME,
                 Long.valueOf(entry.getTimeInForegroundMs()));
             values.put(BatteryHistEntry.KEY_BACKGROUND_USAGE_TIME,
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
index a10d323..aaa1487 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/AdvancedPowerUsageDetailTest.java
@@ -181,7 +181,7 @@
         when(mBatteryEntry.getLabel()).thenReturn(APP_LABEL);
         when(mBatteryEntry.getTimeInBackgroundMs()).thenReturn(BACKGROUND_TIME_MS);
         when(mBatteryEntry.getTimeInForegroundMs()).thenReturn(FOREGROUND_TIME_MS);
-        mBatteryEntry.iconId = ICON_ID;
+        mBatteryEntry.mIconId = ICON_ID;
 
         mFragment.mHeaderPreference = mHeaderPreference;
         mFragment.mState = mState;
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java
index 13ce29e..710d065 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryDiffEntryTest.java
@@ -140,8 +140,8 @@
         // Verifies the app label in the cache.
         final BatteryEntry.NameAndIcon nameAndIcon =
             BatteryDiffEntry.sResourceCache.get(entry.getKey());
-        assertThat(nameAndIcon.name).isEqualTo(expectedName);
-        assertThat(nameAndIcon.iconId).isEqualTo(R.drawable.ic_settings_aod);
+        assertThat(nameAndIcon.mName).isEqualTo(expectedName);
+        assertThat(nameAndIcon.mIconId).isEqualTo(R.drawable.ic_settings_aod);
         // Verifies the restrictable flag in the cache.
         assertThat(entry.mValidForRestriction).isTrue();
         assertThat(BatteryDiffEntry.sValidForRestriction.get(entry.getKey())).isTrue();
@@ -166,8 +166,8 @@
         // Verifies the app label in the cache.
         final BatteryEntry.NameAndIcon nameAndIcon =
             BatteryDiffEntry.sResourceCache.get(entry.getKey());
-        assertThat(nameAndIcon.name).isEqualTo(expectedName);
-        assertThat(nameAndIcon.iconId).isEqualTo(0);
+        assertThat(nameAndIcon.mName).isEqualTo(expectedName);
+        assertThat(nameAndIcon.mIconId).isEqualTo(0);
         // Verifies the restrictable flag in the cache.
         assertThat(entry.mValidForRestriction).isTrue();
         assertThat(BatteryDiffEntry.sValidForRestriction.get(entry.getKey())).isTrue();
@@ -195,7 +195,7 @@
         // Verifies the app label in the cache.
         final BatteryEntry.NameAndIcon nameAndIcon =
             BatteryDiffEntry.sResourceCache.get(entry.getKey());
-        assertThat(nameAndIcon.name).isEqualTo(expectedAppLabel);
+        assertThat(nameAndIcon.mName).isEqualTo(expectedAppLabel);
         // Verifies the restrictable flag in the cache.
         assertThat(entry.mValidForRestriction).isFalse();
         assertThat(BatteryDiffEntry.sValidForRestriction.get(entry.getKey())).isFalse();
@@ -215,7 +215,7 @@
         // Verifies the app label in the cache.
         final BatteryEntry.NameAndIcon nameAndIcon =
             BatteryDiffEntry.sResourceCache.get(entry.getKey());
-        assertThat(nameAndIcon.name).isEqualTo(expectedAppLabel);
+        assertThat(nameAndIcon.mName).isEqualTo(expectedAppLabel);
     }
 
     @Test
@@ -274,7 +274,7 @@
         // Verifies the app label in the cache.
         final BatteryEntry.NameAndIcon nameAndIcon =
             BatteryDiffEntry.sResourceCache.get(entry.getKey());
-        assertThat(nameAndIcon.icon).isEqualTo(mockDrawable);
+        assertThat(nameAndIcon.mIcon).isEqualTo(mockDrawable);
     }
 
     @Test
@@ -309,7 +309,7 @@
         // Verifies the cache is updated into the new drawable.
         final BatteryEntry.NameAndIcon nameAndIcon =
             BatteryDiffEntry.sResourceCache.get(entry2.getKey());
-        assertThat(nameAndIcon.icon).isEqualTo(mockDrawable2);
+        assertThat(nameAndIcon.mIcon).isEqualTo(mockDrawable2);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
index c1b1761..966bc70 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryEntryTest.java
@@ -158,8 +158,8 @@
         final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application,
                 BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY, 200, 100, 1000);
 
-        assertThat(entry.iconId).isEqualTo(R.drawable.ic_settings_aod);
-        assertThat(entry.name).isEqualTo("Ambient display");
+        assertThat(entry.mIconId).isEqualTo(R.drawable.ic_settings_aod);
+        assertThat(entry.mName).isEqualTo("Ambient display");
     }
 
     @Test
@@ -167,8 +167,8 @@
         final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application,
                 BatteryConsumer.FIRST_CUSTOM_POWER_COMPONENT_ID + 42, "ABC", 200, 100);
 
-        assertThat(entry.iconId).isEqualTo(R.drawable.ic_power_system);
-        assertThat(entry.name).isEqualTo("ABC");
+        assertThat(entry.mIconId).isEqualTo(R.drawable.ic_power_system);
+        assertThat(entry.mName).isEqualTo("ABC");
     }
 
     @Test
@@ -261,16 +261,16 @@
 
         final NameAndIcon nameAndIcon = BatteryEntry.getNameAndIconFromUserId(
                 mContext, userId);
-        assertThat(nameAndIcon.name).isEqualTo(getString(
+        assertThat(nameAndIcon.mName).isEqualTo(getString(
                 R.string.running_process_item_removed_user_label));
-        assertThat(nameAndIcon.icon).isNull();
+        assertThat(nameAndIcon.mIcon).isNull();
     }
 
     @Test
     public void getNameAndIconFromUid_rerturnExpectedName() {
         final NameAndIcon nameAndIcon = BatteryEntry.getNameAndIconFromUid(
                 mContext, /* name */ null, /* uid */ 0);
-        assertThat(nameAndIcon.name).isEqualTo(getString(R.string.process_kernel_label));
+        assertThat(nameAndIcon.mName).isEqualTo(getString(R.string.process_kernel_label));
 
         assertNameAndIcon("mediaserver", R.string.process_mediaserver_label);
         assertNameAndIcon("dex2oat32", R.string.process_dex2oat_label);
@@ -312,14 +312,14 @@
     private void assertNameAndIcon(String name, int stringId) {
         final NameAndIcon nameAndIcon = BatteryEntry.getNameAndIconFromUid(
                 mContext, name, /* uid */ 1000);
-        assertThat(nameAndIcon.name).isEqualTo(getString(stringId));
+        assertThat(nameAndIcon.mName).isEqualTo(getString(stringId));
     }
 
     private void assertNameAndIcon(int powerComponentId, int stringId, int iconId) {
         final NameAndIcon nameAndIcon = BatteryEntry.getNameAndIconFromPowerComponent(
                 mContext, powerComponentId);
-        assertThat(nameAndIcon.name).isEqualTo(getString(stringId));
-        assertThat(nameAndIcon.iconId).isEqualTo(iconId);
+        assertThat(nameAndIcon.mName).isEqualTo(getString(stringId));
+        assertThat(nameAndIcon.mIconId).isEqualTo(iconId);
     }
 
     private String getString(int stringId) {
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java
index ca3109c..3acb8f3 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/BatteryHistEntryTest.java
@@ -57,7 +57,7 @@
         when(mockBatteryEntry.isHidden()).thenReturn(true);
         when(mBatteryUsageStats.getConsumedPower()).thenReturn(5.1);
         when(mockBatteryEntry.getConsumedPower()).thenReturn(1.1);
-        mockBatteryEntry.percent = 0.3;
+        mockBatteryEntry.mPercent = 0.3;
         when(mockBatteryEntry.getTimeInForegroundMs()).thenReturn(1234L);
         when(mockBatteryEntry.getTimeInBackgroundMs()).thenReturn(5689L);
         when(mockBatteryEntry.getPowerComponentId()).thenReturn(expectedType);
@@ -76,7 +76,7 @@
         assertBatteryHistEntry(
             new BatteryHistEntry(values),
             /*drainType=*/ expectedType,
-            /*percentOfTotal=*/ mockBatteryEntry.percent);
+            /*percentOfTotal=*/ mockBatteryEntry.mPercent);
     }
 
     @Test
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
index ff0f25c..42483d0 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/ConvertUtilsTest.java
@@ -77,7 +77,7 @@
         when(mockBatteryEntry.isHidden()).thenReturn(true);
         when(mBatteryUsageStats.getConsumedPower()).thenReturn(5.1);
         when(mockBatteryEntry.getConsumedPower()).thenReturn(1.1);
-        mockBatteryEntry.percent = 0.3;
+        mockBatteryEntry.mPercent = 0.3;
         when(mockBatteryEntry.getTimeInForegroundMs()).thenReturn(1234L);
         when(mockBatteryEntry.getTimeInBackgroundMs()).thenReturn(5689L);
         when(mockBatteryEntry.getPowerComponentId()).thenReturn(expectedType);