• 【应用分身】下载支持应用分身的应用(QQ),开启应用分身,返回桌面,会出现所有应用的分身。(Unisoc)


    【BUG】【K631AN】【应用分身】下载支持应用分身的应用(QQ),开启应用分身,返回桌面,会出现所有应用的分身。

    1、进入设置中的应用界面逻辑代码

    AppDashboardFragment.java,通过getPreferenceScreenResId()进入应用界面的布局文件app.xml

    /*
     * Copyright (C) 2021 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.applications;
    
    import android.app.settings.SettingsEnums;
    import android.content.Context;
    import android.provider.SearchIndexableResource;
    
    import com.android.settings.R;
    import com.android.settings.dashboard.DashboardFragment;
    import com.android.settings.search.BaseSearchIndexProvider;
    import com.android.settingslib.core.AbstractPreferenceController;
    import com.android.settingslib.search.SearchIndexable;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    /** Settings page for apps. */
    @SearchIndexable
    public class AppDashboardFragment extends DashboardFragment {
    
        private static final String TAG = "AppDashboardFragment";
        private AppsPreferenceController mAppsPreferenceController;
    
        private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
            final List<AbstractPreferenceController> controllers = new ArrayList<>();
            controllers.add(new AppsPreferenceController(context));
            return controllers;
        }
    
        @Override
        public int getMetricsCategory() {
            return SettingsEnums.MANAGE_APPLICATIONS;
        }
    
        @Override
        protected String getLogTag() {
            return TAG;
        }
    
        @Override
        public int getHelpResource() {
            return R.string.help_url_apps_and_notifications;
        }
    
        @Override
        protected int getPreferenceScreenResId() {
            return R.xml.apps;
        }
    
        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            use(SpecialAppAccessPreferenceController.class).setSession(getSettingsLifecycle());
            mAppsPreferenceController = use(AppsPreferenceController.class);
            mAppsPreferenceController.setFragment(this /* fragment */);
            getSettingsLifecycle().addObserver(mAppsPreferenceController);
    
            final HibernatedAppsPreferenceController hibernatedAppsPreferenceController =
                    use(HibernatedAppsPreferenceController.class);
            getSettingsLifecycle().addObserver(hibernatedAppsPreferenceController);
        }
    
        @Override
        protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
            return buildPreferenceControllers(context);
        }
    
        public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
                new BaseSearchIndexProvider() {
                    @Override
                    public List<SearchIndexableResource> getXmlResourcesToIndex(
                            Context context, boolean enabled) {
                        final SearchIndexableResource sir = new SearchIndexableResource(context);
                        sir.xmlResId = R.xml.apps;
                        return Arrays.asList(sir);
                    }
    
                    @Override
                    public List<AbstractPreferenceController> createPreferenceControllers(
                            Context context) {
                        return buildPreferenceControllers(context);
                    }
                };
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    
    
    
    <PreferenceScreen
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:settings="http://schemas.android.com/apk/res-auto"
        android:key="apps_screen"
        android:title="@string/apps_dashboard_title">
    
        <Preference
            android:key="all_app_infos"
            android:title="@string/all_apps"
            android:summary="@string/summary_placeholder"
            android:order="-999"
            android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
            settings:keywords="@string/keywords_applications_settings"/>
    	
        
        <PreferenceCategory
            android:key="recent_apps_category"
            android:title="@string/recent_app_category_title"
            android:order="-998"
            settings:searchable="false">
            
    
            
            <Preference
                android:key="see_all_apps"
                android:title="@string/default_see_all_apps_title"
                android:icon="@drawable/ic_chevron_right_24dp"
                android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
                android:order="5"
                settings:searchable="false">
            Preference>
        PreferenceCategory>
    
        <PreferenceCategory
            android:key="general_category"
            android:title="@string/category_name_general"
            android:order="-997"
            android:visibility="gone"
            settings:searchable="false"/>
    
        <Preference
            android:key="default_apps"
            android:title="@string/app_default_dashboard_title"
            android:order="-996"
            settings:controller="com.android.settings.applications.DefaultAppsPreferenceController">
            <intent android:action="android.settings.MANAGE_DEFAULT_APPS_SETTINGS"/>
        Preference>
    
        <Preference
            android:key="game_settings"
            android:title="@string/game_settings_title"
            android:summary="@string/game_settings_summary"
            android:order="-995"
            settings:controller="com.android.settings.applications.GameSettingsPreferenceController">
        Preference>
    
        <PreferenceCategory
            android:key="dashboard_tile_placeholder"
            android:order="10"/>
    
        <Preference
            android:key="hibernated_apps"
            android:title="@string/unused_apps"
            android:summary="@string/summary_placeholder"
            android:order="15"
            settings:keywords="app_hibernation_key"
            settings:controller="com.android.settings.applications.HibernatedAppsPreferenceController">
            <intent android:action="android.intent.action.MANAGE_UNUSED_APPS"/>
        Preference>
    
        <Preference
            android:key="special_access"
            android:fragment="com.android.settings.applications.specialaccess.SpecialAccessSettings"
            android:title="@string/special_access"
            android:order="20"
            settings:controller="com.android.settings.applications.SpecialAppAccessPreferenceController"/>
    	
        
        <Preference
            android:key="parallel_app"
            android:fragment="com.android.settings.applications.parallelapp.ParallelAppSettings"
            android:title="@string/parallel_app"
            android:order="25"
            settings:controller="com.android.settings.applications.parallelapp.ParallelAppPreferenceController"/>
    PreferenceScreen>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102

    在这里插入图片描述

    在这里插入图片描述

    2、进入手机分身的fragment类

    ParallelAppSettings.java

    /*
     * Copyright (C) 2016 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.applications.parallelapp;
    
    import android.app.ActivityManager;
    import android.app.IActivityManager;
    import android.app.settings.SettingsEnums;
    import android.content.Context;
    import android.content.pm.UserInfo;
    import android.os.Bundle;
    import android.os.RemoteException;
    import android.os.UserHandle;
    import android.os.UserManager;
    import android.widget.Switch;
    import android.util.Log;
    
    import androidx.preference.PreferenceGroup;
    
    import com.android.settings.R;
    import com.android.settings.dashboard.DashboardFragment;
    import com.android.settings.SettingsActivity;
    import com.android.settingslib.applications.ApplicationsState;
    import com.android.settingslib.applications.ApplicationsState.AppFilter;
    
    import java.util.List;
    
    public class ParallelAppSettings extends DashboardFragment {
        private static final String TAG = "ParallelAppSettings";
        private static final String KEY = "app_list";
        private AppFilter mFilter;
        private int mCloneUserId = -1;
        private IActivityManager mAms;
        private UserManager mUm;
        PreferenceGroup mAppList;
    
        @Override
        public void onAttach(Context context) {
            super.onAttach(context);
            mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
                mFilter = ApplicationsState.FILTER_ALL_ENABLED;
            use(ManageParallelAppsPreferenceController.class).setSession(getSettingsLifecycle());
            use(ManageParallelAppsPreferenceController.class).setParentFragment(this);
            use(ManageParallelAppsPreferenceController.class).setFilter(mFilter);
            mAms = ActivityManager.getService();
        }
    
        @Override
        public void onCreate(Bundle icicle) {
            super.onCreate(icicle);
            // 获取布局文件中PreferenceCategory中key
            mAppList = (PreferenceGroup) findPreference(KEY);
            android.util.Log.d("xin.wang", " Content of mAppList : " + mAppList.getPreferenceCount());
            // 视图反射进入ManageParallelAppsPreferenceController,设置setPreferenceGroup
            use(ManageParallelAppsPreferenceController.class).setPreferenceGroup(mAppList);
        }
    
        @Override
        public void onResume() {
            super.onResume();
            use(ManageParallelAppsPreferenceController.class).rebuild();
        }
    
        @Override
        protected String getLogTag() {
            return TAG;
        }
    
        @Override
        protected int getPreferenceScreenResId() {
            return R.xml.parallel_app_settings;
        }
    
        @Override
        public int getMetricsCategory() {
            return SettingsEnums.PAGE_UNKNOWN;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89

    user()方法,是父类DashboardFragment的方法

     protected <T extends AbstractPreferenceController> T use(Class<T> clazz) {
             List<AbstractPreferenceController> controllerList = mPreferenceControllers.get(clazz);
              if (controllerList != null) {
                  if (controllerList.size() > 1) {
                      Log.w(TAG, "Multiple controllers of Class " + clazz.getSimpleName()
                              + " found, returning first one.");
                  }
                  return (T) controllerList.get(0);
              }
      
              return null;
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    进入布局文件parallel_app_settings.xml

    <PreferenceScreen
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:settings="http://schemas.android.com/apk/res-auto"
        android:key="parallel_app_settings"
        android:title="@string/parallel_app"
        settings:controller="com.android.settings.applications.parallelapp.ManageParallelAppsPreferenceController"
        settings:searchable="false">
    
        <com.android.settingslib.widget.TopIntroPreference
             android:key="support_app"
             android:title="@string/parallel_app_support"/>
    
        <PreferenceCategory
            android:key="app_list"
            android:order="10"
            settings:searchable="false">
        PreferenceCategory>
    
    PreferenceScreen>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    进入ManageParallelAppsPreferenceController

    /*
     * Copyright (C) 2017 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.applications.parallelapp;
    
    import android.app.ActivityManager;
    import android.app.Application;
    import android.content.Context;
    import android.content.pm.PackageInstaller;
    import android.content.pm.PackageManager;
    import android.os.ServiceManager;
    import android.os.UserHandle;
    import android.os.UserManager;
    
    import androidx.preference.Preference;
    import androidx.preference.PreferenceScreen;
    import androidx.preference.PreferenceGroup;
    
    import com.android.settings.applications.AppStateBaseBridge;
    import com.android.settings.core.BasePreferenceController;
    import com.android.settings.dashboard.DashboardFragment;
    import com.android.settings.R;
    import com.android.settings.Utils;
    import com.android.settingslib.applications.ApplicationsState;
    import com.android.settingslib.applications.ApplicationsState.AppEntry;
    import com.android.settingslib.applications.ApplicationsState.AppFilter;
    import com.android.settingslib.core.lifecycle.Lifecycle;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashSet;
    import java.util.Set;
    import java.util.TreeSet;
    
    public class ManageParallelAppsPreferenceController extends BasePreferenceController implements
            ApplicationsState.Callbacks, Preference.OnPreferenceChangeListener {
        private static final String TAG = "ManageParallelAppsPreferenceController";
        private final ApplicationsState mApplicationsState;
        private final PackageInstaller mPackageInstaller;
        private final PackageManager mPm;
        private final UserManager mUm;
        private ApplicationsState.Session mSession;
        private AppFilter mFilter;
        private Context mContext;
        private ParallelAppSettings mParentFragment;
        private HashSet<String> mSupportAppClone;
        PreferenceGroup mAppList;
    
        public ManageParallelAppsPreferenceController(Context context, String key) {
            super(context, key);
    
            mContext = context;
            mApplicationsState = ApplicationsState.getInstance(
                    (Application) context.getApplicationContext());
            mPm = mContext.getPackageManager();
            mPackageInstaller = mPm.getPackageInstaller();
            mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
            //get app could cloning by -> com.tencent.mm=>微信,com.sina.weibo=>微博,com.tencent.mobilqq=>QQ,com.ss.android.ugc.aweme=>抖音
            // 读取支持手机分身的应用包名
            String[] supportApps = context.getResources().getStringArray(com.unisoc.internal.R.array.support_app_clone);
            // 将数组转化为列表
            mSupportAppClone = new HashSet<String>(Arrays.asList(supportApps));
        }
    
        @Override
        public int getAvailabilityStatus() {
            ActivityManager activityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
            boolean isAdmin = mUm.isAdminUser();
            boolean isLowRam = activityManager.isLowRamDevice();
            boolean isSupportAppClone = mContext.getResources().getBoolean(R.bool.config_support_appclone);
    
            return isAdmin && !isLowRam && isSupportAppClone ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
        }
    
        @Override
        public void onRebuildComplete(ArrayList<AppEntry> apps) {
            if (apps == null) {
                return;
            }
    
            final Set<String> appsKeySet = new TreeSet<>();
            final int N = apps.size();
            android.util.Log.d("xin.wang", "apps.size -> " + N);
            for (int i = 0; i < N; i++) {
                final AppEntry entry = apps.get(i);
                android.util.Log.d("xin.wang", "AppEntry entry --> " + entry.toString());
                boolean isSupportClone = mSupportAppClone.contains(entry.info.packageName);
                android.util.Log.d("xin.wang", "get Should Clone for clone --> " + mSupportAppClone);
                android.util.Log.d("xin.wang", "get app packageName : -> " + entry.info.packageName + "<- isSupportClone ->" + isSupportClone );
                int userId = UserHandle.getUserId(entry.info.uid);
                boolean isAdminUser = mUm.isUserAdmin(userId);
    
                if (mSupportAppClone.contains(entry.info.packageName) && isAdminUser) {
                    if (!shouldAddPreference(entry)) {
                        continue;
                    }
                    final String prefkey = ParallelAppPreference.generateKey(entry);
                    appsKeySet.add(prefkey);
                    android.util.Log.d("xin.wang", " get appsKeySet -> " + appsKeySet + "<- prefkey ->" + prefkey);
                    // 获取布局中key
                    ParallelAppPreference preference =
                            (ParallelAppPreference) mAppList.findPreference(prefkey);
                    // 当布局为空的时候,实例化一个布局
                    if (preference == null) {
                        preference = new ParallelAppPreference(mContext, entry,
                                mApplicationsState, mUm, mPm, mPackageInstaller);
                        preference.setOnPreferenceChangeListener(this);
                        mAppList.addPreference(preference);
                    } else {
                        preference.updateState();
                    }
                    preference.setOrder(i);
                }
            }
    
            removeUselessPrefs(appsKeySet);
        }
    
        @Override
        public void onRunningStateChanged(boolean running) {}
    
        @Override
        public void onPackageListChanged() {
            rebuild();
        }
    
        @Override
        public void onPackageIconChanged() {}
    
        @Override
        public void onPackageSizeChanged(String packageName) {}
    
        @Override
        public void onAllSizesComputed() {}
    
        @Override
        public void onLauncherInfoChanged() {}
    
        @Override
        public void onLoadEntriesCompleted() {
            rebuild();
        }
    
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            if (Utils.isMonkeyRunning()) {
                return true;
            }
            if (preference instanceof ParallelAppPreference) {
                ParallelAppPreference parAppPreference = (ParallelAppPreference)preference;
                if ((Boolean)newValue) {
                    parAppPreference.openParApp();
                } else {
                    parAppPreference.createCloseOptionsDialog(mParentFragment.getActivity());
                }
            }
            return true;
        }
    
        public void setFilter(AppFilter filter) {
            mFilter = filter;
        }
    
        public void setSession(Lifecycle lifecycle) {
            mSession = mApplicationsState.newSession(this, lifecycle);
        }
    
        public void setParentFragment(ParallelAppSettings parentFragment) {
            mParentFragment = parentFragment;
        }
    
        public void setPreferenceGroup(PreferenceGroup appList) {
            mAppList = appList;
            android.util.Log.d("xin.wang", "setPreferenceGroup: -> appList -> " + appList.getPreferenceCount());
        }
    
        private boolean shouldAddPreference(AppEntry app) {
            return app != null && UserHandle.isApp(app.info.uid);
        }
    
        private void removeUselessPrefs(final Set<String> appsKeySet) {
            final int prefCount = mAppList.getPreferenceCount();
            android.util.Log.d("xin.wang", "<- prefCount ->  " + prefCount);
            String prefKey;
            if (prefCount > 0) {
                for (int i = prefCount - 1; i >= 0; i--) {
                    Preference pref = mAppList.getPreference(i);
                    prefKey = pref.getKey();
                    boolean isEmpty = !appsKeySet.isEmpty();
                    boolean contains = appsKeySet.contains(prefKey);
                    android.util.Log.d("xin.wang", "<- isEmpty -> " + isEmpty + "<- contains -> " + contains + "<- appsKeySet -> " + appsKeySet + "<- preKey ->" + prefKey);
                    if (!appsKeySet.isEmpty() && appsKeySet.contains(prefKey)) {
                        continue;
                    }
                    mAppList.removePreference(pref);
                }
            }
        }
    
        public void rebuild() {
            final ArrayList<AppEntry> apps = mSession.rebuild(mFilter,
                    ApplicationsState.ALPHA_COMPARATOR);
            boolean flag = apps != null;
            if (apps != null) {
                android.util.Log.d("xin.wang", "rebuild: <-- apps -> " + apps.size());
                onRebuildComplete(apps);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222

    进入分身的布局ParallelAppPreference.java

    点击swicth开启分身的时候创建一个Toast来提醒
    在这里插入图片描述

    关闭分身弹出dialog,判断是否进行关闭

    在这里插入图片描述

    /*
     * Copyright (C) 2017 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.applications.parallelapp;
    
    import android.app.Activity;
    import android.app.ActivityManager;
    import android.app.IActivityManager;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.content.pm.ApplicationInfo;
    import android.content.pm.IPackageManager;
    import android.content.pm.PackageInstaller;
    import android.content.pm.PackageManager;
    import android.content.pm.PackageManager.NameNotFoundException;
    import android.content.pm.UserInfo;
    import android.os.RemoteException;
    import android.os.ServiceManager;
    import android.os.UserHandle;
    import android.os.UserManager;
    import android.util.Log;
    import android.view.View;
    import android.widget.Toast;
    
    import androidx.appcompat.app.AlertDialog;
    import androidx.preference.DialogPreference;
    import androidx.preference.PreferenceViewHolder;
    
    import com.android.settings.R;
    import com.android.settingslib.applications.ApplicationsState;
    import com.android.settingslib.applications.ApplicationsState.AppEntry;
    import com.android.settingslib.widget.AppSwitchPreference;
    
    import java.util.List;
    
    public class ParallelAppPreference extends AppSwitchPreference {
        private final ApplicationsState mApplicationsState;
        private final AppEntry mEntry;
        private final PackageInstaller mPackageInstaller;
        private final PackageManager mPm;
        private final String TAG = "ParallelAppPreference";
        private final UserManager mUm;
        private Activity mActivity;
        private Context mContext;
    
        public ParallelAppPreference (final Context context, AppEntry entry,
                ApplicationsState applicationsState, UserManager um, PackageManager pm, PackageInstaller pi) {
            super(context);
            mContext = context;
            setWidgetLayoutResource(R.layout.restricted_switch_widget);
            mEntry = entry;
            mEntry.ensureLabel(context);
            mApplicationsState = applicationsState;
            mPm = pm;
            mPackageInstaller = pi;
            mUm = um;
            setKey(generateKey(mEntry));
            if (mEntry.icon == null) {
                mApplicationsState.ensureIcon(mEntry);
            }
            setIcon(mEntry.icon);
            setTitle(mEntry.label);
            updateState();
        }
    
        static String generateKey(final AppEntry entry) {
            android.util.Log.d("xin.wang", "generateKey: -> AppEntry ->  " + entry.info.packageName + " | " + entry.info.uid);
            return entry.info.packageName + "|" + entry.info.uid;
        }
    
        @Override
        public void onBindViewHolder(PreferenceViewHolder holder) {
            if (mEntry.icon == null) {
                holder.itemView.post(new Runnable() {
                    @Override
                    public void run() {
                        mApplicationsState.ensureIcon(mEntry);
                        setIcon(mEntry.icon);
                    }
                });
            }
            final View widgetFrame = holder.findViewById(android.R.id.widget_frame);
            widgetFrame.setVisibility(View.VISIBLE);
            super.onBindViewHolder(holder);
    
            holder.findViewById(R.id.restricted_icon).setVisibility(View.GONE);
            holder.findViewById(android.R.id.switch_widget).setVisibility(View.VISIBLE);
        }
    	
        // 更新状态
        public void updateState() {
            boolean isChecked = false;
            boolean hasCloneUser = hasCloneUser();
            try {
                if (hasCloneUser) {
                    ApplicationInfo info = mPm.getApplicationInfoAsUser(
                                    mEntry.info.packageName, PackageManager.GET_META_DATA, getCloneUser());
                    isChecked = (info.flags & ApplicationInfo.FLAG_INSTALLED) != 0 ? true : false;
                    android.util.Log.d("xin.wang", "updateState -> 1 -> : " + isChecked);
                }
                android.util.Log.d("xin.wang", "updateState -> 2 -> : " + isChecked);
                setChecked(isChecked);
            } catch (NameNotFoundException e) {
                 Log.e(TAG,"can not found Application "+mEntry.label);
            }
        }
        //关闭应用分身的时候弹出的dialog -> parallel_app_close -> 当关闭时分身应用的所有数据将会被清除。您确定要继续吗?
        public void createCloseOptionsDialog(Activity activity) {
            mActivity = activity;
            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
            builder.setMessage(mContext.getResources().getString(R.string.parallel_app_close));
            builder.setPositiveButton(android.R.string.ok, mDialogClickListener);
            builder.setNegativeButton(android.R.string.cancel, mDialogClickListener);
            AlertDialog dialog = builder.create();
            dialog.setCancelable(false);
            dialog.show();
        }
    	
        // 开始手机分身
        public void openParApp() {
            if (!hasCloneUser()) {
                createAndStartCloneUser();
            }
            try {
                //应用双开的方法 -> installExistingPackageAsUser(String packageName,int userId);
                int status = mPm.installExistingPackageAsUser(mEntry.info.packageName, getCloneUser());
                android.util.Log.d("xin.wang", "openParApp: -> status -> " + status + "<- mEntry.info.packageName -> " + mEntry.info.packageName);
                if (status == PackageManager.INSTALL_SUCCEEDED) {   //PackageManager.INSTALL_SUCCEEDED -> 返回安装成功的状态码 1
                    android.util.Log.d("xin.wang", "openParApp: -> status -> " + status);
                    createToast();
                } else {
                    Log.d(TAG, "open Parallel App failed status:"+status);
                }
            } catch (PackageManager.NameNotFoundException e) {
                Log.d(TAG, "open Parallel App failed ,"+e);
            }
        }
    
        // 创建开启分身的Toast -> 分身的 %1$s 已经创建
        private void createToast() {
            String content = String.format(mContext.getResources().getString(R.string.parallel_app_open), mEntry.label);
            Toast.makeText(mContext, content, Toast.LENGTH_LONG).show();
        }
    	
        // 获取克隆的用户
        private int getCloneUser() {
            int cloneUserId = UserHandle.myUserId();
            int userCount = 0;
            List<UserInfo> users = mUm.getUsers();  //UserManager.getUser() -> 获取所有的用户信息
            for(UserInfo user : users){
                userCount++;
                android.util.Log.d("xin.wang", "getCloneUser: users -> " + userCount);
                if (user.userType != null && user.userType.equals(UserManager.USER_TYPE_PROFILE_CLONE)) {
                    cloneUserId = user.id;
                }
            }
            return cloneUserId;
        }
    	
        //判断是否克隆
        private boolean hasCloneUser() {
            boolean hasCloneUser = false;
            List<UserInfo> users = mUm.getUsers();  // UserManager.getUsers() -> 获取所有的用户信息
            android.util.Log.d("xin.wang", "hasCloneUser: -> user -> " + users + "<- user.size() -> " + users.size());
            for(UserInfo user : users){
                android.util.Log.d("xin.wang", "hasCloneUser: -> user.userType -> " + user.userType);
                if (user.userType != null && user.userType.equals(UserManager.USER_TYPE_PROFILE_CLONE)) {
                    hasCloneUser = true;
                    break;
                }
            }
            return hasCloneUser;
        }
    	
        //创建第二个user用户
        private void createAndStartCloneUser() {
            String userName = mContext.getResources().getString(R.string.clone_user);
            UserInfo userInfo = mUm.createProfileForUser(userName, UserManager.USER_TYPE_PROFILE_CLONE,
                    UserInfo.FLAG_PROFILE, UserHandle.USER_SYSTEM);
            IActivityManager ams = ActivityManager.getService();
            try {
                ams.startUserInBackground(userInfo.getUserHandle().getIdentifier());
            } catch(RemoteException e) {
                Log.d(TAG, "create and start clone user failed");
                e.printStackTrace();
            }
        }
    	
        //关闭手机分身的时候弹出的dialog
        private DialogInterface.OnClickListener mDialogClickListener = new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface arg0, int arg1) {
                if (arg1 == DialogInterface.BUTTON_NEGATIVE) { //DialogInterface.BUTTON_NEGATIVE -> 取消按钮,点击dialog的取消按钮
                    setChecked(true);
                } else {
                    //deletePackageAsUser(String packageName,IPackageDeleteObserver observer,int Flags,int userId);
                    mPm.deletePackageAsUser(mEntry.info.packageName, null, 0, getCloneUser());
                    android.util.Log.d("xin.wang", "DialogInterface.OnClickListener ->  mEntry.info.packageName -> " + mEntry.info.packageName);
                }
            }
        };
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215

    3、计算应用界面中应用的数量

    在这里插入图片描述

    通过该界面的布局文件app.xml中的key-> recent_apps_category

    进入AppsPreferenceController.java类中,该类计算当前应用的数量,并且显示当前使用的应用数量

    通过分析,可知,该方法中的loadAllAppsCount()加载所有app的数量,该方法实例化InstalledAppCounter类,并重写onCountComplete()方法

    /*
     * Copyright (C) 2021 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.applications;
    
    import android.app.Application;
    import android.app.usage.UsageStats;
    import android.content.Context;
    import android.icu.text.RelativeDateTimeFormatter;
    import android.os.UserHandle;
    import android.text.TextUtils;
    import android.util.ArrayMap;
    
    import androidx.annotation.VisibleForTesting;
    import androidx.fragment.app.Fragment;
    import androidx.lifecycle.Lifecycle;
    import androidx.lifecycle.LifecycleObserver;
    import androidx.lifecycle.OnLifecycleEvent;
    import androidx.preference.Preference;
    import androidx.preference.PreferenceCategory;
    import androidx.preference.PreferenceScreen;
    
    import com.android.settings.R;
    import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
    import com.android.settings.core.BasePreferenceController;
    import com.android.settingslib.Utils;
    import com.android.settingslib.applications.ApplicationsState;
    import com.android.settingslib.utils.StringUtil;
    import com.android.settingslib.widget.AppPreference;
    
    import java.util.List;
    import java.util.Map;
    
    /**
     * This controller displays up to four recently used apps.
     * If there is no recently used app, we only show up an "App Info" preference.
     */
    public class AppsPreferenceController extends BasePreferenceController implements
            LifecycleObserver {
    
        public static final int SHOW_RECENT_APP_COUNT = 4;
    
        @VisibleForTesting
        static final String KEY_RECENT_APPS_CATEGORY = "recent_apps_category";
        @VisibleForTesting
        static final String KEY_GENERAL_CATEGORY = "general_category";
        @VisibleForTesting
        static final String KEY_ALL_APP_INFO = "all_app_infos";
        @VisibleForTesting
        static final String KEY_SEE_ALL = "see_all_apps";
    
        private final ApplicationsState mApplicationsState;
        private final int mUserId;
    
        @VisibleForTesting
        List<UsageStats> mRecentApps;
        @VisibleForTesting
        PreferenceCategory mRecentAppsCategory;
        @VisibleForTesting
        PreferenceCategory mGeneralCategory;
        @VisibleForTesting
        Preference mAllAppsInfoPref;
        @VisibleForTesting
        Preference mSeeAllPref;
    
        private Fragment mHost;
        private boolean mInitialLaunch = false;
    
        public AppsPreferenceController(Context context) {
            super(context, KEY_RECENT_APPS_CATEGORY);
            mApplicationsState = ApplicationsState.getInstance(
                    (Application) mContext.getApplicationContext());
            mUserId = UserHandle.myUserId();
        }
    
        public void setFragment(Fragment fragment) {
            mHost = fragment;
        }
    
        @Override
        public int getAvailabilityStatus() {
            return AVAILABLE_UNSEARCHABLE;
        }
    
        @Override
        public void displayPreference(PreferenceScreen screen) {
            super.displayPreference(screen);
            initPreferences(screen);
            refreshUi();
            mInitialLaunch = true;
        }
    
        @Override
        public void updateState(Preference preference) {
            super.updateState(preference);
            if (!mInitialLaunch) {
                refreshUi();
            }
        }
    
        /**
         * Called when the apps page pauses.
         */
        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        public void onPause() {
            mInitialLaunch = false;
        }
    
        @VisibleForTesting
        void refreshUi() {
            loadAllAppsCount();
            mRecentApps = loadRecentApps();
            android.util.Log.d("xin.wang", "mRecentApps -> : " + mRecentApps.size() + "<- loadAllAppsCount -> " + loadRecentApps());
            if (!mRecentApps.isEmpty()) {
                displayRecentApps();
                mAllAppsInfoPref.setVisible(false);
                mRecentAppsCategory.setVisible(true);
                mGeneralCategory.setVisible(true);
                mSeeAllPref.setVisible(true);
            } else {
                mAllAppsInfoPref.setVisible(true);
                mRecentAppsCategory.setVisible(false);
                mGeneralCategory.setVisible(false);
                mSeeAllPref.setVisible(false);
            }
        }
    	
        // 计算应用的数量
        @VisibleForTesting
        void loadAllAppsCount() {
            // Show total number of installed apps as See all's summary.
            new InstalledAppCounter(mContext, InstalledAppCounter.IGNORE_INSTALL_REASON,
                    mContext.getPackageManager()) {
                @Override
                protected void onCountComplete(int num) {
                    if (!mRecentApps.isEmpty()) {
                        mSeeAllPref.setTitle(
                                mContext.getResources().getQuantityString(R.plurals.see_all_apps_title,
                                        num, num));
                        android.util.Log.d("xin.wang", "onCountComplete: -> AppsCount -> " + num);
                    } else {
                        mAllAppsInfoPref.setSummary(mContext.getString(R.string.apps_summary, num));
                    }
                }
            }.execute();
        }
    
        @VisibleForTesting
        List<UsageStats> loadRecentApps() {
            final RecentAppStatsMixin recentAppStatsMixin = new RecentAppStatsMixin(mContext,
                    SHOW_RECENT_APP_COUNT);
            recentAppStatsMixin.loadDisplayableRecentApps(SHOW_RECENT_APP_COUNT);
            return recentAppStatsMixin.mRecentApps;
        }
    
        private void initPreferences(PreferenceScreen screen) {
            mRecentAppsCategory = screen.findPreference(KEY_RECENT_APPS_CATEGORY);
            mGeneralCategory = screen.findPreference(KEY_GENERAL_CATEGORY);
            mAllAppsInfoPref = screen.findPreference(KEY_ALL_APP_INFO);
            mSeeAllPref = screen.findPreference(KEY_SEE_ALL);
            mRecentAppsCategory.setVisible(false);
            mGeneralCategory.setVisible(false);
            mAllAppsInfoPref.setVisible(false);
            mSeeAllPref.setVisible(false);
        }
    
        private void displayRecentApps() {
            if (mRecentAppsCategory != null) {
                final Map<String, Preference> existedAppPreferences = new ArrayMap<>();
                final int prefCount = mRecentAppsCategory.getPreferenceCount();
                android.util.Log.d("xin.wang", "<- prefCount -> : " + prefCount);
                for (int i = 0; i < prefCount; i++) {
                    final Preference pref = mRecentAppsCategory.getPreference(i);
                    final String key = pref.getKey();
                   // android.util.Log.d("xin.wang", "for each key -> : " + key);
                    if (!TextUtils.equals(key, KEY_SEE_ALL)) {
                        existedAppPreferences.put(key, pref);
                    }
                    android.util.Log.d("xin.wang", "<- Map -> " + existedAppPreferences);
                }
    
                int showAppsCount = 0;
                android.util.Log.d("xin.wang", "List mRecentApps -> : " + mRecentApps);
                for (UsageStats stat : mRecentApps) {
                    final String pkgName = stat.getPackageName();
                    final ApplicationsState.AppEntry appEntry =
                            mApplicationsState.getEntry(pkgName, mUserId);
                    if (appEntry == null) {
                        continue;
                    }
    
                    boolean rebindPref = true;
                    Preference pref = existedAppPreferences.remove(pkgName);
                    if (pref == null) {
                        pref = new AppPreference(mContext);
                        rebindPref = false;
                    }
    
                    android.util.Log.d("xin.wang", "pkgName -> : " + pkgName + "<- appEntry.label -> : " + appEntry.label + "<- pref -> " + pref);
                    pref.setKey(pkgName);
                    pref.setTitle(appEntry.label);
                    pref.setIcon(Utils.getBadgedIcon(mContext, appEntry.info));
                    pref.setSummary(StringUtil.formatRelativeTime(mContext,
                            System.currentTimeMillis() - stat.getLastTimeUsed(), false,
                            RelativeDateTimeFormatter.Style.SHORT));
                    pref.setOrder(showAppsCount++);
                    pref.setOnPreferenceClickListener(preference -> {
                        AppInfoBase.startAppInfoFragment(AppInfoDashboardFragment.class,
                                R.string.application_info_label, pkgName, appEntry.info.uid,
                                mHost, 1001 /*RequestCode*/, getMetricsCategory());
                        return true;
                    });
    
                    if (!rebindPref) {
                        mRecentAppsCategory.addPreference(pref);
                    }
                }
    
                // Remove unused preferences from pref category.
                for (Preference unusedPref : existedAppPreferences.values()) {
                    mRecentAppsCategory.removePreference(unusedPref);
                }
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238

    进入超父类AppCounter.java

    doInBackground方法进行计算总数量,该计算方法,通过遍历用户和应用双重遍历进行计算,所以算出来的数量double,所以在doInBackground(Void... params)中,只获取第一个用户,在进行遍历应用

    /*
     * Copyright (C) 2016 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.applications;
    
    import android.content.Context;
    import android.content.pm.ApplicationInfo;
    import android.content.pm.PackageManager;
    import android.content.pm.UserInfo;
    import android.os.AsyncTask;
    import android.os.UserHandle;
    import android.os.UserManager;
    
    import java.util.List;
    
    public abstract class AppCounter extends AsyncTask<Void, Void, Integer> {
    
        protected final PackageManager mPm;
        protected final UserManager mUm;
    
        public AppCounter(Context context, PackageManager packageManager) {
            mPm = packageManager;
            mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
        }
    
        @Override
        protected Integer doInBackground(Void... params) {
            //int count = 0;
            //int testNum = 0;
            //int testNum2 = 0;
            //android.util.Log.d("xin.wang", "doInBackground:UserInfo-> " + testNum);
            UserInfo user = mUm.getProfiles(UserHandle.myUserId()).get(0);
            final List<ApplicationInfo> list =
                    mPm.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
                                    | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
                                    | (user.isAdmin() ? PackageManager.MATCH_ANY_USER : 0),
                            user.id);
            for (ApplicationInfo info : list) {
                //testNum2 ++;
                //android.util.Log.d("xin.wang", "doInBackground: ApplicationInfo -> " + testNum2);
                if (includeInCount(info)) {
                    count++;
                    //android.util.Log.d("xin.wang", "doInBackground: includeInCount -> " + count);
                }
            }
            /*for (UserInfo user : mUm.getProfiles(UserHandle.myUserId())) {
                testNum ++ ;
                android.util.Log.d("xin.wang", "doInBackground:UserInfo-> " + testNum);
                final List list =
                        mPm.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
                                | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
                                | (user.isAdmin() ? PackageManager.MATCH_ANY_USER : 0),
                                user.id);
                for (ApplicationInfo info : list) {
                    testNum2 ++;
                    android.util.Log.d("xin.wang", "doInBackground: ApplicationInfo -> " + testNum2);
                    if (includeInCount(info)) {
                        count++;
                        android.util.Log.d("xin.wang", "doInBackground: includeInCount -> " + count);
                    }
                }
            }*/
            return count;
        }
    
        @Override
        protected void onPostExecute(Integer count) {
            onCountComplete(count);
        }
    
        void executeInForeground() {
            onPostExecute(doInBackground());
        }
    
        protected abstract void onCountComplete(int num);
        protected abstract boolean includeInCount(ApplicationInfo info);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    4、进入所有应用

    在这里插入图片描述

    该界面的方法ManageApplications.java类来显示应用图标和名字

    该类有两个内部类适配器

    FilterSpinnerAdapter-> SettingsSpinnerAdapter的适配器

    在这里插入图片描述

    ApplicationsAdapter-> RecyclerView的适配器

    在这里插入图片描述

    createHeader()在该方法中创建头部SpinnerHeader,关闭头部的时候只显示一个FILTER_APPS_PERSONAL的应用

     @VisibleForTesting
        void createHeader() {
            final Activity activity = getActivity();
            final FrameLayout pinnedHeader = mRootView.findViewById(R.id.pinned_header);
            mSpinnerHeader = activity.getLayoutInflater()
                    .inflate(R.layout.manage_apps_filter_spinner, pinnedHeader, false);
            mFilterSpinner = mSpinnerHeader.findViewById(R.id.filter_spinner);
            mFilterAdapter = new FilterSpinnerAdapter(this);
            mFilterSpinner.setAdapter(mFilterAdapter);
            mFilterSpinner.setOnItemSelectedListener(this);
            mFilterSpinner.setVisibility(View.GONE);
            pinnedHeader.addView(mSpinnerHeader, 0);
    
            final AppFilterRegistry appFilterRegistry = AppFilterRegistry.getInstance();
            final int filterType = appFilterRegistry.getDefaultFilterType(mListType);
            android.util.Log.d("xin.wang", "createHeader:-> filterType -> " + mListType + "<- filterType -> " + filterType); //filterType = 4 -> FILTER_APPS_ALL
            android.util.Log.d("xin.wang", "createHeader:->mFilterOptions.size()-> " + mFilterAdapter.getCount());
            //mFilterAdapter.enableFilter(filterType);    //filterType = 4 -> FILTER_APPS_ALL
    
            if (mListType == LIST_TYPE_MAIN) {
                if (UserManager.get(getActivity()).getUserProfiles().size() > 1 && !mIsWorkOnly
                        && !mIsPersonalOnly) {
                    mFilterAdapter.enableFilter(FILTER_APPS_PERSONAL);
                    //mFilterAdapter.enableFilter(FILTER_APPS_WORK);
                }
            }
    
            if (mListType == LIST_TYPE_NOTIFICATION) {
                mFilterAdapter.enableFilter(FILTER_APPS_RECENT);
                mFilterAdapter.enableFilter(FILTER_APPS_FREQUENT);
                mFilterAdapter.enableFilter(FILTER_APPS_BLOCKED);
                mFilterAdapter.enableFilter(FILTER_APPS_ALL);
            }
            if (mListType == LIST_TYPE_HIGH_POWER) {
                mFilterAdapter.enableFilter(FILTER_APPS_POWER_ALLOWLIST_ALL);
            }
    
            setCompositeFilter();
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    /*
     * Copyright (C) 2006 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.applications.manageapplications;
    
    import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
    
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_ALL;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_BLOCKED;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_DISABLED;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_ENABLED;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_FREQUENT;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_INSTANT;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_PERSONAL;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_POWER_ALLOWLIST;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_POWER_ALLOWLIST_ALL;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_RECENT;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_WORK;
    import static com.android.settings.search.actionbar.SearchMenuController.MENU_SEARCH;
    
    import android.annotation.Nullable;
    import android.annotation.StringRes;
    import android.app.Activity;
    import android.app.ActivityManager;
    import android.app.settings.SettingsEnums;
    import android.app.usage.IUsageStatsManager;
    import android.compat.annotation.ChangeId;
    import android.compat.annotation.LoggingOnly;
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.ApplicationInfo;
    import android.content.pm.PackageItemInfo;
    import android.content.pm.UserInfo;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.os.ServiceManager;
    import android.os.UserHandle;
    import android.os.UserManager;
    import android.preference.PreferenceFrameLayout;
    import android.text.TextUtils;
    import android.util.ArraySet;
    import android.util.IconDrawableFactory;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemSelectedListener;
    import android.widget.Filter;
    import android.widget.FrameLayout;
    import android.widget.SearchView;
    import android.widget.Spinner;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.VisibleForTesting;
    import androidx.annotation.WorkerThread;
    import androidx.coordinatorlayout.widget.CoordinatorLayout;
    import androidx.core.view.ViewCompat;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;
    
    import com.android.internal.compat.IPlatformCompat;
    import com.android.settings.R;
    import com.android.settings.Settings;
    import com.android.settings.Settings.GamesStorageActivity;
    import com.android.settings.Settings.HighPowerApplicationsActivity;
    import com.android.settings.Settings.ManageExternalSourcesActivity;
    import com.android.settings.Settings.OverlaySettingsActivity;
    import com.android.settings.Settings.StorageUseActivity;
    import com.android.settings.Settings.UsageAccessSettingsActivity;
    import com.android.settings.Settings.WriteSettingsActivity;
    import com.android.settings.SettingsActivity;
    import com.android.settings.Utils;
    import com.android.settings.applications.AppInfoBase;
    import com.android.settings.applications.AppStateAlarmsAndRemindersBridge;
    import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
    import com.android.settings.applications.AppStateBaseBridge;
    import com.android.settings.applications.AppStateInstallAppsBridge;
    import com.android.settings.applications.AppStateManageExternalStorageBridge;
    import com.android.settings.applications.AppStateMediaManagementAppsBridge;
    import com.android.settings.applications.AppStateNotificationBridge;
    import com.android.settings.applications.AppStateNotificationBridge.NotificationsSentState;
    import com.android.settings.applications.AppStateOverlayBridge;
    import com.android.settings.applications.AppStatePowerBridge;
    import com.android.settings.applications.AppStateUsageBridge;
    import com.android.settings.applications.AppStateUsageBridge.UsageState;
    import com.android.settings.applications.AppStateWriteSettingsBridge;
    import com.android.settings.applications.AppStorageSettings;
    import com.android.settings.applications.UsageAccessDetails;
    import com.android.settings.applications.appinfo.AlarmsAndRemindersDetails;
    import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
    import com.android.settings.applications.appinfo.DrawOverlayDetails;
    import com.android.settings.applications.appinfo.ExternalSourcesDetails;
    import com.android.settings.applications.appinfo.ManageExternalStorageDetails;
    import com.android.settings.applications.appinfo.MediaManagementAppsDetails;
    import com.android.settings.applications.appinfo.WriteSettingsDetails;
    import com.android.settings.core.InstrumentedFragment;
    import com.android.settings.core.SubSettingLauncher;
    import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
    import com.android.settings.fuelgauge.HighPowerDetail;
    import com.android.settings.notification.ConfigureNotificationSettings;
    import com.android.settings.notification.NotificationBackend;
    import com.android.settings.notification.app.AppNotificationSettings;
    import com.android.settings.widget.LoadingViewController;
    import com.android.settings.wifi.AppStateChangeWifiStateBridge;
    import com.android.settings.wifi.ChangeWifiStateDetails;
    import com.android.settingslib.applications.ApplicationsState;
    import com.android.settingslib.applications.ApplicationsState.AppEntry;
    import com.android.settingslib.applications.ApplicationsState.AppFilter;
    import com.android.settingslib.applications.ApplicationsState.CompoundFilter;
    import com.android.settingslib.applications.ApplicationsState.VolumeFilter;
    import com.android.settingslib.applications.AppUtils;
    import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
    import com.android.settingslib.utils.ThreadUtils;
    import com.android.settingslib.widget.settingsspinner.SettingsSpinnerAdapter;
    
    import com.google.android.material.appbar.AppBarLayout;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Set;
    import java.util.HashSet;
    
    /**
     * Activity to pick an application that will be used to display installation information and
     * options to uninstall/delete user data for system applications. This activity
     * can be launched through Settings or via the ACTION_MANAGE_PACKAGE_STORAGE
     * intent.
     */
    public class ManageApplications extends InstrumentedFragment
            implements View.OnClickListener, OnItemSelectedListener, SearchView.OnQueryTextListener,
            MenuItem.OnActionExpandListener {
    
        static final String TAG = "ManageApplications";
        static final boolean DEBUG = Build.IS_DEBUGGABLE;
    
        // Intent extras.
        public static final String EXTRA_CLASSNAME = "classname";
        // Used for storage only.
        public static final String EXTRA_VOLUME_UUID = "volumeUuid";
        public static final String EXTRA_VOLUME_NAME = "volumeName";
        public static final String EXTRA_STORAGE_TYPE = "storageType";
        public static final String EXTRA_WORK_ID = "workId";
    
        private static final String EXTRA_SORT_ORDER = "sortOrder";
        private static final String EXTRA_SHOW_SYSTEM = "showSystem";
        private static final String EXTRA_HAS_ENTRIES = "hasEntries";
        private static final String EXTRA_HAS_BRIDGE = "hasBridge";
        private static final String EXTRA_FILTER_TYPE = "filterType";
        @VisibleForTesting
        static final String EXTRA_EXPAND_SEARCH_VIEW = "expand_search_view";
    
        // attributes used as keys when passing values to AppInfoDashboardFragment activity
        public static final String APP_CHG = "chg";
    
        // constant value that can be used to check return code from sub activity.
        private static final int INSTALLED_APP_DETAILS = 1;
        private static final int ADVANCED_SETTINGS = 2;
    
        public static final int SIZE_TOTAL = 0;
        public static final int SIZE_INTERNAL = 1;
        public static final int SIZE_EXTERNAL = 2;
    
        // Storage types. Used to determine what the extra item in the list of preferences is.
        public static final int STORAGE_TYPE_DEFAULT = 0; // Show all apps that are not categorized.
        public static final int STORAGE_TYPE_LEGACY = 1;  // Show apps even if they can be categorized.
    
        /**
         * Intents with action {@code android.settings.MANAGE_APP_OVERLAY_PERMISSION}
         * and data URI scheme {@code package} don't go to the app-specific screen for managing the
         * permission anymore. Instead, they redirect to this screen for managing all the apps that have
         * requested such permission.
         */
        @ChangeId
        @LoggingOnly
        private static final long CHANGE_RESTRICT_SAW_INTENT = 135920175L;
    
        // sort order
        @VisibleForTesting
        int mSortOrder = R.id.sort_order_alpha;
    
        // whether showing system apps.
        private boolean mShowSystem;
    
        private ApplicationsState mApplicationsState;
    
        public int mListType;
        private AppFilterItem mFilter;
        private ApplicationsAdapter mApplications;
    
        private View mLoadingContainer;
        private SearchView mSearchView;
    
        // Size resource used for packages whose size computation failed for some reason
        CharSequence mInvalidSizeStr;
    
        private String mCurrentPkgName;
        private int mCurrentUid;
    
        private Menu mOptionsMenu;
    
        public static final int LIST_TYPE_MAIN = 0;
        public static final int LIST_TYPE_NOTIFICATION = 1;
        public static final int LIST_TYPE_STORAGE = 3;
        public static final int LIST_TYPE_USAGE_ACCESS = 4;
        public static final int LIST_TYPE_HIGH_POWER = 5;
        public static final int LIST_TYPE_OVERLAY = 6;
        public static final int LIST_TYPE_WRITE_SETTINGS = 7;
        public static final int LIST_TYPE_MANAGE_SOURCES = 8;
        public static final int LIST_TYPE_GAMES = 9;
        public static final int LIST_TYPE_WIFI_ACCESS = 10;
        public static final int LIST_MANAGE_EXTERNAL_STORAGE = 11;
        public static final int LIST_TYPE_ALARMS_AND_REMINDERS = 12;
        public static final int LIST_TYPE_MEDIA_MANAGEMENT_APPS = 13;
    
        // List types that should show instant apps.
        public static final Set LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
                LIST_TYPE_MAIN,
                LIST_TYPE_STORAGE));
    
        @VisibleForTesting
        View mSpinnerHeader;
        @VisibleForTesting
        FilterSpinnerAdapter mFilterAdapter;
        @VisibleForTesting
        RecyclerView mRecyclerView;
        // Whether or not search view is expanded.
        @VisibleForTesting
        boolean mExpandSearch;
    
        private View mRootView;
        private Spinner mFilterSpinner;
        private IUsageStatsManager mUsageStatsManager;
        private UserManager mUserManager;
        private NotificationBackend mNotificationBackend;
        private ResetAppsHelper mResetAppsHelper;
        private String mVolumeUuid;
        private int mStorageType;
        private boolean mIsWorkOnly;
        private int mWorkUserId;
        private boolean mIsPersonalOnly;
        private View mEmptyView;
        private int mFilterType;
        private AppBarLayout mAppBarLayout;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setHasOptionsMenu(true);
            final Activity activity = getActivity();
            mUserManager = activity.getSystemService(UserManager.class);
            mApplicationsState = ApplicationsState.getInstance(activity.getApplication());
    
            Intent intent = activity.getIntent();
            Bundle args = getArguments();
            int screenTitle = intent.getIntExtra(
                    SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, R.string.all_apps);
            String className = args != null ? args.getString(EXTRA_CLASSNAME) : null;
            if (className == null) {
                className = intent.getComponent().getClassName();
            }
            if (className.equals(StorageUseActivity.class.getName())) {
                if (args != null && args.containsKey(EXTRA_VOLUME_UUID)) {
                    mVolumeUuid = args.getString(EXTRA_VOLUME_UUID);
                    mStorageType = args.getInt(EXTRA_STORAGE_TYPE, STORAGE_TYPE_DEFAULT);
                    mListType = LIST_TYPE_STORAGE;
                } else {
                    // No volume selected, display a normal list, sorted by size.
                    mListType = LIST_TYPE_MAIN;
                }
                mSortOrder = R.id.sort_order_size;
            } else if (className.equals(UsageAccessSettingsActivity.class.getName())) {
                mListType = LIST_TYPE_USAGE_ACCESS;
                screenTitle = R.string.usage_access;
            } else if (className.equals(HighPowerApplicationsActivity.class.getName())) {
                mListType = LIST_TYPE_HIGH_POWER;
                // Default to showing system.
                mShowSystem = true;
                screenTitle = R.string.high_power_apps;
            } else if (className.equals(OverlaySettingsActivity.class.getName())) {
                mListType = LIST_TYPE_OVERLAY;
                screenTitle = R.string.system_alert_window_settings;
    
                reportIfRestrictedSawIntent(intent);
            } else if (className.equals(WriteSettingsActivity.class.getName())) {
                mListType = LIST_TYPE_WRITE_SETTINGS;
                screenTitle = R.string.write_settings;
            } else if (className.equals(ManageExternalSourcesActivity.class.getName())) {
                mListType = LIST_TYPE_MANAGE_SOURCES;
                screenTitle = R.string.install_other_apps;
            } else if (className.equals(GamesStorageActivity.class.getName())) {
                mListType = LIST_TYPE_GAMES;
                mSortOrder = R.id.sort_order_size;
            } else if (className.equals(Settings.ChangeWifiStateActivity.class.getName())) {
                mListType = LIST_TYPE_WIFI_ACCESS;
                screenTitle = R.string.change_wifi_state_title;
            } else if (className.equals(Settings.ManageExternalStorageActivity.class.getName())) {
                mListType = LIST_MANAGE_EXTERNAL_STORAGE;
                screenTitle = R.string.manage_external_storage_title;
            }  else if (className.equals(Settings.MediaManagementAppsActivity.class.getName())) {
                mListType = LIST_TYPE_MEDIA_MANAGEMENT_APPS;
                screenTitle = R.string.media_management_apps_title;
            } else if (className.equals(Settings.AlarmsAndRemindersActivity.class.getName())) {
                mListType = LIST_TYPE_ALARMS_AND_REMINDERS;
                screenTitle = R.string.alarms_and_reminders_title;
            } else if (className.equals(Settings.NotificationAppListActivity.class.getName())) {
                mListType = LIST_TYPE_NOTIFICATION;
                mUsageStatsManager = IUsageStatsManager.Stub.asInterface(
                        ServiceManager.getService(Context.USAGE_STATS_SERVICE));
                mNotificationBackend = new NotificationBackend();
                mSortOrder = R.id.sort_order_recent_notification;
                screenTitle = R.string.app_notifications_title;
            } else {
                if (screenTitle == -1) {
                    screenTitle = R.string.all_apps;
                }
                mListType = LIST_TYPE_MAIN;
            }
            final AppFilterRegistry appFilterRegistry = AppFilterRegistry.getInstance();
            mFilter = appFilterRegistry.get(appFilterRegistry.getDefaultFilterType(mListType));
            mIsPersonalOnly = args != null ? args.getInt(ProfileSelectFragment.EXTRA_PROFILE)
                    == ProfileSelectFragment.ProfileType.PERSONAL : false;
            mIsWorkOnly = args != null ? args.getInt(ProfileSelectFragment.EXTRA_PROFILE)
                    == ProfileSelectFragment.ProfileType.WORK : false;
            mWorkUserId = args != null ? args.getInt(EXTRA_WORK_ID) : UserHandle.myUserId();
            if (mIsWorkOnly && mWorkUserId == UserHandle.myUserId()) {
                mWorkUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
            }
    
            mExpandSearch = activity.getIntent().getBooleanExtra(EXTRA_EXPAND_SEARCH_VIEW, false);
    
            if (savedInstanceState != null) {
                mSortOrder = savedInstanceState.getInt(EXTRA_SORT_ORDER, mSortOrder);
                mShowSystem = savedInstanceState.getBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
                mFilterType =
                        savedInstanceState.getInt(EXTRA_FILTER_TYPE, AppFilterRegistry.FILTER_APPS_ALL);
                mExpandSearch = savedInstanceState.getBoolean(EXTRA_EXPAND_SEARCH_VIEW);
            }
    
            mInvalidSizeStr = activity.getText(R.string.invalid_size_value);
    
            mResetAppsHelper = new ResetAppsHelper(activity);
    
            if (screenTitle > 0) {
                activity.setTitle(screenTitle);
            }
        }
    
        private void reportIfRestrictedSawIntent(Intent intent) {
            try {
                Uri data = intent.getData();
                if (data == null || !TextUtils.equals("package", data.getScheme())) {
                    // Not a restricted intent
                    return;
                }
                IBinder activityToken = getActivity().getActivityToken();
                int callingUid = ActivityManager.getService().getLaunchedFromUid(activityToken);
                if (callingUid == -1) {
                    Log.w(TAG, "Error obtaining calling uid");
                    return;
                }
                IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
                        ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
                if (platformCompat == null) {
                    Log.w(TAG, "Error obtaining IPlatformCompat service");
                    return;
                }
                platformCompat.reportChangeByUid(CHANGE_RESTRICT_SAW_INTENT, callingUid);
            } catch (RemoteException e) {
                Log.w(TAG, "Error reporting SAW intent restriction", e);
            }
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            if (mListType == LIST_TYPE_OVERLAY && !Utils.isSystemAlertWindowEnabled(getContext())) {
                mRootView = inflater.inflate(R.layout.manage_applications_apps_unsupported, null);
                setHasOptionsMenu(false);
                return mRootView;
            }
    
            mRootView = inflater.inflate(R.layout.manage_applications_apps, null);
            mLoadingContainer = mRootView.findViewById(R.id.loading_container);
            mEmptyView = mRootView.findViewById(android.R.id.empty);
            mRecyclerView = mRootView.findViewById(R.id.apps_list);
    
            mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter,
                    savedInstanceState);
            if (savedInstanceState != null) {
                mApplications.mHasReceivedLoadEntries =
                        savedInstanceState.getBoolean(EXTRA_HAS_ENTRIES, false);
                mApplications.mHasReceivedBridgeCallback =
                        savedInstanceState.getBoolean(EXTRA_HAS_BRIDGE, false);
            }
            mRecyclerView.setItemAnimator(null);
            mRecyclerView.setLayoutManager(new LinearLayoutManager(
                    getContext(), RecyclerView.VERTICAL, false /* reverseLayout */));
            mRecyclerView.setAdapter(mApplications);
            android.util.Log.d("xin.wang", "onCreateView:mRecyclerView.setAdapter-> " + Thread.currentThread().getName());
    
            // We have to do this now because PreferenceFrameLayout looks at it
            // only when the view is added.
            if (container instanceof PreferenceFrameLayout) {
                ((PreferenceFrameLayout.LayoutParams) mRootView.getLayoutParams()).removeBorders = true;
            }
    
            createHeader();
    
            mResetAppsHelper.onRestoreInstanceState(savedInstanceState);
    
            mAppBarLayout = getActivity().findViewById(R.id.app_bar);
            disableToolBarScrollableBehavior();
    
            return mRootView;
        }
    
    
        @VisibleForTesting
        void createHeader() {
            final Activity activity = getActivity();
            final FrameLayout pinnedHeader = mRootView.findViewById(R.id.pinned_header);
            mSpinnerHeader = activity.getLayoutInflater()
                    .inflate(R.layout.manage_apps_filter_spinner, pinnedHeader, false);
            mFilterSpinner = mSpinnerHeader.findViewById(R.id.filter_spinner);
            mFilterAdapter = new FilterSpinnerAdapter(this);
            mFilterSpinner.setAdapter(mFilterAdapter);
            mFilterSpinner.setOnItemSelectedListener(this);
            mFilterSpinner.setVisibility(View.GONE);
            pinnedHeader.addView(mSpinnerHeader, 0);
    
            final AppFilterRegistry appFilterRegistry = AppFilterRegistry.getInstance();
            final int filterType = appFilterRegistry.getDefaultFilterType(mListType);
            android.util.Log.d("xin.wang", "createHeader:-> filterType -> " + mListType + "<- filterType -> " + filterType); //filterType = 4 -> FILTER_APPS_ALL
            android.util.Log.d("xin.wang", "createHeader:->mFilterOptions.size()-> " + mFilterAdapter.getCount());
            //mFilterAdapter.enableFilter(filterType);    //filterType = 4 -> FILTER_APPS_ALL
    
            if (mListType == LIST_TYPE_MAIN) {
                if (UserManager.get(getActivity()).getUserProfiles().size() > 1 && !mIsWorkOnly
                        && !mIsPersonalOnly) {
                    mFilterAdapter.enableFilter(FILTER_APPS_PERSONAL);
                    //mFilterAdapter.enableFilter(FILTER_APPS_WORK);
                }
            }
    
            if (mListType == LIST_TYPE_NOTIFICATION) {
                mFilterAdapter.enableFilter(FILTER_APPS_RECENT);
                mFilterAdapter.enableFilter(FILTER_APPS_FREQUENT);
                mFilterAdapter.enableFilter(FILTER_APPS_BLOCKED);
                mFilterAdapter.enableFilter(FILTER_APPS_ALL);
            }
            if (mListType == LIST_TYPE_HIGH_POWER) {
                mFilterAdapter.enableFilter(FILTER_APPS_POWER_ALLOWLIST_ALL);
            }
    
            setCompositeFilter();
        }
    
        @VisibleForTesting
        @Nullable
        static AppFilter getCompositeFilter(int listType, int storageType, String volumeUuid) {
            AppFilter filter = new VolumeFilter(volumeUuid);
            if (listType == LIST_TYPE_STORAGE) {
                if (storageType == STORAGE_TYPE_DEFAULT) {
                    filter = new CompoundFilter(ApplicationsState.FILTER_APPS_EXCEPT_GAMES, filter);
                }
                return filter;
            }
            if (listType == LIST_TYPE_GAMES) {
                return new CompoundFilter(ApplicationsState.FILTER_GAMES, filter);
            }
            return null;
        }
    
        @Override
        public int getMetricsCategory() {
            switch (mListType) {
                case LIST_TYPE_MAIN:
                    return SettingsEnums.MANAGE_APPLICATIONS;
                case LIST_TYPE_NOTIFICATION:
                    return SettingsEnums.MANAGE_APPLICATIONS_NOTIFICATIONS;
                case LIST_TYPE_STORAGE:
                    return SettingsEnums.APPLICATIONS_STORAGE_APPS;
                case LIST_TYPE_GAMES:
                    return SettingsEnums.APPLICATIONS_STORAGE_GAMES;
                case LIST_TYPE_USAGE_ACCESS:
                    return SettingsEnums.USAGE_ACCESS;
                case LIST_TYPE_HIGH_POWER:
                    return SettingsEnums.APPLICATIONS_HIGH_POWER_APPS;
                case LIST_TYPE_OVERLAY:
                    return SettingsEnums.SYSTEM_ALERT_WINDOW_APPS;
                case LIST_TYPE_WRITE_SETTINGS:
                    return SettingsEnums.SYSTEM_ALERT_WINDOW_APPS;
                case LIST_TYPE_MANAGE_SOURCES:
                    return SettingsEnums.MANAGE_EXTERNAL_SOURCES;
                case LIST_TYPE_WIFI_ACCESS:
                    return SettingsEnums.CONFIGURE_WIFI;
                case LIST_MANAGE_EXTERNAL_STORAGE:
                    return SettingsEnums.MANAGE_EXTERNAL_STORAGE;
                case LIST_TYPE_ALARMS_AND_REMINDERS:
                    return SettingsEnums.ALARMS_AND_REMINDERS;
                case LIST_TYPE_MEDIA_MANAGEMENT_APPS:
                    return SettingsEnums.MEDIA_MANAGEMENT_APPS;
                default:
                    return SettingsEnums.PAGE_UNKNOWN;
            }
        }
    
        @Override
        public void onStart() {
            super.onStart();
            updateView();
            if (mApplications != null) {
                mApplications.resume(mSortOrder);
                mApplications.updateLoading();
            }
        }
    
        @Override
        public void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            mResetAppsHelper.onSaveInstanceState(outState);
            outState.putInt(EXTRA_SORT_ORDER, mSortOrder);
            outState.putInt(EXTRA_FILTER_TYPE, mFilter.getFilterType());
            outState.putBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
            //add bug 1702049:NullPointerException on a null object reference
            if (mApplications != null) {
                outState.putBoolean(EXTRA_HAS_ENTRIES, mApplications.mHasReceivedLoadEntries);
                outState.putBoolean(EXTRA_HAS_BRIDGE, mApplications.mHasReceivedBridgeCallback);
                if (mSearchView != null) {
                    outState.putBoolean(EXTRA_EXPAND_SEARCH_VIEW, !mSearchView.isIconified());
                }
                mApplications.onSaveInstanceState(outState);
            }
        }
    
        @Override
        public void onStop() {
            super.onStop();
            if (mApplications != null) {
                mApplications.pause();
            }
            mResetAppsHelper.stop();
        }
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
    
            if (mApplications != null) {
                mApplications.release();
            }
            mRootView = null;
        }
    
        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode == INSTALLED_APP_DETAILS && mCurrentPkgName != null) {
                if (mListType == LIST_TYPE_NOTIFICATION) {
                    mApplications.mExtraInfoBridge.forceUpdate(mCurrentPkgName, mCurrentUid);
                } else if (mListType == LIST_TYPE_HIGH_POWER || mListType == LIST_TYPE_OVERLAY
                        || mListType == LIST_TYPE_WRITE_SETTINGS) {
                    mApplications.mExtraInfoBridge.forceUpdate(mCurrentPkgName, mCurrentUid);
                } else {
                    mApplicationsState.requestSize(mCurrentPkgName, UserHandle.getUserId(mCurrentUid));
                }
            }
        }
    
        private void setCompositeFilter() {
            AppFilter compositeFilter = getCompositeFilter(mListType, mStorageType, mVolumeUuid);
            if (compositeFilter == null) {
                compositeFilter = mFilter.getFilter();
            }
            if (mIsWorkOnly) {
                compositeFilter = new CompoundFilter(compositeFilter, ApplicationsState.FILTER_WORK);
            }
            if (mIsPersonalOnly) {
                compositeFilter = new CompoundFilter(compositeFilter,
                        ApplicationsState.FILTER_PERSONAL);
            }
            mApplications.setCompositeFilter(compositeFilter);
        }
    
        // utility method used to start sub activity
        private void startApplicationDetailsActivity() {
            switch (mListType) {
                case LIST_TYPE_NOTIFICATION:
                    startAppInfoFragment(AppNotificationSettings.class, R.string.notifications_title);
                    break;
                case LIST_TYPE_USAGE_ACCESS:
                    startAppInfoFragment(UsageAccessDetails.class, R.string.usage_access);
                    break;
                case LIST_TYPE_STORAGE:
                    startAppInfoFragment(AppStorageSettings.class, R.string.storage_settings);
                    break;
                case LIST_TYPE_HIGH_POWER:
                    HighPowerDetail.show(this, mCurrentUid, mCurrentPkgName, INSTALLED_APP_DETAILS);
                    break;
                case LIST_TYPE_OVERLAY:
                    startAppInfoFragment(DrawOverlayDetails.class, R.string.overlay_settings);
                    break;
                case LIST_TYPE_WRITE_SETTINGS:
                    startAppInfoFragment(WriteSettingsDetails.class, R.string.write_system_settings);
                    break;
                case LIST_TYPE_MANAGE_SOURCES:
                    startAppInfoFragment(ExternalSourcesDetails.class, R.string.install_other_apps);
                    break;
                case LIST_TYPE_GAMES:
                    startAppInfoFragment(AppStorageSettings.class, R.string.game_storage_settings);
                    break;
                case LIST_TYPE_WIFI_ACCESS:
                    startAppInfoFragment(ChangeWifiStateDetails.class,
                            R.string.change_wifi_state_title);
                    break;
                case LIST_MANAGE_EXTERNAL_STORAGE:
                    startAppInfoFragment(ManageExternalStorageDetails.class,
                            R.string.manage_external_storage_title);
                    break;
                case LIST_TYPE_ALARMS_AND_REMINDERS:
                    startAppInfoFragment(AlarmsAndRemindersDetails.class,
                            R.string.alarms_and_reminders_label);
                    break;
                case LIST_TYPE_MEDIA_MANAGEMENT_APPS:
                    startAppInfoFragment(MediaManagementAppsDetails.class,
                            R.string.media_management_apps_title);
                    break;
                // TODO: Figure out if there is a way where we can spin up the profile's settings
                // process ahead of time, to avoid a long load of data when user clicks on a managed
                // app. Maybe when they load the list of apps that contains managed profile apps.
                default:
                    startAppInfoFragment(
                            AppInfoDashboardFragment.class, R.string.application_info_label);
                    break;
            }
        }
    
        private void startAppInfoFragment(Class fragment, int titleRes) {
            AppInfoBase.startAppInfoFragment(fragment, titleRes, mCurrentPkgName, mCurrentUid, this,
                    INSTALLED_APP_DETAILS, getMetricsCategory());
        }
    
        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            final Activity activity = getActivity();
            if (activity == null) {
                return;
            }
            mOptionsMenu = menu;
            inflater.inflate(R.menu.manage_apps, menu);
    
            final MenuItem searchMenuItem = menu.findItem(R.id.search_app_list_menu);
            if (searchMenuItem != null) {
                searchMenuItem.setOnActionExpandListener(this);
                mSearchView = (SearchView) searchMenuItem.getActionView();
                mSearchView.setQueryHint(getText(R.string.search_settings));
                mSearchView.setOnQueryTextListener(this);
                if (mExpandSearch) {
                    searchMenuItem.expandActionView();
                }
            }
    
            updateOptionsMenu();
        }
    
        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            // To prevent a large space on tool bar.
            mAppBarLayout.setExpanded(false /*expanded*/, false /*animate*/);
            // To prevent user can expand the collapsing tool bar view.
            ViewCompat.setNestedScrollingEnabled(mRecyclerView, false);
            return true;
        }
    
        @Override
        public boolean onMenuItemActionCollapse(MenuItem item) {
            // We keep the collapsed status after user cancel the search function.
            mAppBarLayout.setExpanded(false /*expanded*/, false /*animate*/);
            ViewCompat.setNestedScrollingEnabled(mRecyclerView, true);
            return true;
        }
    
        @Override
        public void onPrepareOptionsMenu(Menu menu) {
            updateOptionsMenu();
        }
    
        @Override
        public void onDestroyOptionsMenu() {
            mOptionsMenu = null;
        }
    
        @StringRes
        int getHelpResource() {
            switch (mListType) {
                case LIST_TYPE_NOTIFICATION:
                    return R.string.help_uri_notifications;
                case LIST_TYPE_USAGE_ACCESS:
                    return R.string.help_url_usage_access;
                case LIST_TYPE_STORAGE:
                    return R.string.help_uri_apps_storage;
                case LIST_TYPE_HIGH_POWER:
                    return R.string.help_uri_apps_high_power;
                case LIST_TYPE_OVERLAY:
                    return R.string.help_uri_apps_overlay;
                case LIST_TYPE_WRITE_SETTINGS:
                    return R.string.help_uri_apps_write_settings;
                case LIST_TYPE_MANAGE_SOURCES:
                    return R.string.help_uri_apps_manage_sources;
                case LIST_TYPE_GAMES:
                    return R.string.help_uri_apps_overlay;
                case LIST_TYPE_WIFI_ACCESS:
                    return R.string.help_uri_apps_wifi_access;
                case LIST_MANAGE_EXTERNAL_STORAGE:
                    return R.string.help_uri_manage_external_storage;
                case LIST_TYPE_ALARMS_AND_REMINDERS:
                    return R.string.help_uri_alarms_and_reminders;
                case LIST_TYPE_MEDIA_MANAGEMENT_APPS:
                    return R.string.help_uri_media_management_apps;
                default:
                case LIST_TYPE_MAIN:
                    return R.string.help_uri_apps;
            }
        }
    
        void updateOptionsMenu() {
            if (mOptionsMenu == null) {
                return;
            }
            mOptionsMenu.findItem(R.id.advanced).setVisible(false);
    
            mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible(mListType == LIST_TYPE_STORAGE
                    && mSortOrder != R.id.sort_order_alpha);
            mOptionsMenu.findItem(R.id.sort_order_size).setVisible(mListType == LIST_TYPE_STORAGE
                    && mSortOrder != R.id.sort_order_size);
    
            mOptionsMenu.findItem(R.id.show_system).setVisible(!mShowSystem
                    && mListType != LIST_TYPE_HIGH_POWER && wheatherShowSystemOption());
            mOptionsMenu.findItem(R.id.hide_system).setVisible(mShowSystem
                    && mListType != LIST_TYPE_HIGH_POWER && wheatherShowSystemOption());
            mOptionsMenu.findItem(R.id.reset_app_preferences).setVisible(mListType == LIST_TYPE_MAIN);
    
            // Hide notification menu items, because sorting happens when filtering
            mOptionsMenu.findItem(R.id.sort_order_recent_notification).setVisible(false);
            mOptionsMenu.findItem(R.id.sort_order_frequent_notification).setVisible(false);
            final MenuItem searchItem = mOptionsMenu.findItem(MENU_SEARCH);
            if (searchItem != null) {
                searchItem.setVisible(false);
            }
        }
    
        //hide the optionsmenu of hide-system and show-system in the work interface
        private boolean wheatherShowSystemOption() {
            boolean hasManageProfile = false;
            List users = mUserManager.getUsers();
            android.util.Log.d("xin.wang", "wheatherShowSystemOption: " + users + "<- users.size->" + users.size());
            for(UserInfo user : users){
                if (user.isManagedProfile()) {
                    hasManageProfile = true;
                    break;
                }
            }
            if (mIsWorkOnly && !mIsPersonalOnly) {
                if (!hasManageProfile) {
                    return false;
                }
            }
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            int menuId = item.getItemId();
            int i = item.getItemId();
            if (i == R.id.sort_order_alpha || i == R.id.sort_order_size) {
                if (mApplications != null) {
                    mApplications.rebuild(menuId);
                }
            } else if (i == R.id.show_system || i == R.id.hide_system) {
                mShowSystem = !mShowSystem;
                mApplications.rebuild();
            } else if (i == R.id.reset_app_preferences) {
                mResetAppsHelper.buildResetDialog();
                return true;
            } else if (i == R.id.advanced) {
                if (mListType == LIST_TYPE_NOTIFICATION) {
                    new SubSettingLauncher(getContext())
                            .setDestination(ConfigureNotificationSettings.class.getName())
                            .setTitleRes(R.string.configure_notification_settings)
                            .setSourceMetricsCategory(getMetricsCategory())
                            .setResultListener(this, ADVANCED_SETTINGS)
                            .launch();
                } else {
                    Intent intent = new Intent(
                            android.provider.Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
                    startActivityForResult(intent, ADVANCED_SETTINGS);
                }
                return true;
            } else {// Handle the home button
                return false;
            }
            updateOptionsMenu();
            return true;
        }
    
        @Override
        public void onClick(View view) {
            if (mApplications == null) {
                return;
            }
            final int position = mRecyclerView.getChildAdapterPosition(view);
    
            if (position == RecyclerView.NO_POSITION) {
                Log.w(TAG, "Cannot find position for child, skipping onClick handling");
                return;
            }
            if (mApplications.getApplicationCount() > position) {
                ApplicationsState.AppEntry entry = mApplications.getAppEntry(position);
                mCurrentPkgName = entry.info.packageName;
                mCurrentUid = entry.info.uid;
                startApplicationDetailsActivity();
                // We disable the scrolling ability in onMenuItemActionCollapse, we should recover it
                // if user selects any app item.
                ViewCompat.setNestedScrollingEnabled(mRecyclerView, true);
            }
        }
    
        @Override
        public void onItemSelected(AdapterView parent, View view, int position, long id) {
            mFilter = mFilterAdapter.getFilter(position);
            setCompositeFilter();
            mApplications.setFilter(mFilter);
    
            if (DEBUG) {
                Log.d(TAG, "Selecting filter " + getContext().getText(mFilter.getTitle()));
            }
        }
    
        @Override
        public void onNothingSelected(AdapterView parent) {
        }
    
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }
    
        @Override
        public boolean onQueryTextChange(String newText) {
            mApplications.filterSearch(newText);
            return false;
        }
    
        public void updateView() {
            updateOptionsMenu();
            final Activity host = getActivity();
            if (host != null) {
                host.invalidateOptionsMenu();
            }
        }
    
        public void setHasDisabled(boolean hasDisabledApps) {
            if (mListType != LIST_TYPE_MAIN) {
                return;
            }
            mFilterAdapter.setFilterEnabled(FILTER_APPS_ENABLED, hasDisabledApps);
            mFilterAdapter.setFilterEnabled(FILTER_APPS_DISABLED, hasDisabledApps);
        }
    
        public void setHasInstant(boolean haveInstantApps) {
            if (LIST_TYPES_WITH_INSTANT.contains(mListType)) {
                mFilterAdapter.setFilterEnabled(FILTER_APPS_INSTANT, haveInstantApps);
            }
        }
    
        private void disableToolBarScrollableBehavior() {
            final CoordinatorLayout.LayoutParams params =
                    (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
            final AppBarLayout.Behavior behavior = new AppBarLayout.Behavior();
            behavior.setDragCallback(
                    new AppBarLayout.Behavior.DragCallback() {
                        @Override
                        public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
                            return false;
                        }
                    });
            params.setBehavior(behavior);
        }
    
        static class FilterSpinnerAdapter extends SettingsSpinnerAdapter {
    
            private final ManageApplications mManageApplications;
            private final Context mContext;
    
            // Use ArrayAdapter for view logic, but have our own list for managing
            // the options available.
            private final ArrayList mFilterOptions = new ArrayList<>();
    
            public FilterSpinnerAdapter(ManageApplications manageApplications) {
                super(manageApplications.getContext());
                mContext = manageApplications.getContext();
                mManageApplications = manageApplications;
            }
    
            public AppFilterItem getFilter(int position) {
                return mFilterOptions.get(position);
            }
    
            public void setFilterEnabled(@AppFilterRegistry.FilterType int filter, boolean enabled) {
                if (enabled) {
                    enableFilter(filter);
                } else {
                    disableFilter(filter);
                }
            }
    
            public void enableFilter(@AppFilterRegistry.FilterType int filterType) {
                final AppFilterItem filter = AppFilterRegistry.getInstance().get(filterType);
                if (mFilterOptions.contains(filter)) {
                    return;
                }
                if (DEBUG) {
                    Log.d(TAG, "Enabling filter " + mContext.getText(filter.getTitle()));
                }
                mFilterOptions.add(filter);
                Collections.sort(mFilterOptions);
                updateFilterView(mFilterOptions.size() > 1);
                notifyDataSetChanged();
                if (mFilterOptions.size() == 1) {
                    if (DEBUG) {
                        Log.d(TAG, "Auto selecting filter " + filter + " " + mContext.getText(
                                filter.getTitle()));
                    }
                    mManageApplications.mFilterSpinner.setSelection(0);
                    mManageApplications.onItemSelected(null, null, 0, 0);
                }
                if (mFilterOptions.size() > 1) {
                    final AppFilterItem previousFilter = AppFilterRegistry.getInstance().get(
                            mManageApplications.mFilterType);
                    final int index = mFilterOptions.indexOf(previousFilter);
                    if (index != -1) {
                        android.util.Log.d("xin.wang", "enableFilter: previousFilter -> " + previousFilter + "<- index -> " + index);
                        mManageApplications.mFilterSpinner.setSelection(index);
                        mManageApplications.onItemSelected(null, null, index, 0);
                    }
                }
            }
    
            public void disableFilter(@AppFilterRegistry.FilterType int filterType) {
                final AppFilterItem filter = AppFilterRegistry.getInstance().get(filterType);
                if (!mFilterOptions.remove(filter)) {
                    return;
                }
                if (DEBUG) {
                    Log.d(TAG, "Disabling filter " + filter + " " + mContext.getText(
                            filter.getTitle()));
                }
                Collections.sort(mFilterOptions);
                updateFilterView(mFilterOptions.size() > 1);
                notifyDataSetChanged();
                if (mManageApplications.mFilter == filter) {
                    if (mFilterOptions.size() > 0) {
                        if (DEBUG) {
                            Log.d(TAG, "Auto selecting filter " + mFilterOptions.get(0)
                                    + mContext.getText(mFilterOptions.get(0).getTitle()));
                        }
                        android.util.Log.d("xin.wang", "disableFilter: Auto selecting filter -> " + mContext.getText(mFilterOptions.get(0).getTitle()));
                        mManageApplications.mFilterSpinner.setSelection(0);
                        mManageApplications.onItemSelected(null, null, 0, 0);
                    }
                }
            }
    
            @Override
            public int getCount() {
                android.util.Log.d("xin.wang", "getCount: mFilterOptions.size()->" + mFilterOptions.size());
                return mFilterOptions.size();
            }
    
            @Override
            public CharSequence getItem(int position) {
                return mContext.getText(mFilterOptions.get(position).getTitle());
            }
    
            @VisibleForTesting
            void updateFilterView(boolean hasFilter) {
                // If we need to add a floating filter in this screen, we should have an extra top
                // padding for putting floating filter view. Otherwise, the content of list will be
                // overlapped by floating filter.
                if (hasFilter) {
                    mManageApplications.mSpinnerHeader.setVisibility(View.VISIBLE);
                } else {
                    mManageApplications.mSpinnerHeader.setVisibility(View.GONE);
                }
            }
        }
    
        static class ApplicationsAdapter extends RecyclerView.Adapter
                implements ApplicationsState.Callbacks, AppStateBaseBridge.Callback {
    
            private static final String STATE_LAST_SCROLL_INDEX = "state_last_scroll_index";
            private static final int VIEW_TYPE_APP = 0;
            private static final int VIEW_TYPE_EXTRA_VIEW = 1;
    
            private final ApplicationsState mState;
            private final ApplicationsState.Session mSession;
            private final ManageApplications mManageApplications;
            private final Context mContext;
            private final AppStateBaseBridge mExtraInfoBridge;
            private final LoadingViewController mLoadingViewController;
            private final IconDrawableFactory mIconDrawableFactory;
    
            private AppFilterItem mAppFilter;
            private ArrayList mEntries;
            private ArrayList mOriginalEntries;
            private boolean mResumed;
            private int mLastSortMode = -1;
            private int mWhichSize = SIZE_TOTAL;
            private AppFilter mCompositeFilter;
            private boolean mHasReceivedLoadEntries;
            private boolean mHasReceivedBridgeCallback;
            private SearchFilter mSearchFilter;
            private PowerAllowlistBackend mBackend;
            private HashSet mSupportAppClone;
            // This is to remember and restore the last scroll position when this
            // fragment is paused. We need this special handling because app entries are added gradually
            // when we rebuild the list after the user made some changes, like uninstalling an app.
            private int mLastIndex = -1;
    
            @VisibleForTesting
            OnScrollListener mOnScrollListener;
            private RecyclerView mRecyclerView;
    
    
            public ApplicationsAdapter(ApplicationsState state, ManageApplications manageApplications,
                    AppFilterItem appFilter, Bundle savedInstanceState) {
                setHasStableIds(true);
                mState = state;
                mSession = state.newSession(this);
                mManageApplications = manageApplications;
                mLoadingViewController = new LoadingViewController(
                        mManageApplications.mLoadingContainer,
                        mManageApplications.mRecyclerView,
                        mManageApplications.mEmptyView
                );
                mContext = manageApplications.getActivity();
                mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
                mAppFilter = appFilter;
                mBackend = PowerAllowlistBackend.getInstance(mContext);
                String[] supportApps = mContext.getResources().getStringArray(com.unisoc.internal.R.array.support_app_clone);
                mSupportAppClone = new HashSet(Arrays.asList(supportApps));
                android.util.Log.d("xin.wang", "ApplicationsAdapter -> mSupportAppClone -> : " + mSupportAppClone);
                if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
                    mExtraInfoBridge = new AppStateNotificationBridge(mContext, mState, this,
                            manageApplications.mUsageStatsManager,
                            manageApplications.mUserManager,
                            manageApplications.mNotificationBackend);
                } else if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
                    mExtraInfoBridge = new AppStateUsageBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_HIGH_POWER) {
                    mBackend.refreshList();
                    mExtraInfoBridge = new AppStatePowerBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_OVERLAY) {
                    mExtraInfoBridge = new AppStateOverlayBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_WRITE_SETTINGS) {
                    mExtraInfoBridge = new AppStateWriteSettingsBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_MANAGE_SOURCES) {
                    mExtraInfoBridge = new AppStateInstallAppsBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_WIFI_ACCESS) {
                    mExtraInfoBridge = new AppStateChangeWifiStateBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_MANAGE_EXTERNAL_STORAGE) {
                    mExtraInfoBridge = new AppStateManageExternalStorageBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_ALARMS_AND_REMINDERS) {
                    mExtraInfoBridge = new AppStateAlarmsAndRemindersBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_MEDIA_MANAGEMENT_APPS) {
                    mExtraInfoBridge = new AppStateMediaManagementAppsBridge(mContext, mState, this);
                } else {
                    mExtraInfoBridge = null;
                }
                if (savedInstanceState != null) {
                    mLastIndex = savedInstanceState.getInt(STATE_LAST_SCROLL_INDEX);
                }
            }
    
            @Override
            public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
                super.onAttachedToRecyclerView(recyclerView);
                mRecyclerView = recyclerView;
                mOnScrollListener = new OnScrollListener(this);
                mRecyclerView.addOnScrollListener(mOnScrollListener);
            }
    
            @Override
            public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
                super.onDetachedFromRecyclerView(recyclerView);
                mRecyclerView.removeOnScrollListener(mOnScrollListener);
                mOnScrollListener = null;
                mRecyclerView = null;
            }
    
            public void setCompositeFilter(AppFilter compositeFilter) {
                mCompositeFilter = compositeFilter;
                rebuild();
            }
    
            public void setFilter(AppFilterItem appFilter) {
                mAppFilter = appFilter;
    
                // Notification filters require resorting the list
                if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
                    if (FILTER_APPS_FREQUENT == appFilter.getFilterType()) {
                        rebuild(R.id.sort_order_frequent_notification);
                    } else if (FILTER_APPS_RECENT == appFilter.getFilterType()) {
                        rebuild(R.id.sort_order_recent_notification);
                    } else if (FILTER_APPS_BLOCKED == appFilter.getFilterType()) {
                        rebuild(R.id.sort_order_alpha);
                    } else {
                        rebuild(R.id.sort_order_alpha);
                    }
                } else {
                    rebuild();
                }
            }
    
            public void resume(int sort) {
                if (DEBUG) Log.i(TAG, "Resume!  mResumed=" + mResumed);
                if (!mResumed) {
                    mResumed = true;
                    mSession.onResume();
                    mLastSortMode = sort;
                    if (mExtraInfoBridge != null) {
                        mExtraInfoBridge.resume();
                    }
                    rebuild();
                } else {
                    rebuild(sort);
                }
            }
    
            public void pause() {
                if (mResumed) {
                    mResumed = false;
                    mSession.onPause();
                    if (mExtraInfoBridge != null) {
                        mExtraInfoBridge.pause();
                    }
                }
            }
    
            public void onSaveInstanceState(Bundle outState) {
                // Record the current scroll position before pausing.
                final LinearLayoutManager layoutManager =
                        (LinearLayoutManager) mManageApplications.mRecyclerView.getLayoutManager();
                outState.putInt(STATE_LAST_SCROLL_INDEX, layoutManager.findFirstVisibleItemPosition());
            }
    
            public void release() {
                mSession.onDestroy();
                if (mExtraInfoBridge != null) {
                    mExtraInfoBridge.release();
                }
            }
    
            public void rebuild(int sort) {
                if (sort == mLastSortMode) {
                    return;
                }
                mManageApplications.mSortOrder = sort;
                mLastSortMode = sort;
                rebuild();
            }
    
            @Override
            public ApplicationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                final View view;
                if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
                    view = ApplicationViewHolder.newView(parent, true /* twoTarget */);
                } else {
                    view = ApplicationViewHolder.newView(parent, false /* twoTarget */);
                }
                return new ApplicationViewHolder(view);
            }
    
            @Override
            public int getItemViewType(int position) {
                return VIEW_TYPE_APP;
            }
    
            public void rebuild() {
                if (!mHasReceivedLoadEntries
                        || (mExtraInfoBridge != null && !mHasReceivedBridgeCallback)) {
                    // Don't rebuild the list until all the app entries are loaded.
                    if (DEBUG) {
                        Log.d(TAG, "Not rebuilding until all the app entries loaded."
                                + " !mHasReceivedLoadEntries=" + !mHasReceivedLoadEntries
                                + " !mExtraInfoBridgeNull=" + (mExtraInfoBridge != null)
                                + " !mHasReceivedBridgeCallback=" + !mHasReceivedBridgeCallback);
                    }
                    return;
                }
                ApplicationsState.AppFilter filterObj;
                Comparator comparatorObj;
                boolean emulated = Environment.isExternalStorageEmulated();
                if (emulated) {
                    mWhichSize = SIZE_TOTAL;
                } else {
                    mWhichSize = SIZE_INTERNAL;
                }
                filterObj = mAppFilter.getFilter();
                if (mCompositeFilter != null) {
                    filterObj = new CompoundFilter(filterObj, mCompositeFilter);
                }
                if (!mManageApplications.mShowSystem) {
                    if (LIST_TYPES_WITH_INSTANT.contains(mManageApplications.mListType)) {
                        filterObj = new CompoundFilter(filterObj,
                                ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT);
                    } else {
                        filterObj = new CompoundFilter(filterObj,
                                ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
                    }
                }
                if (mLastSortMode == R.id.sort_order_size) {
                    switch (mWhichSize) {
                        case SIZE_INTERNAL:
                            comparatorObj = ApplicationsState.INTERNAL_SIZE_COMPARATOR;
                            break;
                        case SIZE_EXTERNAL:
                            comparatorObj = ApplicationsState.EXTERNAL_SIZE_COMPARATOR;
                            break;
                        default:
                            comparatorObj = ApplicationsState.SIZE_COMPARATOR;
                            break;
                    }
                } else if (mLastSortMode == R.id.sort_order_recent_notification) {
                    comparatorObj = AppStateNotificationBridge.RECENT_NOTIFICATION_COMPARATOR;
                } else if (mLastSortMode == R.id.sort_order_frequent_notification) {
                    comparatorObj = AppStateNotificationBridge.FREQUENCY_NOTIFICATION_COMPARATOR;
                } else {
                    comparatorObj = ApplicationsState.ALPHA_COMPARATOR;
                }
    
                final AppFilter finalFilterObj = new CompoundFilter(filterObj,
                        ApplicationsState.FILTER_NOT_HIDE);
                ThreadUtils.postOnBackgroundThread(() -> {
                    mSession.rebuild(finalFilterObj, comparatorObj, false);
                });
            }
    
            @VisibleForTesting
            void filterSearch(String query) {
                if (mSearchFilter == null) {
                    mSearchFilter = new SearchFilter();
                }
                // If we haven't load apps list completely, don't filter anything.
                if (mOriginalEntries == null) {
                    Log.w(TAG, "Apps haven't loaded completely yet, so nothing can be filtered");
                    return;
                }
                mSearchFilter.filter(query);
            }
    
            private static boolean packageNameEquals(PackageItemInfo info1, PackageItemInfo info2) {
                if (info1 == null || info2 == null) {
                    return false;
                }
                if (info1.packageName == null || info2.packageName == null) {
                    return false;
                }
                return info1.packageName.equals(info2.packageName);
            }
    
            private ArrayList removeDuplicateIgnoringUser(
                    ArrayList entries) {
                int size = entries.size();
                // returnList will not have more entries than entries
                ArrayList returnEntries = new ArrayList<>(size);
    
                // assume appinfo of same package but different users are grouped together
                PackageItemInfo lastInfo = null;
                for (int i = 0; i < size; i++) {
                    AppEntry appEntry = entries.get(i);
                    PackageItemInfo info = appEntry.info;
                    if (!packageNameEquals(lastInfo, appEntry.info)) {
                        returnEntries.add(appEntry);
                    }
                    lastInfo = info;
                }
                returnEntries.trimToSize();
                return returnEntries;
            }
    
            @Override
            public void onRebuildComplete(ArrayList entries) {
                //android.util.Log.d("xin.wang", "onRebuildComplete:-> entries-> " + entries);
                android.util.Log.d("xin.wang", "哈哈哈onRebuildComplete:-> entries-> " + entries.size());
                if (DEBUG) {
                    Log.d(TAG, "onRebuildComplete size=" + entries.size());
                }
                final int filterType = mAppFilter.getFilterType();
                if (filterType == FILTER_APPS_POWER_ALLOWLIST
                        || filterType == FILTER_APPS_POWER_ALLOWLIST_ALL) {
                    entries = removeDuplicateIgnoringUser(entries);
                    android.util.Log.d("xin.wang", "onRebuildComplete: entries -> " + entries.size());
                }
                //only show the cloned third-party apps in the interface of work
                if (mManageApplications.mIsWorkOnly && !mManageApplications.mIsPersonalOnly) {
                    ArrayList cloneEntries = new ArrayList();
                    int cloneNum = 0;
                    for (ApplicationsState.AppEntry entry : entries) {
                        cloneNum ++;
                        android.util.Log.d("xin.wang", "哈哈哈onRebuildComplete: cloneNum -> " + cloneNum);
                        int userId = UserHandle.getUserId(entry.info.uid);
                        UserInfo userInfo = mManageApplications.mUserManager.getUserInfo(userId);
                        boolean isManagedProfile = userInfo.isManagedProfile();
    
                        if (isManagedProfile) {
                            cloneEntries.add(entry);
                            android.util.Log.d("xin.wang", "isManagedProfile: -> cloneEntries " + cloneEntries + "<- cloneEntries.size() -> " + cloneEntries.size());
                            continue;
                        }
                        boolean isCloneProfile = userInfo.isCloneProfile();
                        boolean contains = mSupportAppClone.contains(entry.info.packageName);
                        android.util.Log.d("xin.wang", "onRebuildComplete: isCloneProfile -> " + isCloneProfile + "<- contains -> " + contains);
                        if (mSupportAppClone.contains(entry.info.packageName) && isCloneProfile) {
                            android.util.Log.d("xin.wang", "onRebuildComplete:mSupportAppClone-> " + mSupportAppClone + "<- entry.info.packageName->" + entry.info.packageName);
                            cloneEntries.add(entry);
                            android.util.Log.d("xin.wang", "mSupportAppClone.contains(entry.info.packageName): ->  cloneEntries " + cloneEntries + "<- cloneEntries.size() -> " + cloneEntries.size());
                        }
                    }
                    mEntries = cloneEntries;
                    android.util.Log.d("xin.wang", "onRebuildComplete:cloneEntries ->  " + cloneEntries + "<- cloneEntries.size() ->  " + cloneEntries.size());
                    mOriginalEntries = cloneEntries;
                } else {
                    mEntries = entries;
                    android.util.Log.d("xin.wang", "哈哈哈onRebuildComplete: mEntries -> " + mEntries.size());
                    mOriginalEntries = entries;
                }
    
                notifyDataSetChanged();
                if (getItemCount() == 0) {
                    mLoadingViewController.showEmpty(false /* animate */);
                } else {
                    mLoadingViewController.showContent(false /* animate */);
    
                    if (mManageApplications.mSearchView != null
                            && mManageApplications.mSearchView.isVisibleToUser()) {
                        final CharSequence query = mManageApplications.mSearchView.getQuery();
                        if (!TextUtils.isEmpty(query)) {
                            filterSearch(query.toString());
                        }
                    }
                }
                // Restore the last scroll position if the number of entries added so far is bigger than
                // it.
                if (mLastIndex != -1 && getItemCount() > mLastIndex) {
                    mManageApplications.mRecyclerView.getLayoutManager().scrollToPosition(mLastIndex);
                    mLastIndex = -1;
                }
    
                if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
                    // No enabled or disabled filters for usage access.
                    return;
                }
    
                mManageApplications.setHasDisabled(mState.haveDisabledApps());
                mManageApplications.setHasInstant(mState.haveInstantApps());
            }
    
            @VisibleForTesting
            void updateLoading() {
                final boolean appLoaded = mHasReceivedLoadEntries && mSession.getAllApps().size() != 0;
                if (appLoaded) {
                    mLoadingViewController.showContent(false /* animate */);
                } else {
                    mLoadingViewController.showLoadingViewDelayed();
                }
            }
    
            @Override
            public void onExtraInfoUpdated() {
                mHasReceivedBridgeCallback = true;
                rebuild();
            }
    
            @Override
            public void onRunningStateChanged(boolean running) {
                mManageApplications.getActivity().setProgressBarIndeterminateVisibility(running);
            }
    
            @Override
            public void onPackageListChanged() {
                rebuild();
            }
    
            @Override
            public void onPackageIconChanged() {
                // We ensure icons are loaded when their item is displayed, so
                // don't care about icons loaded in the background.
            }
    
            @Override
            public void onLoadEntriesCompleted() {
                mHasReceivedLoadEntries = true;
                // We may have been skipping rebuilds until this came in, trigger one now.
                rebuild();
            }
    
            @Override
            public void onPackageSizeChanged(String packageName) {
                if (mEntries == null) {
                    return;
                }
                final int size = mEntries.size();
                for (int i = 0; i < size; i++) {
                    final AppEntry entry = mEntries.get(i);
                    android.util.Log.d("xin.wang", "onPackageSizeChanged: -> entry -> " + entry.info.packageName + "<- size -> " + size + "<- mEntries -> " + mEntries);
                    final ApplicationInfo info = entry.info;
                    if (info == null && !TextUtils.equals(packageName, info.packageName)) {
                        continue;
                    }
                    if (TextUtils.equals(mManageApplications.mCurrentPkgName, info.packageName)) {
                        // We got the size information for the last app the
                        // user viewed, and are sorting by size...  they may
                        // have cleared data, so we immediately want to resort
                        // the list with the new size to reflect it to the user.
                        rebuild();
                        return;
                    } else {
                        mOnScrollListener.postNotifyItemChange(i);
                    }
                }
            }
    
            @Override
            public void onLauncherInfoChanged() {
                if (!mManageApplications.mShowSystem) {
                    rebuild();
                }
            }
    
            @Override
            public void onAllSizesComputed() {
                if (mLastSortMode == R.id.sort_order_size) {
                    rebuild();
                }
            }
    
            @Override
            public int getItemCount() {
                if (mEntries == null) {
                    return 0;
                }
                android.util.Log.d("xin.wang", "getItemCount: " + mEntries.size());
                return mEntries.size();
            }
    
            public int getApplicationCount() {
                return mEntries != null ? mEntries.size() : 0;
            }
    
            public AppEntry getAppEntry(int position) {
                return mEntries.get(position);
            }
    
            @Override
            public long getItemId(int position) {
                if (position == mEntries.size()) {
                    return -1;
                }
                return mEntries.get(position).id;
            }
    
            public boolean isEnabled(int position) {
                if (getItemViewType(position) == VIEW_TYPE_EXTRA_VIEW
                        || mManageApplications.mListType != LIST_TYPE_HIGH_POWER) {
                    return true;
                }
                ApplicationsState.AppEntry entry = mEntries.get(position);
    
                return !mBackend.isSysAllowlisted(entry.info.packageName)
                        && !mBackend.isDefaultActiveApp(entry.info.packageName);
            }
    
            @Override
            public void onBindViewHolder(ApplicationViewHolder holder, int position) {
                // Bind the data efficiently with the holder
                final ApplicationsState.AppEntry entry = mEntries.get(position);
                android.util.Log.d("xin.wang", "onBindViewHolder: ApplicationsState.AppEntry -> " + entry + "<- entry -> ");
                synchronized (entry) {
                    mState.ensureLabelDescription(entry);
                    holder.setTitle(entry.label, entry.labelDescription);
                    android.util.Log.d("xin.wang", "onBindViewHolder -> entry.label -> : " + entry.label + "<- entry.labelDescription -> " + entry.labelDescription);
                    mState.ensureIcon(entry);
                    holder.setIcon(entry.icon);
                    updateSummary(holder, entry);
                    updateSwitch(holder, entry);
                    holder.updateDisableView(entry.info);
                }
                holder.setEnabled(isEnabled(position));
    
                holder.itemView.setOnClickListener(mManageApplications);
            }
    
            private void updateSummary(ApplicationViewHolder holder, AppEntry entry) {
                switch (mManageApplications.mListType) {
                    case LIST_TYPE_NOTIFICATION:
                        if (entry.extraInfo != null
                                && entry.extraInfo instanceof NotificationsSentState) {
                            holder.setSummary(AppStateNotificationBridge.getSummary(mContext,
                                    (NotificationsSentState) entry.extraInfo, mLastSortMode));
                        } else {
                            holder.setSummary(null);
                        }
                        break;
                    case LIST_TYPE_USAGE_ACCESS:
                        if (entry.extraInfo != null
                                && entry.extraInfo instanceof PermissionState) {
                            holder.setSummary(
                                    (new UsageState((PermissionState) entry.extraInfo)).isPermissible()
                                            ? R.string.app_permission_summary_allowed
                                            : R.string.app_permission_summary_not_allowed);
                        } else {
                            holder.setSummary(null);
                        }
                        break;
                    case LIST_TYPE_HIGH_POWER:
                        holder.setSummary(HighPowerDetail.getSummary(mContext, entry));
                        break;
                    case LIST_TYPE_OVERLAY:
                        holder.setSummary(DrawOverlayDetails.getSummary(mContext, entry));
                        break;
                    case LIST_TYPE_WRITE_SETTINGS:
                        holder.setSummary(WriteSettingsDetails.getSummary(mContext, entry));
                        break;
                    case LIST_TYPE_MANAGE_SOURCES:
                        holder.setSummary(ExternalSourcesDetails.getPreferenceSummary(mContext, entry));
                        break;
                    case LIST_TYPE_WIFI_ACCESS:
                        holder.setSummary(ChangeWifiStateDetails.getSummary(mContext, entry));
                        break;
                    case LIST_MANAGE_EXTERNAL_STORAGE:
                        holder.setSummary(ManageExternalStorageDetails.getSummary(mContext, entry));
                        break;
                    case LIST_TYPE_ALARMS_AND_REMINDERS:
                        holder.setSummary(AlarmsAndRemindersDetails.getSummary(mContext, entry));
                        break;
                    case LIST_TYPE_MEDIA_MANAGEMENT_APPS:
                        holder.setSummary(MediaManagementAppsDetails.getSummary(mContext, entry));
                        break;
                    default:
                        holder.updateSizeText(entry, mManageApplications.mInvalidSizeStr, mWhichSize);
                        break;
                }
            }
    
            private void updateSwitch(ApplicationViewHolder holder, AppEntry entry) {
                switch (mManageApplications.mListType) {
                    case LIST_TYPE_NOTIFICATION:
                        holder.updateSwitch(((AppStateNotificationBridge) mExtraInfoBridge)
                                        .getSwitchOnCheckedListener(entry),
                                AppStateNotificationBridge.enableSwitch(entry),
                                AppStateNotificationBridge.checkSwitch(entry));
                        if (entry.extraInfo != null
                                && entry.extraInfo instanceof NotificationsSentState) {
                            holder.setSummary(AppStateNotificationBridge.getSummary(mContext,
                                    (NotificationsSentState) entry.extraInfo, mLastSortMode));
                        } else {
                            holder.setSummary(null);
                        }
                        break;
                }
            }
    
            public static class OnScrollListener extends RecyclerView.OnScrollListener {
                private int mScrollState = SCROLL_STATE_IDLE;
                private boolean mDelayNotifyDataChange;
                private ApplicationsAdapter mAdapter;
    
                public OnScrollListener(ApplicationsAdapter adapter) {
                    mAdapter = adapter;
                }
    
                @Override
                public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                    mScrollState = newState;
                    if (mScrollState == SCROLL_STATE_IDLE && mDelayNotifyDataChange) {
                        mDelayNotifyDataChange = false;
                        mAdapter.notifyDataSetChanged();
                    }
                }
    
                public void postNotifyItemChange(int index) {
                    if (mScrollState == SCROLL_STATE_IDLE) {
                        mAdapter.notifyItemChanged(index);
                    } else {
                        mDelayNotifyDataChange = true;
                    }
                }
            }
    
            /**
             * An array filter that constrains the content of the array adapter with a substring.
             * Item that does not contains the specified substring will be removed from the list.

    */ private class SearchFilter extends Filter { @WorkerThread @Override protected FilterResults performFiltering(CharSequence query) { final ArrayList matchedEntries; if (TextUtils.isEmpty(query)) { matchedEntries = mOriginalEntries; } else { matchedEntries = new ArrayList<>(); for (ApplicationsState.AppEntry entry : mOriginalEntries) { if (entry.label.toLowerCase().contains(query.toString().toLowerCase())) { matchedEntries.add(entry); } } } final FilterResults results = new FilterResults(); results.values = matchedEntries; results.count = matchedEntries.size(); return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { mEntries = (ArrayList) results.values; notifyDataSetChanged(); } } } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584
    • 585
    • 586
    • 587
    • 588
    • 589
    • 590
    • 591
    • 592
    • 593
    • 594
    • 595
    • 596
    • 597
    • 598
    • 599
    • 600
    • 601
    • 602
    • 603
    • 604
    • 605
    • 606
    • 607
    • 608
    • 609
    • 610
    • 611
    • 612
    • 613
    • 614
    • 615
    • 616
    • 617
    • 618
    • 619
    • 620
    • 621
    • 622
    • 623
    • 624
    • 625
    • 626
    • 627
    • 628
    • 629
    • 630
    • 631
    • 632
    • 633
    • 634
    • 635
    • 636
    • 637
    • 638
    • 639
    • 640
    • 641
    • 642
    • 643
    • 644
    • 645
    • 646
    • 647
    • 648
    • 649
    • 650
    • 651
    • 652
    • 653
    • 654
    • 655
    • 656
    • 657
    • 658
    • 659
    • 660
    • 661
    • 662
    • 663
    • 664
    • 665
    • 666
    • 667
    • 668
    • 669
    • 670
    • 671
    • 672
    • 673
    • 674
    • 675
    • 676
    • 677
    • 678
    • 679
    • 680
    • 681
    • 682
    • 683
    • 684
    • 685
    • 686
    • 687
    • 688
    • 689
    • 690
    • 691
    • 692
    • 693
    • 694
    • 695
    • 696
    • 697
    • 698
    • 699
    • 700
    • 701
    • 702
    • 703
    • 704
    • 705
    • 706
    • 707
    • 708
    • 709
    • 710
    • 711
    • 712
    • 713
    • 714
    • 715
    • 716
    • 717
    • 718
    • 719
    • 720
    • 721
    • 722
    • 723
    • 724
    • 725
    • 726
    • 727
    • 728
    • 729
    • 730
    • 731
    • 732
    • 733
    • 734
    • 735
    • 736
    • 737
    • 738
    • 739
    • 740
    • 741
    • 742
    • 743
    • 744
    • 745
    • 746
    • 747
    • 748
    • 749
    • 750
    • 751
    • 752
    • 753
    • 754
    • 755
    • 756
    • 757
    • 758
    • 759
    • 760
    • 761
    • 762
    • 763
    • 764
    • 765
    • 766
    • 767
    • 768
    • 769
    • 770
    • 771
    • 772
    • 773
    • 774
    • 775
    • 776
    • 777
    • 778
    • 779
    • 780
    • 781
    • 782
    • 783
    • 784
    • 785
    • 786
    • 787
    • 788
    • 789
    • 790
    • 791
    • 792
    • 793
    • 794
    • 795
    • 796
    • 797
    • 798
    • 799
    • 800
    • 801
    • 802
    • 803
    • 804
    • 805
    • 806
    • 807
    • 808
    • 809
    • 810
    • 811
    • 812
    • 813
    • 814
    • 815
    • 816
    • 817
    • 818
    • 819
    • 820
    • 821
    • 822
    • 823
    • 824
    • 825
    • 826
    • 827
    • 828
    • 829
    • 830
    • 831
    • 832
    • 833
    • 834
    • 835
    • 836
    • 837
    • 838
    • 839
    • 840
    • 841
    • 842
    • 843
    • 844
    • 845
    • 846
    • 847
    • 848
    • 849
    • 850
    • 851
    • 852
    • 853
    • 854
    • 855
    • 856
    • 857
    • 858
    • 859
    • 860
    • 861
    • 862
    • 863
    • 864
    • 865
    • 866
    • 867
    • 868
    • 869
    • 870
    • 871
    • 872
    • 873
    • 874
    • 875
    • 876
    • 877
    • 878
    • 879
    • 880
    • 881
    • 882
    • 883
    • 884
    • 885
    • 886
    • 887
    • 888
    • 889
    • 890
    • 891
    • 892
    • 893
    • 894
    • 895
    • 896
    • 897
    • 898
    • 899
    • 900
    • 901
    • 902
    • 903
    • 904
    • 905
    • 906
    • 907
    • 908
    • 909
    • 910
    • 911
    • 912
    • 913
    • 914
    • 915
    • 916
    • 917
    • 918
    • 919
    • 920
    • 921
    • 922
    • 923
    • 924
    • 925
    • 926
    • 927
    • 928
    • 929
    • 930
    • 931
    • 932
    • 933
    • 934
    • 935
    • 936
    • 937
    • 938
    • 939
    • 940
    • 941
    • 942
    • 943
    • 944
    • 945
    • 946
    • 947
    • 948
    • 949
    • 950
    • 951
    • 952
    • 953
    • 954
    • 955
    • 956
    • 957
    • 958
    • 959
    • 960
    • 961
    • 962
    • 963
    • 964
    • 965
    • 966
    • 967
    • 968
    • 969
    • 970
    • 971
    • 972
    • 973
    • 974
    • 975
    • 976
    • 977
    • 978
    • 979
    • 980
    • 981
    • 982
    • 983
    • 984
    • 985
    • 986
    • 987
    • 988
    • 989
    • 990
    • 991
    • 992
    • 993
    • 994
    • 995
    • 996
    • 997
    • 998
    • 999
    • 1000
    • 1001
    • 1002
    • 1003
    • 1004
    • 1005
    • 1006
    • 1007
    • 1008
    • 1009
    • 1010
    • 1011
    • 1012
    • 1013
    • 1014
    • 1015
    • 1016
    • 1017
    • 1018
    • 1019
    • 1020
    • 1021
    • 1022
    • 1023
    • 1024
    • 1025
    • 1026
    • 1027
    • 1028
    • 1029
    • 1030
    • 1031
    • 1032
    • 1033
    • 1034
    • 1035
    • 1036
    • 1037
    • 1038
    • 1039
    • 1040
    • 1041
    • 1042
    • 1043
    • 1044
    • 1045
    • 1046
    • 1047
    • 1048
    • 1049
    • 1050
    • 1051
    • 1052
    • 1053
    • 1054
    • 1055
    • 1056
    • 1057
    • 1058
    • 1059
    • 1060
    • 1061
    • 1062
    • 1063
    • 1064
    • 1065
    • 1066
    • 1067
    • 1068
    • 1069
    • 1070
    • 1071
    • 1072
    • 1073
    • 1074
    • 1075
    • 1076
    • 1077
    • 1078
    • 1079
    • 1080
    • 1081
    • 1082
    • 1083
    • 1084
    • 1085
    • 1086
    • 1087
    • 1088
    • 1089
    • 1090
    • 1091
    • 1092
    • 1093
    • 1094
    • 1095
    • 1096
    • 1097
    • 1098
    • 1099
    • 1100
    • 1101
    • 1102
    • 1103
    • 1104
    • 1105
    • 1106
    • 1107
    • 1108
    • 1109
    • 1110
    • 1111
    • 1112
    • 1113
    • 1114
    • 1115
    • 1116
    • 1117
    • 1118
    • 1119
    • 1120
    • 1121
    • 1122
    • 1123
    • 1124
    • 1125
    • 1126
    • 1127
    • 1128
    • 1129
    • 1130
    • 1131
    • 1132
    • 1133
    • 1134
    • 1135
    • 1136
    • 1137
    • 1138
    • 1139
    • 1140
    • 1141
    • 1142
    • 1143
    • 1144
    • 1145
    • 1146
    • 1147
    • 1148
    • 1149
    • 1150
    • 1151
    • 1152
    • 1153
    • 1154
    • 1155
    • 1156
    • 1157
    • 1158
    • 1159
    • 1160
    • 1161
    • 1162
    • 1163
    • 1164
    • 1165
    • 1166
    • 1167
    • 1168
    • 1169
    • 1170
    • 1171
    • 1172
    • 1173
    • 1174
    • 1175
    • 1176
    • 1177
    • 1178
    • 1179
    • 1180
    • 1181
    • 1182
    • 1183
    • 1184
    • 1185
    • 1186
    • 1187
    • 1188
    • 1189
    • 1190
    • 1191
    • 1192
    • 1193
    • 1194
    • 1195
    • 1196
    • 1197
    • 1198
    • 1199
    • 1200
    • 1201
    • 1202
    • 1203
    • 1204
    • 1205
    • 1206
    • 1207
    • 1208
    • 1209
    • 1210
    • 1211
    • 1212
    • 1213
    • 1214
    • 1215
    • 1216
    • 1217
    • 1218
    • 1219
    • 1220
    • 1221
    • 1222
    • 1223
    • 1224
    • 1225
    • 1226
    • 1227
    • 1228
    • 1229
    • 1230
    • 1231
    • 1232
    • 1233
    • 1234
    • 1235
    • 1236
    • 1237
    • 1238
    • 1239
    • 1240
    • 1241
    • 1242
    • 1243
    • 1244
    • 1245
    • 1246
    • 1247
    • 1248
    • 1249
    • 1250
    • 1251
    • 1252
    • 1253
    • 1254
    • 1255
    • 1256
    • 1257
    • 1258
    • 1259
    • 1260
    • 1261
    • 1262
    • 1263
    • 1264
    • 1265
    • 1266
    • 1267
    • 1268
    • 1269
    • 1270
    • 1271
    • 1272
    • 1273
    • 1274
    • 1275
    • 1276
    • 1277
    • 1278
    • 1279
    • 1280
    • 1281
    • 1282
    • 1283
    • 1284
    • 1285
    • 1286
    • 1287
    • 1288
    • 1289
    • 1290
    • 1291
    • 1292
    • 1293
    • 1294
    • 1295
    • 1296
    • 1297
    • 1298
    • 1299
    • 1300
    • 1301
    • 1302
    • 1303
    • 1304
    • 1305
    • 1306
    • 1307
    • 1308
    • 1309
    • 1310
    • 1311
    • 1312
    • 1313
    • 1314
    • 1315
    • 1316
    • 1317
    • 1318
    • 1319
    • 1320
    • 1321
    • 1322
    • 1323
    • 1324
    • 1325
    • 1326
    • 1327
    • 1328
    • 1329
    • 1330
    • 1331
    • 1332
    • 1333
    • 1334
    • 1335
    • 1336
    • 1337
    • 1338
    • 1339
    • 1340
    • 1341
    • 1342
    • 1343
    • 1344
    • 1345
    • 1346
    • 1347
    • 1348
    • 1349
    • 1350
    • 1351
    • 1352
    • 1353
    • 1354
    • 1355
    • 1356
    • 1357
    • 1358
    • 1359
    • 1360
    • 1361
    • 1362
    • 1363
    • 1364
    • 1365
    • 1366
    • 1367
    • 1368
    • 1369
    • 1370
    • 1371
    • 1372
    • 1373
    • 1374
    • 1375
    • 1376
    • 1377
    • 1378
    • 1379
    • 1380
    • 1381
    • 1382
    • 1383
    • 1384
    • 1385
    • 1386
    • 1387
    • 1388
    • 1389
    • 1390
    • 1391
    • 1392
    • 1393
    • 1394
    • 1395
    • 1396
    • 1397
    • 1398
    • 1399
    • 1400
    • 1401
    • 1402
    • 1403
    • 1404
    • 1405
    • 1406
    • 1407
    • 1408
    • 1409
    • 1410
    • 1411
    • 1412
    • 1413
    • 1414
    • 1415
    • 1416
    • 1417
    • 1418
    • 1419
    • 1420
    • 1421
    • 1422
    • 1423
    • 1424
    • 1425
    • 1426
    • 1427
    • 1428
    • 1429
    • 1430
    • 1431
    • 1432
    • 1433
    • 1434
    • 1435
    • 1436
    • 1437
    • 1438
    • 1439
    • 1440
    • 1441
    • 1442
    • 1443
    • 1444
    • 1445
    • 1446
    • 1447
    • 1448
    • 1449
    • 1450
    • 1451
    • 1452
    • 1453
    • 1454
    • 1455
    • 1456
    • 1457
    • 1458
    • 1459
    • 1460
    • 1461
    • 1462
    • 1463
    • 1464
    • 1465
    • 1466
    • 1467
    • 1468
    • 1469
    • 1470
    • 1471
    • 1472
    • 1473
    • 1474
    • 1475
    • 1476
    • 1477
    • 1478
    • 1479
    • 1480
    • 1481
    • 1482
    • 1483
    • 1484
    • 1485
    • 1486
    • 1487
    • 1488
    • 1489
    • 1490
    • 1491
    • 1492
    • 1493
    • 1494
    • 1495
    • 1496
    • 1497
    • 1498
    • 1499
    • 1500
    • 1501
    • 1502
    • 1503
    • 1504
    • 1505
    • 1506
    • 1507
    • 1508
    • 1509
    • 1510
    • 1511
    • 1512
    • 1513
    • 1514
    • 1515
    • 1516
    • 1517
    • 1518
    • 1519
    • 1520
    • 1521
    • 1522
    • 1523
    • 1524
    • 1525
    • 1526
    • 1527
    • 1528
    • 1529
    • 1530
    • 1531
    • 1532
    • 1533
    • 1534
    • 1535
    • 1536
    • 1537
    • 1538
    • 1539
    • 1540
    • 1541
    • 1542
    • 1543
    • 1544
    • 1545
    • 1546
    • 1547
    • 1548
    • 1549
    • 1550
    • 1551
    • 1552
    • 1553
    • 1554
    • 1555
    • 1556
    • 1557
    • 1558
    • 1559
    • 1560
    • 1561
    • 1562
    • 1563
    • 1564
    • 1565
    • 1566
    • 1567
    • 1568
    • 1569
    • 1570
    • 1571
    • 1572
    • 1573
    • 1574
    • 1575
    • 1576
    • 1577
    • 1578
    • 1579
    • 1580
    • 1581
    • 1582
    • 1583
    • 1584
    • 1585
    • 1586
    • 1587
    • 1588
    • 1589
    • 1590
    • 1591
    • 1592
    • 1593
    • 1594
    • 1595
    • 1596
    • 1597
    • 1598
    • 1599
    • 1600
    • 1601
    • 1602
    • 1603
    • 1604
    • 1605
    • 1606
    • 1607
    • 1608
    • 1609
    • 1610
    • 1611
    • 1612
    • 1613
    • 1614
    • 1615
    • 1616
    • 1617
    • 1618
    • 1619
    • 1620
    • 1621
    • 1622
    • 1623
    • 1624
    • 1625
    • 1626
    • 1627
    • 1628
    • 1629
    • 1630
    • 1631
    • 1632
    • 1633
    • 1634
    • 1635
    • 1636
    • 1637
    • 1638
    • 1639
    • 1640
    • 1641
    • 1642
    • 1643
    • 1644
    • 1645
    • 1646
    • 1647
    • 1648
    • 1649
    • 1650
    • 1651
    • 1652
    • 1653
    • 1654
    • 1655
    • 1656
    /*
     * Copyright (C) 2006 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.applications.manageapplications;
    
    import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
    
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_ALL;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_BLOCKED;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_DISABLED;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_ENABLED;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_FREQUENT;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_INSTANT;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_PERSONAL;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_POWER_ALLOWLIST;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_POWER_ALLOWLIST_ALL;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_RECENT;
    import static com.android.settings.applications.manageapplications.AppFilterRegistry.FILTER_APPS_WORK;
    import static com.android.settings.search.actionbar.SearchMenuController.MENU_SEARCH;
    
    import android.annotation.Nullable;
    import android.annotation.StringRes;
    import android.app.Activity;
    import android.app.ActivityManager;
    import android.app.settings.SettingsEnums;
    import android.app.usage.IUsageStatsManager;
    import android.compat.annotation.ChangeId;
    import android.compat.annotation.LoggingOnly;
    import android.content.Context;
    import android.content.Intent;
    import android.content.pm.ApplicationInfo;
    import android.content.pm.PackageItemInfo;
    import android.content.pm.UserInfo;
    import android.net.Uri;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.os.ServiceManager;
    import android.os.UserHandle;
    import android.os.UserManager;
    import android.preference.PreferenceFrameLayout;
    import android.text.TextUtils;
    import android.util.ArraySet;
    import android.util.IconDrawableFactory;
    import android.util.Log;
    import android.view.LayoutInflater;
    import android.view.Menu;
    import android.view.MenuInflater;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemSelectedListener;
    import android.widget.Filter;
    import android.widget.FrameLayout;
    import android.widget.SearchView;
    import android.widget.Spinner;
    
    import androidx.annotation.NonNull;
    import androidx.annotation.VisibleForTesting;
    import androidx.annotation.WorkerThread;
    import androidx.coordinatorlayout.widget.CoordinatorLayout;
    import androidx.core.view.ViewCompat;
    import androidx.recyclerview.widget.LinearLayoutManager;
    import androidx.recyclerview.widget.RecyclerView;
    
    import com.android.internal.compat.IPlatformCompat;
    import com.android.settings.R;
    import com.android.settings.Settings;
    import com.android.settings.Settings.GamesStorageActivity;
    import com.android.settings.Settings.HighPowerApplicationsActivity;
    import com.android.settings.Settings.ManageExternalSourcesActivity;
    import com.android.settings.Settings.OverlaySettingsActivity;
    import com.android.settings.Settings.StorageUseActivity;
    import com.android.settings.Settings.UsageAccessSettingsActivity;
    import com.android.settings.Settings.WriteSettingsActivity;
    import com.android.settings.SettingsActivity;
    import com.android.settings.Utils;
    import com.android.settings.applications.AppInfoBase;
    import com.android.settings.applications.AppStateAlarmsAndRemindersBridge;
    import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
    import com.android.settings.applications.AppStateBaseBridge;
    import com.android.settings.applications.AppStateInstallAppsBridge;
    import com.android.settings.applications.AppStateManageExternalStorageBridge;
    import com.android.settings.applications.AppStateMediaManagementAppsBridge;
    import com.android.settings.applications.AppStateNotificationBridge;
    import com.android.settings.applications.AppStateNotificationBridge.NotificationsSentState;
    import com.android.settings.applications.AppStateOverlayBridge;
    import com.android.settings.applications.AppStatePowerBridge;
    import com.android.settings.applications.AppStateUsageBridge;
    import com.android.settings.applications.AppStateUsageBridge.UsageState;
    import com.android.settings.applications.AppStateWriteSettingsBridge;
    import com.android.settings.applications.AppStorageSettings;
    import com.android.settings.applications.UsageAccessDetails;
    import com.android.settings.applications.appinfo.AlarmsAndRemindersDetails;
    import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
    import com.android.settings.applications.appinfo.DrawOverlayDetails;
    import com.android.settings.applications.appinfo.ExternalSourcesDetails;
    import com.android.settings.applications.appinfo.ManageExternalStorageDetails;
    import com.android.settings.applications.appinfo.MediaManagementAppsDetails;
    import com.android.settings.applications.appinfo.WriteSettingsDetails;
    import com.android.settings.core.InstrumentedFragment;
    import com.android.settings.core.SubSettingLauncher;
    import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
    import com.android.settings.fuelgauge.HighPowerDetail;
    import com.android.settings.notification.ConfigureNotificationSettings;
    import com.android.settings.notification.NotificationBackend;
    import com.android.settings.notification.app.AppNotificationSettings;
    import com.android.settings.widget.LoadingViewController;
    import com.android.settings.wifi.AppStateChangeWifiStateBridge;
    import com.android.settings.wifi.ChangeWifiStateDetails;
    import com.android.settingslib.applications.ApplicationsState;
    import com.android.settingslib.applications.ApplicationsState.AppEntry;
    import com.android.settingslib.applications.ApplicationsState.AppFilter;
    import com.android.settingslib.applications.ApplicationsState.CompoundFilter;
    import com.android.settingslib.applications.ApplicationsState.VolumeFilter;
    import com.android.settingslib.applications.AppUtils;
    import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
    import com.android.settingslib.utils.ThreadUtils;
    import com.android.settingslib.widget.settingsspinner.SettingsSpinnerAdapter;
    
    import com.google.android.material.appbar.AppBarLayout;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Set;
    import java.util.HashSet;
    
    /**
     * Activity to pick an application that will be used to display installation information and
     * options to uninstall/delete user data for system applications. This activity
     * can be launched through Settings or via the ACTION_MANAGE_PACKAGE_STORAGE
     * intent.
     */
    public class ManageApplications extends InstrumentedFragment
            implements View.OnClickListener, OnItemSelectedListener, SearchView.OnQueryTextListener,
            MenuItem.OnActionExpandListener {
    
        static final String TAG = "ManageApplications";
        static final boolean DEBUG = Build.IS_DEBUGGABLE;
    
        // Intent extras.
        public static final String EXTRA_CLASSNAME = "classname";
        // Used for storage only.
        public static final String EXTRA_VOLUME_UUID = "volumeUuid";
        public static final String EXTRA_VOLUME_NAME = "volumeName";
        public static final String EXTRA_STORAGE_TYPE = "storageType";
        public static final String EXTRA_WORK_ID = "workId";
    
        private static final String EXTRA_SORT_ORDER = "sortOrder";
        private static final String EXTRA_SHOW_SYSTEM = "showSystem";
        private static final String EXTRA_HAS_ENTRIES = "hasEntries";
        private static final String EXTRA_HAS_BRIDGE = "hasBridge";
        private static final String EXTRA_FILTER_TYPE = "filterType";
        @VisibleForTesting
        static final String EXTRA_EXPAND_SEARCH_VIEW = "expand_search_view";
    
        // attributes used as keys when passing values to AppInfoDashboardFragment activity
        public static final String APP_CHG = "chg";
    
        // constant value that can be used to check return code from sub activity.
        private static final int INSTALLED_APP_DETAILS = 1;
        private static final int ADVANCED_SETTINGS = 2;
    
        public static final int SIZE_TOTAL = 0;
        public static final int SIZE_INTERNAL = 1;
        public static final int SIZE_EXTERNAL = 2;
    
        // Storage types. Used to determine what the extra item in the list of preferences is.
        public static final int STORAGE_TYPE_DEFAULT = 0; // Show all apps that are not categorized.
        public static final int STORAGE_TYPE_LEGACY = 1;  // Show apps even if they can be categorized.
    
        /**
         * Intents with action {@code android.settings.MANAGE_APP_OVERLAY_PERMISSION}
         * and data URI scheme {@code package} don't go to the app-specific screen for managing the
         * permission anymore. Instead, they redirect to this screen for managing all the apps that have
         * requested such permission.
         */
        @ChangeId
        @LoggingOnly
        private static final long CHANGE_RESTRICT_SAW_INTENT = 135920175L;
    
        // sort order
        @VisibleForTesting
        int mSortOrder = R.id.sort_order_alpha;
    
        // whether showing system apps.
        private boolean mShowSystem;
    
        private ApplicationsState mApplicationsState;
    
        public int mListType;
        private AppFilterItem mFilter;
        private ApplicationsAdapter mApplications;
    
        private View mLoadingContainer;
        private SearchView mSearchView;
    
        // Size resource used for packages whose size computation failed for some reason
        CharSequence mInvalidSizeStr;
    
        private String mCurrentPkgName;
        private int mCurrentUid;
    
        private Menu mOptionsMenu;
    
        public static final int LIST_TYPE_MAIN = 0;
        public static final int LIST_TYPE_NOTIFICATION = 1;
        public static final int LIST_TYPE_STORAGE = 3;
        public static final int LIST_TYPE_USAGE_ACCESS = 4;
        public static final int LIST_TYPE_HIGH_POWER = 5;
        public static final int LIST_TYPE_OVERLAY = 6;
        public static final int LIST_TYPE_WRITE_SETTINGS = 7;
        public static final int LIST_TYPE_MANAGE_SOURCES = 8;
        public static final int LIST_TYPE_GAMES = 9;
        public static final int LIST_TYPE_WIFI_ACCESS = 10;
        public static final int LIST_MANAGE_EXTERNAL_STORAGE = 11;
        public static final int LIST_TYPE_ALARMS_AND_REMINDERS = 12;
        public static final int LIST_TYPE_MEDIA_MANAGEMENT_APPS = 13;
    
        // List types that should show instant apps.
        public static final Set<Integer> LIST_TYPES_WITH_INSTANT = new ArraySet<>(Arrays.asList(
                LIST_TYPE_MAIN,
                LIST_TYPE_STORAGE));
    
        @VisibleForTesting
        View mSpinnerHeader;
        @VisibleForTesting
        FilterSpinnerAdapter mFilterAdapter;
        @VisibleForTesting
        RecyclerView mRecyclerView;
        // Whether or not search view is expanded.
        @VisibleForTesting
        boolean mExpandSearch;
    
        private View mRootView;
        private Spinner mFilterSpinner;
        private IUsageStatsManager mUsageStatsManager;
        private UserManager mUserManager;
        private NotificationBackend mNotificationBackend;
        private ResetAppsHelper mResetAppsHelper;
        private String mVolumeUuid;
        private int mStorageType;
        private boolean mIsWorkOnly;
        private int mWorkUserId;
        private boolean mIsPersonalOnly;
        private View mEmptyView;
        private int mFilterType;
        private AppBarLayout mAppBarLayout;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setHasOptionsMenu(true);
            final Activity activity = getActivity();
            mUserManager = activity.getSystemService(UserManager.class);
            mApplicationsState = ApplicationsState.getInstance(activity.getApplication());
    
            Intent intent = activity.getIntent();
            Bundle args = getArguments();
            int screenTitle = intent.getIntExtra(
                    SettingsActivity.EXTRA_SHOW_FRAGMENT_TITLE_RESID, R.string.all_apps);
            String className = args != null ? args.getString(EXTRA_CLASSNAME) : null;
            if (className == null) {
                className = intent.getComponent().getClassName();
            }
            if (className.equals(StorageUseActivity.class.getName())) {
                if (args != null && args.containsKey(EXTRA_VOLUME_UUID)) {
                    mVolumeUuid = args.getString(EXTRA_VOLUME_UUID);
                    mStorageType = args.getInt(EXTRA_STORAGE_TYPE, STORAGE_TYPE_DEFAULT);
                    mListType = LIST_TYPE_STORAGE;
                } else {
                    // No volume selected, display a normal list, sorted by size.
                    mListType = LIST_TYPE_MAIN;
                }
                mSortOrder = R.id.sort_order_size;
            } else if (className.equals(UsageAccessSettingsActivity.class.getName())) {
                mListType = LIST_TYPE_USAGE_ACCESS;
                screenTitle = R.string.usage_access;
            } else if (className.equals(HighPowerApplicationsActivity.class.getName())) {
                mListType = LIST_TYPE_HIGH_POWER;
                // Default to showing system.
                mShowSystem = true;
                screenTitle = R.string.high_power_apps;
            } else if (className.equals(OverlaySettingsActivity.class.getName())) {
                mListType = LIST_TYPE_OVERLAY;
                screenTitle = R.string.system_alert_window_settings;
    
                reportIfRestrictedSawIntent(intent);
            } else if (className.equals(WriteSettingsActivity.class.getName())) {
                mListType = LIST_TYPE_WRITE_SETTINGS;
                screenTitle = R.string.write_settings;
            } else if (className.equals(ManageExternalSourcesActivity.class.getName())) {
                mListType = LIST_TYPE_MANAGE_SOURCES;
                screenTitle = R.string.install_other_apps;
            } else if (className.equals(GamesStorageActivity.class.getName())) {
                mListType = LIST_TYPE_GAMES;
                mSortOrder = R.id.sort_order_size;
            } else if (className.equals(Settings.ChangeWifiStateActivity.class.getName())) {
                mListType = LIST_TYPE_WIFI_ACCESS;
                screenTitle = R.string.change_wifi_state_title;
            } else if (className.equals(Settings.ManageExternalStorageActivity.class.getName())) {
                mListType = LIST_MANAGE_EXTERNAL_STORAGE;
                screenTitle = R.string.manage_external_storage_title;
            }  else if (className.equals(Settings.MediaManagementAppsActivity.class.getName())) {
                mListType = LIST_TYPE_MEDIA_MANAGEMENT_APPS;
                screenTitle = R.string.media_management_apps_title;
            } else if (className.equals(Settings.AlarmsAndRemindersActivity.class.getName())) {
                mListType = LIST_TYPE_ALARMS_AND_REMINDERS;
                screenTitle = R.string.alarms_and_reminders_title;
            } else if (className.equals(Settings.NotificationAppListActivity.class.getName())) {
                mListType = LIST_TYPE_NOTIFICATION;
                mUsageStatsManager = IUsageStatsManager.Stub.asInterface(
                        ServiceManager.getService(Context.USAGE_STATS_SERVICE));
                mNotificationBackend = new NotificationBackend();
                mSortOrder = R.id.sort_order_recent_notification;
                screenTitle = R.string.app_notifications_title;
            } else {
                if (screenTitle == -1) {
                    screenTitle = R.string.all_apps;
                }
                mListType = LIST_TYPE_MAIN;
            }
            final AppFilterRegistry appFilterRegistry = AppFilterRegistry.getInstance();
            mFilter = appFilterRegistry.get(appFilterRegistry.getDefaultFilterType(mListType));
            mIsPersonalOnly = args != null ? args.getInt(ProfileSelectFragment.EXTRA_PROFILE)
                    == ProfileSelectFragment.ProfileType.PERSONAL : false;
            mIsWorkOnly = args != null ? args.getInt(ProfileSelectFragment.EXTRA_PROFILE)
                    == ProfileSelectFragment.ProfileType.WORK : false;
            mWorkUserId = args != null ? args.getInt(EXTRA_WORK_ID) : UserHandle.myUserId();
            if (mIsWorkOnly && mWorkUserId == UserHandle.myUserId()) {
                mWorkUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
            }
    
            mExpandSearch = activity.getIntent().getBooleanExtra(EXTRA_EXPAND_SEARCH_VIEW, false);
    
            if (savedInstanceState != null) {
                mSortOrder = savedInstanceState.getInt(EXTRA_SORT_ORDER, mSortOrder);
                mShowSystem = savedInstanceState.getBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
                mFilterType =
                        savedInstanceState.getInt(EXTRA_FILTER_TYPE, AppFilterRegistry.FILTER_APPS_ALL);
                mExpandSearch = savedInstanceState.getBoolean(EXTRA_EXPAND_SEARCH_VIEW);
            }
    
            mInvalidSizeStr = activity.getText(R.string.invalid_size_value);
    
            mResetAppsHelper = new ResetAppsHelper(activity);
    
            if (screenTitle > 0) {
                activity.setTitle(screenTitle);
            }
        }
    
        private void reportIfRestrictedSawIntent(Intent intent) {
            try {
                Uri data = intent.getData();
                if (data == null || !TextUtils.equals("package", data.getScheme())) {
                    // Not a restricted intent
                    return;
                }
                IBinder activityToken = getActivity().getActivityToken();
                int callingUid = ActivityManager.getService().getLaunchedFromUid(activityToken);
                if (callingUid == -1) {
                    Log.w(TAG, "Error obtaining calling uid");
                    return;
                }
                IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
                        ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
                if (platformCompat == null) {
                    Log.w(TAG, "Error obtaining IPlatformCompat service");
                    return;
                }
                platformCompat.reportChangeByUid(CHANGE_RESTRICT_SAW_INTENT, callingUid);
            } catch (RemoteException e) {
                Log.w(TAG, "Error reporting SAW intent restriction", e);
            }
        }
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            if (mListType == LIST_TYPE_OVERLAY && !Utils.isSystemAlertWindowEnabled(getContext())) {
                mRootView = inflater.inflate(R.layout.manage_applications_apps_unsupported, null);
                setHasOptionsMenu(false);
                return mRootView;
            }
    
            mRootView = inflater.inflate(R.layout.manage_applications_apps, null);
            mLoadingContainer = mRootView.findViewById(R.id.loading_container);
            mEmptyView = mRootView.findViewById(android.R.id.empty);
            mRecyclerView = mRootView.findViewById(R.id.apps_list);
    
            mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter,
                    savedInstanceState);
            if (savedInstanceState != null) {
                mApplications.mHasReceivedLoadEntries =
                        savedInstanceState.getBoolean(EXTRA_HAS_ENTRIES, false);
                mApplications.mHasReceivedBridgeCallback =
                        savedInstanceState.getBoolean(EXTRA_HAS_BRIDGE, false);
            }
            mRecyclerView.setItemAnimator(null);
            mRecyclerView.setLayoutManager(new LinearLayoutManager(
                    getContext(), RecyclerView.VERTICAL, false /* reverseLayout */));
            mRecyclerView.setAdapter(mApplications);
            android.util.Log.d("xin.wang", "onCreateView:mRecyclerView.setAdapter-> " + Thread.currentThread().getName());
    
            // We have to do this now because PreferenceFrameLayout looks at it
            // only when the view is added.
            if (container instanceof PreferenceFrameLayout) {
                ((PreferenceFrameLayout.LayoutParams) mRootView.getLayoutParams()).removeBorders = true;
            }
    
            createHeader();
    
            mResetAppsHelper.onRestoreInstanceState(savedInstanceState);
    
            mAppBarLayout = getActivity().findViewById(R.id.app_bar);
            disableToolBarScrollableBehavior();
    
            return mRootView;
        }
    
    
        @VisibleForTesting
        void createHeader() {
            final Activity activity = getActivity();
            final FrameLayout pinnedHeader = mRootView.findViewById(R.id.pinned_header);
            mSpinnerHeader = activity.getLayoutInflater()
                    .inflate(R.layout.manage_apps_filter_spinner, pinnedHeader, false);
            mFilterSpinner = mSpinnerHeader.findViewById(R.id.filter_spinner);
            mFilterAdapter = new FilterSpinnerAdapter(this);
            mFilterSpinner.setAdapter(mFilterAdapter);
            mFilterSpinner.setOnItemSelectedListener(this);
            mFilterSpinner.setVisibility(View.GONE);
            pinnedHeader.addView(mSpinnerHeader, 0);
    
            final AppFilterRegistry appFilterRegistry = AppFilterRegistry.getInstance();
            final int filterType = appFilterRegistry.getDefaultFilterType(mListType);
            android.util.Log.d("xin.wang", "createHeader:-> filterType -> " + mListType + "<- filterType -> " + filterType); //filterType = 4 -> FILTER_APPS_ALL
            android.util.Log.d("xin.wang", "createHeader:->mFilterOptions.size()-> " + mFilterAdapter.getCount());
            //mFilterAdapter.enableFilter(filterType);    //filterType = 4 -> FILTER_APPS_ALL
    
            if (mListType == LIST_TYPE_MAIN) {
                if (UserManager.get(getActivity()).getUserProfiles().size() > 1 && !mIsWorkOnly
                        && !mIsPersonalOnly) {
                    mFilterAdapter.enableFilter(FILTER_APPS_PERSONAL);
                    //mFilterAdapter.enableFilter(FILTER_APPS_WORK);
                }
            }
    
            if (mListType == LIST_TYPE_NOTIFICATION) {
                mFilterAdapter.enableFilter(FILTER_APPS_RECENT);
                mFilterAdapter.enableFilter(FILTER_APPS_FREQUENT);
                mFilterAdapter.enableFilter(FILTER_APPS_BLOCKED);
                mFilterAdapter.enableFilter(FILTER_APPS_ALL);
            }
            if (mListType == LIST_TYPE_HIGH_POWER) {
                mFilterAdapter.enableFilter(FILTER_APPS_POWER_ALLOWLIST_ALL);
            }
    
            setCompositeFilter();
        }
    
        @VisibleForTesting
        @Nullable
        static AppFilter getCompositeFilter(int listType, int storageType, String volumeUuid) {
            AppFilter filter = new VolumeFilter(volumeUuid);
            if (listType == LIST_TYPE_STORAGE) {
                if (storageType == STORAGE_TYPE_DEFAULT) {
                    filter = new CompoundFilter(ApplicationsState.FILTER_APPS_EXCEPT_GAMES, filter);
                }
                return filter;
            }
            if (listType == LIST_TYPE_GAMES) {
                return new CompoundFilter(ApplicationsState.FILTER_GAMES, filter);
            }
            return null;
        }
    
        @Override
        public int getMetricsCategory() {
            switch (mListType) {
                case LIST_TYPE_MAIN:
                    return SettingsEnums.MANAGE_APPLICATIONS;
                case LIST_TYPE_NOTIFICATION:
                    return SettingsEnums.MANAGE_APPLICATIONS_NOTIFICATIONS;
                case LIST_TYPE_STORAGE:
                    return SettingsEnums.APPLICATIONS_STORAGE_APPS;
                case LIST_TYPE_GAMES:
                    return SettingsEnums.APPLICATIONS_STORAGE_GAMES;
                case LIST_TYPE_USAGE_ACCESS:
                    return SettingsEnums.USAGE_ACCESS;
                case LIST_TYPE_HIGH_POWER:
                    return SettingsEnums.APPLICATIONS_HIGH_POWER_APPS;
                case LIST_TYPE_OVERLAY:
                    return SettingsEnums.SYSTEM_ALERT_WINDOW_APPS;
                case LIST_TYPE_WRITE_SETTINGS:
                    return SettingsEnums.SYSTEM_ALERT_WINDOW_APPS;
                case LIST_TYPE_MANAGE_SOURCES:
                    return SettingsEnums.MANAGE_EXTERNAL_SOURCES;
                case LIST_TYPE_WIFI_ACCESS:
                    return SettingsEnums.CONFIGURE_WIFI;
                case LIST_MANAGE_EXTERNAL_STORAGE:
                    return SettingsEnums.MANAGE_EXTERNAL_STORAGE;
                case LIST_TYPE_ALARMS_AND_REMINDERS:
                    return SettingsEnums.ALARMS_AND_REMINDERS;
                case LIST_TYPE_MEDIA_MANAGEMENT_APPS:
                    return SettingsEnums.MEDIA_MANAGEMENT_APPS;
                default:
                    return SettingsEnums.PAGE_UNKNOWN;
            }
        }
    
        @Override
        public void onStart() {
            super.onStart();
            updateView();
            if (mApplications != null) {
                mApplications.resume(mSortOrder);
                mApplications.updateLoading();
            }
        }
    
        @Override
        public void onSaveInstanceState(Bundle outState) {
            super.onSaveInstanceState(outState);
            mResetAppsHelper.onSaveInstanceState(outState);
            outState.putInt(EXTRA_SORT_ORDER, mSortOrder);
            outState.putInt(EXTRA_FILTER_TYPE, mFilter.getFilterType());
            outState.putBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
            //add bug 1702049:NullPointerException on a null object reference
            if (mApplications != null) {
                outState.putBoolean(EXTRA_HAS_ENTRIES, mApplications.mHasReceivedLoadEntries);
                outState.putBoolean(EXTRA_HAS_BRIDGE, mApplications.mHasReceivedBridgeCallback);
                if (mSearchView != null) {
                    outState.putBoolean(EXTRA_EXPAND_SEARCH_VIEW, !mSearchView.isIconified());
                }
                mApplications.onSaveInstanceState(outState);
            }
        }
    
        @Override
        public void onStop() {
            super.onStop();
            if (mApplications != null) {
                mApplications.pause();
            }
            mResetAppsHelper.stop();
        }
    
        @Override
        public void onDestroyView() {
            super.onDestroyView();
    
            if (mApplications != null) {
                mApplications.release();
            }
            mRootView = null;
        }
    
        @Override
        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (requestCode == INSTALLED_APP_DETAILS && mCurrentPkgName != null) {
                if (mListType == LIST_TYPE_NOTIFICATION) {
                    mApplications.mExtraInfoBridge.forceUpdate(mCurrentPkgName, mCurrentUid);
                } else if (mListType == LIST_TYPE_HIGH_POWER || mListType == LIST_TYPE_OVERLAY
                        || mListType == LIST_TYPE_WRITE_SETTINGS) {
                    mApplications.mExtraInfoBridge.forceUpdate(mCurrentPkgName, mCurrentUid);
                } else {
                    mApplicationsState.requestSize(mCurrentPkgName, UserHandle.getUserId(mCurrentUid));
                }
            }
        }
    
        private void setCompositeFilter() {
            AppFilter compositeFilter = getCompositeFilter(mListType, mStorageType, mVolumeUuid);
            if (compositeFilter == null) {
                compositeFilter = mFilter.getFilter();
            }
            if (mIsWorkOnly) {
                compositeFilter = new CompoundFilter(compositeFilter, ApplicationsState.FILTER_WORK);
            }
            if (mIsPersonalOnly) {
                compositeFilter = new CompoundFilter(compositeFilter,
                        ApplicationsState.FILTER_PERSONAL);
            }
            mApplications.setCompositeFilter(compositeFilter);
        }
    
        // utility method used to start sub activity
        private void startApplicationDetailsActivity() {
            switch (mListType) {
                case LIST_TYPE_NOTIFICATION:
                    startAppInfoFragment(AppNotificationSettings.class, R.string.notifications_title);
                    break;
                case LIST_TYPE_USAGE_ACCESS:
                    startAppInfoFragment(UsageAccessDetails.class, R.string.usage_access);
                    break;
                case LIST_TYPE_STORAGE:
                    startAppInfoFragment(AppStorageSettings.class, R.string.storage_settings);
                    break;
                case LIST_TYPE_HIGH_POWER:
                    HighPowerDetail.show(this, mCurrentUid, mCurrentPkgName, INSTALLED_APP_DETAILS);
                    break;
                case LIST_TYPE_OVERLAY:
                    startAppInfoFragment(DrawOverlayDetails.class, R.string.overlay_settings);
                    break;
                case LIST_TYPE_WRITE_SETTINGS:
                    startAppInfoFragment(WriteSettingsDetails.class, R.string.write_system_settings);
                    break;
                case LIST_TYPE_MANAGE_SOURCES:
                    startAppInfoFragment(ExternalSourcesDetails.class, R.string.install_other_apps);
                    break;
                case LIST_TYPE_GAMES:
                    startAppInfoFragment(AppStorageSettings.class, R.string.game_storage_settings);
                    break;
                case LIST_TYPE_WIFI_ACCESS:
                    startAppInfoFragment(ChangeWifiStateDetails.class,
                            R.string.change_wifi_state_title);
                    break;
                case LIST_MANAGE_EXTERNAL_STORAGE:
                    startAppInfoFragment(ManageExternalStorageDetails.class,
                            R.string.manage_external_storage_title);
                    break;
                case LIST_TYPE_ALARMS_AND_REMINDERS:
                    startAppInfoFragment(AlarmsAndRemindersDetails.class,
                            R.string.alarms_and_reminders_label);
                    break;
                case LIST_TYPE_MEDIA_MANAGEMENT_APPS:
                    startAppInfoFragment(MediaManagementAppsDetails.class,
                            R.string.media_management_apps_title);
                    break;
                // TODO: Figure out if there is a way where we can spin up the profile's settings
                // process ahead of time, to avoid a long load of data when user clicks on a managed
                // app. Maybe when they load the list of apps that contains managed profile apps.
                default:
                    startAppInfoFragment(
                            AppInfoDashboardFragment.class, R.string.application_info_label);
                    break;
            }
        }
    
        private void startAppInfoFragment(Class<?> fragment, int titleRes) {
            AppInfoBase.startAppInfoFragment(fragment, titleRes, mCurrentPkgName, mCurrentUid, this,
                    INSTALLED_APP_DETAILS, getMetricsCategory());
        }
    
        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            final Activity activity = getActivity();
            if (activity == null) {
                return;
            }
            mOptionsMenu = menu;
            inflater.inflate(R.menu.manage_apps, menu);
    
            final MenuItem searchMenuItem = menu.findItem(R.id.search_app_list_menu);
            if (searchMenuItem != null) {
                searchMenuItem.setOnActionExpandListener(this);
                mSearchView = (SearchView) searchMenuItem.getActionView();
                mSearchView.setQueryHint(getText(R.string.search_settings));
                mSearchView.setOnQueryTextListener(this);
                if (mExpandSearch) {
                    searchMenuItem.expandActionView();
                }
            }
    
            updateOptionsMenu();
        }
    
        @Override
        public boolean onMenuItemActionExpand(MenuItem item) {
            // To prevent a large space on tool bar.
            mAppBarLayout.setExpanded(false /*expanded*/, false /*animate*/);
            // To prevent user can expand the collapsing tool bar view.
            ViewCompat.setNestedScrollingEnabled(mRecyclerView, false);
            return true;
        }
    
        @Override
        public boolean onMenuItemActionCollapse(MenuItem item) {
            // We keep the collapsed status after user cancel the search function.
            mAppBarLayout.setExpanded(false /*expanded*/, false /*animate*/);
            ViewCompat.setNestedScrollingEnabled(mRecyclerView, true);
            return true;
        }
    
        @Override
        public void onPrepareOptionsMenu(Menu menu) {
            updateOptionsMenu();
        }
    
        @Override
        public void onDestroyOptionsMenu() {
            mOptionsMenu = null;
        }
    
        @StringRes
        int getHelpResource() {
            switch (mListType) {
                case LIST_TYPE_NOTIFICATION:
                    return R.string.help_uri_notifications;
                case LIST_TYPE_USAGE_ACCESS:
                    return R.string.help_url_usage_access;
                case LIST_TYPE_STORAGE:
                    return R.string.help_uri_apps_storage;
                case LIST_TYPE_HIGH_POWER:
                    return R.string.help_uri_apps_high_power;
                case LIST_TYPE_OVERLAY:
                    return R.string.help_uri_apps_overlay;
                case LIST_TYPE_WRITE_SETTINGS:
                    return R.string.help_uri_apps_write_settings;
                case LIST_TYPE_MANAGE_SOURCES:
                    return R.string.help_uri_apps_manage_sources;
                case LIST_TYPE_GAMES:
                    return R.string.help_uri_apps_overlay;
                case LIST_TYPE_WIFI_ACCESS:
                    return R.string.help_uri_apps_wifi_access;
                case LIST_MANAGE_EXTERNAL_STORAGE:
                    return R.string.help_uri_manage_external_storage;
                case LIST_TYPE_ALARMS_AND_REMINDERS:
                    return R.string.help_uri_alarms_and_reminders;
                case LIST_TYPE_MEDIA_MANAGEMENT_APPS:
                    return R.string.help_uri_media_management_apps;
                default:
                case LIST_TYPE_MAIN:
                    return R.string.help_uri_apps;
            }
        }
    
        void updateOptionsMenu() {
            if (mOptionsMenu == null) {
                return;
            }
            mOptionsMenu.findItem(R.id.advanced).setVisible(false);
    
            mOptionsMenu.findItem(R.id.sort_order_alpha).setVisible(mListType == LIST_TYPE_STORAGE
                    && mSortOrder != R.id.sort_order_alpha);
            mOptionsMenu.findItem(R.id.sort_order_size).setVisible(mListType == LIST_TYPE_STORAGE
                    && mSortOrder != R.id.sort_order_size);
    
            mOptionsMenu.findItem(R.id.show_system).setVisible(!mShowSystem
                    && mListType != LIST_TYPE_HIGH_POWER && wheatherShowSystemOption());
            mOptionsMenu.findItem(R.id.hide_system).setVisible(mShowSystem
                    && mListType != LIST_TYPE_HIGH_POWER && wheatherShowSystemOption());
            mOptionsMenu.findItem(R.id.reset_app_preferences).setVisible(mListType == LIST_TYPE_MAIN);
    
            // Hide notification menu items, because sorting happens when filtering
            mOptionsMenu.findItem(R.id.sort_order_recent_notification).setVisible(false);
            mOptionsMenu.findItem(R.id.sort_order_frequent_notification).setVisible(false);
            final MenuItem searchItem = mOptionsMenu.findItem(MENU_SEARCH);
            if (searchItem != null) {
                searchItem.setVisible(false);
            }
        }
    
        //hide the optionsmenu of hide-system and show-system in the work interface
        private boolean wheatherShowSystemOption() {
            boolean hasManageProfile = false;
            List<UserInfo> users = mUserManager.getUsers();
            android.util.Log.d("xin.wang", "wheatherShowSystemOption: " + users + "<- users.size->" + users.size());
            for(UserInfo user : users){
                if (user.isManagedProfile()) {
                    hasManageProfile = true;
                    break;
                }
            }
            if (mIsWorkOnly && !mIsPersonalOnly) {
                if (!hasManageProfile) {
                    return false;
                }
            }
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            int menuId = item.getItemId();
            int i = item.getItemId();
            if (i == R.id.sort_order_alpha || i == R.id.sort_order_size) {
                if (mApplications != null) {
                    mApplications.rebuild(menuId);
                }
            } else if (i == R.id.show_system || i == R.id.hide_system) {
                mShowSystem = !mShowSystem;
                mApplications.rebuild();
            } else if (i == R.id.reset_app_preferences) {
                mResetAppsHelper.buildResetDialog();
                return true;
            } else if (i == R.id.advanced) {
                if (mListType == LIST_TYPE_NOTIFICATION) {
                    new SubSettingLauncher(getContext())
                            .setDestination(ConfigureNotificationSettings.class.getName())
                            .setTitleRes(R.string.configure_notification_settings)
                            .setSourceMetricsCategory(getMetricsCategory())
                            .setResultListener(this, ADVANCED_SETTINGS)
                            .launch();
                } else {
                    Intent intent = new Intent(
                            android.provider.Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS);
                    startActivityForResult(intent, ADVANCED_SETTINGS);
                }
                return true;
            } else {// Handle the home button
                return false;
            }
            updateOptionsMenu();
            return true;
        }
    
        @Override
        public void onClick(View view) {
            if (mApplications == null) {
                return;
            }
            final int position = mRecyclerView.getChildAdapterPosition(view);
    
            if (position == RecyclerView.NO_POSITION) {
                Log.w(TAG, "Cannot find position for child, skipping onClick handling");
                return;
            }
            if (mApplications.getApplicationCount() > position) {
                ApplicationsState.AppEntry entry = mApplications.getAppEntry(position);
                mCurrentPkgName = entry.info.packageName;
                mCurrentUid = entry.info.uid;
                startApplicationDetailsActivity();
                // We disable the scrolling ability in onMenuItemActionCollapse, we should recover it
                // if user selects any app item.
                ViewCompat.setNestedScrollingEnabled(mRecyclerView, true);
            }
        }
    
        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            mFilter = mFilterAdapter.getFilter(position);
            setCompositeFilter();
            mApplications.setFilter(mFilter);
    
            if (DEBUG) {
                Log.d(TAG, "Selecting filter " + getContext().getText(mFilter.getTitle()));
            }
        }
    
        @Override
        public void onNothingSelected(AdapterView<?> parent) {
        }
    
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }
    
        @Override
        public boolean onQueryTextChange(String newText) {
            mApplications.filterSearch(newText);
            return false;
        }
    
        public void updateView() {
            updateOptionsMenu();
            final Activity host = getActivity();
            if (host != null) {
                host.invalidateOptionsMenu();
            }
        }
    
        public void setHasDisabled(boolean hasDisabledApps) {
            if (mListType != LIST_TYPE_MAIN) {
                return;
            }
            mFilterAdapter.setFilterEnabled(FILTER_APPS_ENABLED, hasDisabledApps);
            mFilterAdapter.setFilterEnabled(FILTER_APPS_DISABLED, hasDisabledApps);
        }
    
        public void setHasInstant(boolean haveInstantApps) {
            if (LIST_TYPES_WITH_INSTANT.contains(mListType)) {
                mFilterAdapter.setFilterEnabled(FILTER_APPS_INSTANT, haveInstantApps);
            }
        }
    
        private void disableToolBarScrollableBehavior() {
            final CoordinatorLayout.LayoutParams params =
                    (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams();
            final AppBarLayout.Behavior behavior = new AppBarLayout.Behavior();
            behavior.setDragCallback(
                    new AppBarLayout.Behavior.DragCallback() {
                        @Override
                        public boolean canDrag(@NonNull AppBarLayout appBarLayout) {
                            return false;
                        }
                    });
            params.setBehavior(behavior);
        }
    
        static class FilterSpinnerAdapter extends SettingsSpinnerAdapter<CharSequence> {
    
            private final ManageApplications mManageApplications;
            private final Context mContext;
    
            // Use ArrayAdapter for view logic, but have our own list for managing
            // the options available.
            private final ArrayList<AppFilterItem> mFilterOptions = new ArrayList<>();
    
            public FilterSpinnerAdapter(ManageApplications manageApplications) {
                super(manageApplications.getContext());
                mContext = manageApplications.getContext();
                mManageApplications = manageApplications;
            }
    
            public AppFilterItem getFilter(int position) {
                return mFilterOptions.get(position);
            }
    
            public void setFilterEnabled(@AppFilterRegistry.FilterType int filter, boolean enabled) {
                if (enabled) {
                    enableFilter(filter);
                } else {
                    disableFilter(filter);
                }
            }
    
            public void enableFilter(@AppFilterRegistry.FilterType int filterType) {
                final AppFilterItem filter = AppFilterRegistry.getInstance().get(filterType);
                if (mFilterOptions.contains(filter)) {
                    return;
                }
                if (DEBUG) {
                    Log.d(TAG, "Enabling filter " + mContext.getText(filter.getTitle()));
                }
                mFilterOptions.add(filter);
                Collections.sort(mFilterOptions);
                updateFilterView(mFilterOptions.size() > 1);
                notifyDataSetChanged();
                if (mFilterOptions.size() == 1) {
                    if (DEBUG) {
                        Log.d(TAG, "Auto selecting filter " + filter + " " + mContext.getText(
                                filter.getTitle()));
                    }
                    mManageApplications.mFilterSpinner.setSelection(0);
                    mManageApplications.onItemSelected(null, null, 0, 0);
                }
                if (mFilterOptions.size() > 1) {
                    final AppFilterItem previousFilter = AppFilterRegistry.getInstance().get(
                            mManageApplications.mFilterType);
                    final int index = mFilterOptions.indexOf(previousFilter);
                    if (index != -1) {
                        android.util.Log.d("xin.wang", "enableFilter: previousFilter -> " + previousFilter + "<- index -> " + index);
                        mManageApplications.mFilterSpinner.setSelection(index);
                        mManageApplications.onItemSelected(null, null, index, 0);
                    }
                }
            }
    
            public void disableFilter(@AppFilterRegistry.FilterType int filterType) {
                final AppFilterItem filter = AppFilterRegistry.getInstance().get(filterType);
                if (!mFilterOptions.remove(filter)) {
                    return;
                }
                if (DEBUG) {
                    Log.d(TAG, "Disabling filter " + filter + " " + mContext.getText(
                            filter.getTitle()));
                }
                Collections.sort(mFilterOptions);
                updateFilterView(mFilterOptions.size() > 1);
                notifyDataSetChanged();
                if (mManageApplications.mFilter == filter) {
                    if (mFilterOptions.size() > 0) {
                        if (DEBUG) {
                            Log.d(TAG, "Auto selecting filter " + mFilterOptions.get(0)
                                    + mContext.getText(mFilterOptions.get(0).getTitle()));
                        }
                        android.util.Log.d("xin.wang", "disableFilter: Auto selecting filter -> " + mContext.getText(mFilterOptions.get(0).getTitle()));
                        mManageApplications.mFilterSpinner.setSelection(0);
                        mManageApplications.onItemSelected(null, null, 0, 0);
                    }
                }
            }
    
            @Override
            public int getCount() {
                android.util.Log.d("xin.wang", "getCount: mFilterOptions.size()->" + mFilterOptions.size());
                return mFilterOptions.size();
            }
    
            @Override
            public CharSequence getItem(int position) {
                return mContext.getText(mFilterOptions.get(position).getTitle());
            }
    
            @VisibleForTesting
            void updateFilterView(boolean hasFilter) {
                // If we need to add a floating filter in this screen, we should have an extra top
                // padding for putting floating filter view. Otherwise, the content of list will be
                // overlapped by floating filter.
                if (hasFilter) {
                    mManageApplications.mSpinnerHeader.setVisibility(View.VISIBLE);
                } else {
                    mManageApplications.mSpinnerHeader.setVisibility(View.GONE);
                }
            }
        }
    
        static class ApplicationsAdapter extends RecyclerView.Adapter<ApplicationViewHolder>
                implements ApplicationsState.Callbacks, AppStateBaseBridge.Callback {
    
            private static final String STATE_LAST_SCROLL_INDEX = "state_last_scroll_index";
            private static final int VIEW_TYPE_APP = 0;
            private static final int VIEW_TYPE_EXTRA_VIEW = 1;
    
            private final ApplicationsState mState;
            private final ApplicationsState.Session mSession;
            private final ManageApplications mManageApplications;
            private final Context mContext;
            private final AppStateBaseBridge mExtraInfoBridge;
            private final LoadingViewController mLoadingViewController;
            private final IconDrawableFactory mIconDrawableFactory;
    
            private AppFilterItem mAppFilter;
            private ArrayList<ApplicationsState.AppEntry> mEntries;
            private ArrayList<ApplicationsState.AppEntry> mOriginalEntries;
            private boolean mResumed;
            private int mLastSortMode = -1;
            private int mWhichSize = SIZE_TOTAL;
            private AppFilter mCompositeFilter;
            private boolean mHasReceivedLoadEntries;
            private boolean mHasReceivedBridgeCallback;
            private SearchFilter mSearchFilter;
            private PowerAllowlistBackend mBackend;
            private HashSet<String> mSupportAppClone;
            // This is to remember and restore the last scroll position when this
            // fragment is paused. We need this special handling because app entries are added gradually
            // when we rebuild the list after the user made some changes, like uninstalling an app.
            private int mLastIndex = -1;
    
            @VisibleForTesting
            OnScrollListener mOnScrollListener;
            private RecyclerView mRecyclerView;
    
    
            public ApplicationsAdapter(ApplicationsState state, ManageApplications manageApplications,
                    AppFilterItem appFilter, Bundle savedInstanceState) {
                setHasStableIds(true);
                mState = state;
                mSession = state.newSession(this);
                mManageApplications = manageApplications;
                mLoadingViewController = new LoadingViewController(
                        mManageApplications.mLoadingContainer,
                        mManageApplications.mRecyclerView,
                        mManageApplications.mEmptyView
                );
                mContext = manageApplications.getActivity();
                mIconDrawableFactory = IconDrawableFactory.newInstance(mContext);
                mAppFilter = appFilter;
                mBackend = PowerAllowlistBackend.getInstance(mContext);
                String[] supportApps = mContext.getResources().getStringArray(com.unisoc.internal.R.array.support_app_clone);
                mSupportAppClone = new HashSet<String>(Arrays.asList(supportApps));
                android.util.Log.d("xin.wang", "ApplicationsAdapter -> mSupportAppClone -> : " + mSupportAppClone);
                if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
                    mExtraInfoBridge = new AppStateNotificationBridge(mContext, mState, this,
                            manageApplications.mUsageStatsManager,
                            manageApplications.mUserManager,
                            manageApplications.mNotificationBackend);
                } else if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
                    mExtraInfoBridge = new AppStateUsageBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_HIGH_POWER) {
                    mBackend.refreshList();
                    mExtraInfoBridge = new AppStatePowerBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_OVERLAY) {
                    mExtraInfoBridge = new AppStateOverlayBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_WRITE_SETTINGS) {
                    mExtraInfoBridge = new AppStateWriteSettingsBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_MANAGE_SOURCES) {
                    mExtraInfoBridge = new AppStateInstallAppsBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_WIFI_ACCESS) {
                    mExtraInfoBridge = new AppStateChangeWifiStateBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_MANAGE_EXTERNAL_STORAGE) {
                    mExtraInfoBridge = new AppStateManageExternalStorageBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_ALARMS_AND_REMINDERS) {
                    mExtraInfoBridge = new AppStateAlarmsAndRemindersBridge(mContext, mState, this);
                } else if (mManageApplications.mListType == LIST_TYPE_MEDIA_MANAGEMENT_APPS) {
                    mExtraInfoBridge = new AppStateMediaManagementAppsBridge(mContext, mState, this);
                } else {
                    mExtraInfoBridge = null;
                }
                if (savedInstanceState != null) {
                    mLastIndex = savedInstanceState.getInt(STATE_LAST_SCROLL_INDEX);
                }
            }
    
            @Override
            public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
                super.onAttachedToRecyclerView(recyclerView);
                mRecyclerView = recyclerView;
                mOnScrollListener = new OnScrollListener(this);
                mRecyclerView.addOnScrollListener(mOnScrollListener);
            }
    
            @Override
            public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
                super.onDetachedFromRecyclerView(recyclerView);
                mRecyclerView.removeOnScrollListener(mOnScrollListener);
                mOnScrollListener = null;
                mRecyclerView = null;
            }
    
            public void setCompositeFilter(AppFilter compositeFilter) {
                mCompositeFilter = compositeFilter;
                rebuild();
            }
    
            public void setFilter(AppFilterItem appFilter) {
                mAppFilter = appFilter;
    
                // Notification filters require resorting the list
                if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
                    if (FILTER_APPS_FREQUENT == appFilter.getFilterType()) {
                        rebuild(R.id.sort_order_frequent_notification);
                    } else if (FILTER_APPS_RECENT == appFilter.getFilterType()) {
                        rebuild(R.id.sort_order_recent_notification);
                    } else if (FILTER_APPS_BLOCKED == appFilter.getFilterType()) {
                        rebuild(R.id.sort_order_alpha);
                    } else {
                        rebuild(R.id.sort_order_alpha);
                    }
                } else {
                    rebuild();
                }
            }
    
            public void resume(int sort) {
                if (DEBUG) Log.i(TAG, "Resume!  mResumed=" + mResumed);
                if (!mResumed) {
                    mResumed = true;
                    mSession.onResume();
                    mLastSortMode = sort;
                    if (mExtraInfoBridge != null) {
                        mExtraInfoBridge.resume();
                    }
                    rebuild();
                } else {
                    rebuild(sort);
                }
            }
    
            public void pause() {
                if (mResumed) {
                    mResumed = false;
                    mSession.onPause();
                    if (mExtraInfoBridge != null) {
                        mExtraInfoBridge.pause();
                    }
                }
            }
    
            public void onSaveInstanceState(Bundle outState) {
                // Record the current scroll position before pausing.
                final LinearLayoutManager layoutManager =
                        (LinearLayoutManager) mManageApplications.mRecyclerView.getLayoutManager();
                outState.putInt(STATE_LAST_SCROLL_INDEX, layoutManager.findFirstVisibleItemPosition());
            }
    
            public void release() {
                mSession.onDestroy();
                if (mExtraInfoBridge != null) {
                    mExtraInfoBridge.release();
                }
            }
    
            public void rebuild(int sort) {
                if (sort == mLastSortMode) {
                    return;
                }
                mManageApplications.mSortOrder = sort;
                mLastSortMode = sort;
                rebuild();
            }
    
            @Override
            public ApplicationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
                final View view;
                if (mManageApplications.mListType == LIST_TYPE_NOTIFICATION) {
                    view = ApplicationViewHolder.newView(parent, true /* twoTarget */);
                } else {
                    view = ApplicationViewHolder.newView(parent, false /* twoTarget */);
                }
                return new ApplicationViewHolder(view);
            }
    
            @Override
            public int getItemViewType(int position) {
                return VIEW_TYPE_APP;
            }
    
            public void rebuild() {
                if (!mHasReceivedLoadEntries
                        || (mExtraInfoBridge != null && !mHasReceivedBridgeCallback)) {
                    // Don't rebuild the list until all the app entries are loaded.
                    if (DEBUG) {
                        Log.d(TAG, "Not rebuilding until all the app entries loaded."
                                + " !mHasReceivedLoadEntries=" + !mHasReceivedLoadEntries
                                + " !mExtraInfoBridgeNull=" + (mExtraInfoBridge != null)
                                + " !mHasReceivedBridgeCallback=" + !mHasReceivedBridgeCallback);
                    }
                    return;
                }
                ApplicationsState.AppFilter filterObj;
                Comparator<AppEntry> comparatorObj;
                boolean emulated = Environment.isExternalStorageEmulated();
                if (emulated) {
                    mWhichSize = SIZE_TOTAL;
                } else {
                    mWhichSize = SIZE_INTERNAL;
                }
                filterObj = mAppFilter.getFilter();
                if (mCompositeFilter != null) {
                    filterObj = new CompoundFilter(filterObj, mCompositeFilter);
                }
                if (!mManageApplications.mShowSystem) {
                    if (LIST_TYPES_WITH_INSTANT.contains(mManageApplications.mListType)) {
                        filterObj = new CompoundFilter(filterObj,
                                ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER_AND_INSTANT);
                    } else {
                        filterObj = new CompoundFilter(filterObj,
                                ApplicationsState.FILTER_DOWNLOADED_AND_LAUNCHER);
                    }
                }
                if (mLastSortMode == R.id.sort_order_size) {
                    switch (mWhichSize) {
                        case SIZE_INTERNAL:
                            comparatorObj = ApplicationsState.INTERNAL_SIZE_COMPARATOR;
                            break;
                        case SIZE_EXTERNAL:
                            comparatorObj = ApplicationsState.EXTERNAL_SIZE_COMPARATOR;
                            break;
                        default:
                            comparatorObj = ApplicationsState.SIZE_COMPARATOR;
                            break;
                    }
                } else if (mLastSortMode == R.id.sort_order_recent_notification) {
                    comparatorObj = AppStateNotificationBridge.RECENT_NOTIFICATION_COMPARATOR;
                } else if (mLastSortMode == R.id.sort_order_frequent_notification) {
                    comparatorObj = AppStateNotificationBridge.FREQUENCY_NOTIFICATION_COMPARATOR;
                } else {
                    comparatorObj = ApplicationsState.ALPHA_COMPARATOR;
                }
    
                final AppFilter finalFilterObj = new CompoundFilter(filterObj,
                        ApplicationsState.FILTER_NOT_HIDE);
                ThreadUtils.postOnBackgroundThread(() -> {
                    mSession.rebuild(finalFilterObj, comparatorObj, false);
                });
            }
    
            @VisibleForTesting
            void filterSearch(String query) {
                if (mSearchFilter == null) {
                    mSearchFilter = new SearchFilter();
                }
                // If we haven't load apps list completely, don't filter anything.
                if (mOriginalEntries == null) {
                    Log.w(TAG, "Apps haven't loaded completely yet, so nothing can be filtered");
                    return;
                }
                mSearchFilter.filter(query);
            }
    
            private static boolean packageNameEquals(PackageItemInfo info1, PackageItemInfo info2) {
                if (info1 == null || info2 == null) {
                    return false;
                }
                if (info1.packageName == null || info2.packageName == null) {
                    return false;
                }
                return info1.packageName.equals(info2.packageName);
            }
    
            private ArrayList<ApplicationsState.AppEntry> removeDuplicateIgnoringUser(
                    ArrayList<ApplicationsState.AppEntry> entries) {
                int size = entries.size();
                // returnList will not have more entries than entries
                ArrayList<ApplicationsState.AppEntry> returnEntries = new ArrayList<>(size);
    
                // assume appinfo of same package but different users are grouped together
                PackageItemInfo lastInfo = null;
                for (int i = 0; i < size; i++) {
                    AppEntry appEntry = entries.get(i);
                    PackageItemInfo info = appEntry.info;
                    if (!packageNameEquals(lastInfo, appEntry.info)) {
                        returnEntries.add(appEntry);
                    }
                    lastInfo = info;
                }
                returnEntries.trimToSize();
                return returnEntries;
            }
    
            @Override
            public void onRebuildComplete(ArrayList<AppEntry> entries) {
                //android.util.Log.d("xin.wang", "onRebuildComplete:-> entries-> " + entries);
                android.util.Log.d("xin.wang", "哈哈哈onRebuildComplete:-> entries-> " + entries.size());
                if (DEBUG) {
                    Log.d(TAG, "onRebuildComplete size=" + entries.size());
                }
                final int filterType = mAppFilter.getFilterType();
                if (filterType == FILTER_APPS_POWER_ALLOWLIST
                        || filterType == FILTER_APPS_POWER_ALLOWLIST_ALL) {
                    entries = removeDuplicateIgnoringUser(entries);
                    android.util.Log.d("xin.wang", "onRebuildComplete: entries -> " + entries.size());
                }
                //only show the cloned third-party apps in the interface of work
                if (mManageApplications.mIsWorkOnly && !mManageApplications.mIsPersonalOnly) {
                    ArrayList<ApplicationsState.AppEntry> cloneEntries = new ArrayList();
                    int cloneNum = 0;
                    for (ApplicationsState.AppEntry entry : entries) {
                        cloneNum ++;
                        android.util.Log.d("xin.wang", "哈哈哈onRebuildComplete: cloneNum -> " + cloneNum);
                        int userId = UserHandle.getUserId(entry.info.uid);
                        UserInfo userInfo = mManageApplications.mUserManager.getUserInfo(userId);
                        boolean isManagedProfile = userInfo.isManagedProfile();
    
                        if (isManagedProfile) {
                            cloneEntries.add(entry);
                            android.util.Log.d("xin.wang", "isManagedProfile: -> cloneEntries " + cloneEntries + "<- cloneEntries.size() -> " + cloneEntries.size());
                            continue;
                        }
                        boolean isCloneProfile = userInfo.isCloneProfile();
                        boolean contains = mSupportAppClone.contains(entry.info.packageName);
                        android.util.Log.d("xin.wang", "onRebuildComplete: isCloneProfile -> " + isCloneProfile + "<- contains -> " + contains);
                        if (mSupportAppClone.contains(entry.info.packageName) && isCloneProfile) {
                            android.util.Log.d("xin.wang", "onRebuildComplete:mSupportAppClone-> " + mSupportAppClone + "<- entry.info.packageName->" + entry.info.packageName);
                            cloneEntries.add(entry);
                            android.util.Log.d("xin.wang", "mSupportAppClone.contains(entry.info.packageName): ->  cloneEntries " + cloneEntries + "<- cloneEntries.size() -> " + cloneEntries.size());
                        }
                    }
                    mEntries = cloneEntries;
                    android.util.Log.d("xin.wang", "onRebuildComplete:cloneEntries ->  " + cloneEntries + "<- cloneEntries.size() ->  " + cloneEntries.size());
                    mOriginalEntries = cloneEntries;
                } else {
                    mEntries = entries;
                    android.util.Log.d("xin.wang", "哈哈哈onRebuildComplete: mEntries -> " + mEntries.size());
                    mOriginalEntries = entries;
                }
    
                notifyDataSetChanged();
                if (getItemCount() == 0) {
                    mLoadingViewController.showEmpty(false /* animate */);
                } else {
                    mLoadingViewController.showContent(false /* animate */);
    
                    if (mManageApplications.mSearchView != null
                            && mManageApplications.mSearchView.isVisibleToUser()) {
                        final CharSequence query = mManageApplications.mSearchView.getQuery();
                        if (!TextUtils.isEmpty(query)) {
                            filterSearch(query.toString());
                        }
                    }
                }
                // Restore the last scroll position if the number of entries added so far is bigger than
                // it.
                if (mLastIndex != -1 && getItemCount() > mLastIndex) {
                    mManageApplications.mRecyclerView.getLayoutManager().scrollToPosition(mLastIndex);
                    mLastIndex = -1;
                }
    
                if (mManageApplications.mListType == LIST_TYPE_USAGE_ACCESS) {
                    // No enabled or disabled filters for usage access.
                    return;
                }
    
                mManageApplications.setHasDisabled(mState.haveDisabledApps());
                mManageApplications.setHasInstant(mState.haveInstantApps());
            }
    
            @VisibleForTesting
            void updateLoading() {
                final boolean appLoaded = mHasReceivedLoadEntries && mSession.getAllApps().size() != 0;
                if (appLoaded) {
                    mLoadingViewController.showContent(false /* animate */);
                } else {
                    mLoadingViewController.showLoadingViewDelayed();
                }
            }
    
            @Override
            public void onExtraInfoUpdated() {
                mHasReceivedBridgeCallback = true;
                rebuild();
            }
    
            @Override
            public void onRunningStateChanged(boolean running) {
                mManageApplications.getActivity().setProgressBarIndeterminateVisibility(running);
            }
    
            @Override
            public void onPackageListChanged() {
                rebuild();
            }
    
            @Override
            public void onPackageIconChanged() {
                // We ensure icons are loaded when their item is displayed, so
                // don't care about icons loaded in the background.
            }
    
            @Override
            public void onLoadEntriesCompleted() {
                mHasReceivedLoadEntries = true;
                // We may have been skipping rebuilds until this came in, trigger one now.
                rebuild();
            }
    
            @Override
            public void onPackageSizeChanged(String packageName) {
                if (mEntries == null) {
                    return;
                }
                final int size = mEntries.size();
                for (int i = 0; i < size; i++) {
                    final AppEntry entry = mEntries.get(i);
                    android.util.Log.d("xin.wang", "onPackageSizeChanged: -> entry -> " + entry.info.packageName + "<- size -> " + size + "<- mEntries -> " + mEntries);
                    final ApplicationInfo info = entry.info;
                    if (info == null && !TextUtils.equals(packageName, info.packageName)) {
                        continue;
                    }
                    if (TextUtils.equals(mManageApplications.mCurrentPkgName, info.packageName)) {
                        // We got the size information for the last app the
                        // user viewed, and are sorting by size...  they may
                        // have cleared data, so we immediately want to resort
                        // the list with the new size to reflect it to the user.
                        rebuild();
                        return;
                    } else {
                        mOnScrollListener.postNotifyItemChange(i);
                    }
                }
            }
    
            @Override
            public void onLauncherInfoChanged() {
                if (!mManageApplications.mShowSystem) {
                    rebuild();
                }
            }
    
            @Override
            public void onAllSizesComputed() {
                if (mLastSortMode == R.id.sort_order_size) {
                    rebuild();
                }
            }
    
            @Override
            public int getItemCount() {
                if (mEntries == null) {
                    return 0;
                }
                android.util.Log.d("xin.wang", "getItemCount: " + mEntries.size());
                return mEntries.size();
            }
    
            public int getApplicationCount() {
                return mEntries != null ? mEntries.size() : 0;
            }
    
            public AppEntry getAppEntry(int position) {
                return mEntries.get(position);
            }
    
            @Override
            public long getItemId(int position) {
                if (position == mEntries.size()) {
                    return -1;
                }
                return mEntries.get(position).id;
            }
    
            public boolean isEnabled(int position) {
                if (getItemViewType(position) == VIEW_TYPE_EXTRA_VIEW
                        || mManageApplications.mListType != LIST_TYPE_HIGH_POWER) {
                    return true;
                }
                ApplicationsState.AppEntry entry = mEntries.get(position);
    
                return !mBackend.isSysAllowlisted(entry.info.packageName)
                        && !mBackend.isDefaultActiveApp(entry.info.packageName);
            }
    
            @Override
            public void onBindViewHolder(ApplicationViewHolder holder, int position) {
                // Bind the data efficiently with the holder
                final ApplicationsState.AppEntry entry = mEntries.get(position);
                android.util.Log.d("xin.wang", "onBindViewHolder: ApplicationsState.AppEntry -> " + entry + "<- entry -> ");
                synchronized (entry) {
                    mState.ensureLabelDescription(entry);
                    holder.setTitle(entry.label, entry.labelDescription);
                    android.util.Log.d("xin.wang", "onBindViewHolder -> entry.label -> : " + entry.label + "<- entry.labelDescription -> " + entry.labelDescription);
                    mState.ensureIcon(entry);
                    holder.setIcon(entry.icon);
                    updateSummary(holder, entry);
                    updateSwitch(holder, entry);
                    holder.updateDisableView(entry.info);
                }
                holder.setEnabled(isEnabled(position));
    
                holder.itemView.setOnClickListener(mManageApplications);
            }
    
            private void updateSummary(ApplicationViewHolder holder, AppEntry entry) {
                switch (mManageApplications.mListType) {
                    case LIST_TYPE_NOTIFICATION:
                        if (entry.extraInfo != null
                                && entry.extraInfo instanceof NotificationsSentState) {
                            holder.setSummary(AppStateNotificationBridge.getSummary(mContext,
                                    (NotificationsSentState) entry.extraInfo, mLastSortMode));
                        } else {
                            holder.setSummary(null);
                        }
                        break;
                    case LIST_TYPE_USAGE_ACCESS:
                        if (entry.extraInfo != null
                                && entry.extraInfo instanceof PermissionState) {
                            holder.setSummary(
                                    (new UsageState((PermissionState) entry.extraInfo)).isPermissible()
                                            ? R.string.app_permission_summary_allowed
                                            : R.string.app_permission_summary_not_allowed);
                        } else {
                            holder.setSummary(null);
                        }
                        break;
                    case LIST_TYPE_HIGH_POWER:
                        holder.setSummary(HighPowerDetail.getSummary(mContext, entry));
                        break;
                    case LIST_TYPE_OVERLAY:
                        holder.setSummary(DrawOverlayDetails.getSummary(mContext, entry));
                        break;
                    case LIST_TYPE_WRITE_SETTINGS:
                        holder.setSummary(WriteSettingsDetails.getSummary(mContext, entry));
                        break;
                    case LIST_TYPE_MANAGE_SOURCES:
                        holder.setSummary(ExternalSourcesDetails.getPreferenceSummary(mContext, entry));
                        break;
                    case LIST_TYPE_WIFI_ACCESS:
                        holder.setSummary(ChangeWifiStateDetails.getSummary(mContext, entry));
                        break;
                    case LIST_MANAGE_EXTERNAL_STORAGE:
                        holder.setSummary(ManageExternalStorageDetails.getSummary(mContext, entry));
                        break;
                    case LIST_TYPE_ALARMS_AND_REMINDERS:
                        holder.setSummary(AlarmsAndRemindersDetails.getSummary(mContext, entry));
                        break;
                    case LIST_TYPE_MEDIA_MANAGEMENT_APPS:
                        holder.setSummary(MediaManagementAppsDetails.getSummary(mContext, entry));
                        break;
                    default:
                        holder.updateSizeText(entry, mManageApplications.mInvalidSizeStr, mWhichSize);
                        break;
                }
            }
    
            private void updateSwitch(ApplicationViewHolder holder, AppEntry entry) {
                switch (mManageApplications.mListType) {
                    case LIST_TYPE_NOTIFICATION:
                        holder.updateSwitch(((AppStateNotificationBridge) mExtraInfoBridge)
                                        .getSwitchOnCheckedListener(entry),
                                AppStateNotificationBridge.enableSwitch(entry),
                                AppStateNotificationBridge.checkSwitch(entry));
                        if (entry.extraInfo != null
                                && entry.extraInfo instanceof NotificationsSentState) {
                            holder.setSummary(AppStateNotificationBridge.getSummary(mContext,
                                    (NotificationsSentState) entry.extraInfo, mLastSortMode));
                        } else {
                            holder.setSummary(null);
                        }
                        break;
                }
            }
    
            public static class OnScrollListener extends RecyclerView.OnScrollListener {
                private int mScrollState = SCROLL_STATE_IDLE;
                private boolean mDelayNotifyDataChange;
                private ApplicationsAdapter mAdapter;
    
                public OnScrollListener(ApplicationsAdapter adapter) {
                    mAdapter = adapter;
                }
    
                @Override
                public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
                    mScrollState = newState;
                    if (mScrollState == SCROLL_STATE_IDLE && mDelayNotifyDataChange) {
                        mDelayNotifyDataChange = false;
                        mAdapter.notifyDataSetChanged();
                    }
                }
    
                public void postNotifyItemChange(int index) {
                    if (mScrollState == SCROLL_STATE_IDLE) {
                        mAdapter.notifyItemChanged(index);
                    } else {
                        mDelayNotifyDataChange = true;
                    }
                }
            }
    
            /**
             * An array filter that constrains the content of the array adapter with a substring.
             * Item that does not contains the specified substring will be removed from the list.

    */
    private class SearchFilter extends Filter { @WorkerThread @Override protected FilterResults performFiltering(CharSequence query) { final ArrayList<ApplicationsState.AppEntry> matchedEntries; if (TextUtils.isEmpty(query)) { matchedEntries = mOriginalEntries; } else { matchedEntries = new ArrayList<>(); for (ApplicationsState.AppEntry entry : mOriginalEntries) { if (entry.label.toLowerCase().contains(query.toString().toLowerCase())) { matchedEntries.add(entry); } } } final FilterResults results = new FilterResults(); results.values = matchedEntries; results.count = matchedEntries.size(); return results; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { mEntries = (ArrayList<ApplicationsState.AppEntry>) results.values; notifyDataSetChanged(); } } } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584
    • 585
    • 586
    • 587
    • 588
    • 589
    • 590
    • 591
    • 592
    • 593
    • 594
    • 595
    • 596
    • 597
    • 598
    • 599
    • 600
    • 601
    • 602
    • 603
    • 604
    • 605
    • 606
    • 607
    • 608
    • 609
    • 610
    • 611
    • 612
    • 613
    • 614
    • 615
    • 616
    • 617
    • 618
    • 619
    • 620
    • 621
    • 622
    • 623
    • 624
    • 625
    • 626
    • 627
    • 628
    • 629
    • 630
    • 631
    • 632
    • 633
    • 634
    • 635
    • 636
    • 637
    • 638
    • 639
    • 640
    • 641
    • 642
    • 643
    • 644
    • 645
    • 646
    • 647
    • 648
    • 649
    • 650
    • 651
    • 652
    • 653
    • 654
    • 655
    • 656
    • 657
    • 658
    • 659
    • 660
    • 661
    • 662
    • 663
    • 664
    • 665
    • 666
    • 667
    • 668
    • 669
    • 670
    • 671
    • 672
    • 673
    • 674
    • 675
    • 676
    • 677
    • 678
    • 679
    • 680
    • 681
    • 682
    • 683
    • 684
    • 685
    • 686
    • 687
    • 688
    • 689
    • 690
    • 691
    • 692
    • 693
    • 694
    • 695
    • 696
    • 697
    • 698
    • 699
    • 700
    • 701
    • 702
    • 703
    • 704
    • 705
    • 706
    • 707
    • 708
    • 709
    • 710
    • 711
    • 712
    • 713
    • 714
    • 715
    • 716
    • 717
    • 718
    • 719
    • 720
    • 721
    • 722
    • 723
    • 724
    • 725
    • 726
    • 727
    • 728
    • 729
    • 730
    • 731
    • 732
    • 733
    • 734
    • 735
    • 736
    • 737
    • 738
    • 739
    • 740
    • 741
    • 742
    • 743
    • 744
    • 745
    • 746
    • 747
    • 748
    • 749
    • 750
    • 751
    • 752
    • 753
    • 754
    • 755
    • 756
    • 757
    • 758
    • 759
    • 760
    • 761
    • 762
    • 763
    • 764
    • 765
    • 766
    • 767
    • 768
    • 769
    • 770
    • 771
    • 772
    • 773
    • 774
    • 775
    • 776
    • 777
    • 778
    • 779
    • 780
    • 781
    • 782
    • 783
    • 784
    • 785
    • 786
    • 787
    • 788
    • 789
    • 790
    • 791
    • 792
    • 793
    • 794
    • 795
    • 796
    • 797
    • 798
    • 799
    • 800
    • 801
    • 802
    • 803
    • 804
    • 805
    • 806
    • 807
    • 808
    • 809
    • 810
    • 811
    • 812
    • 813
    • 814
    • 815
    • 816
    • 817
    • 818
    • 819
    • 820
    • 821
    • 822
    • 823
    • 824
    • 825
    • 826
    • 827
    • 828
    • 829
    • 830
    • 831
    • 832
    • 833
    • 834
    • 835
    • 836
    • 837
    • 838
    • 839
    • 840
    • 841
    • 842
    • 843
    • 844
    • 845
    • 846
    • 847
    • 848
    • 849
    • 850
    • 851
    • 852
    • 853
    • 854
    • 855
    • 856
    • 857
    • 858
    • 859
    • 860
    • 861
    • 862
    • 863
    • 864
    • 865
    • 866
    • 867
    • 868
    • 869
    • 870
    • 871
    • 872
    • 873
    • 874
    • 875
    • 876
    • 877
    • 878
    • 879
    • 880
    • 881
    • 882
    • 883
    • 884
    • 885
    • 886
    • 887
    • 888
    • 889
    • 890
    • 891
    • 892
    • 893
    • 894
    • 895
    • 896
    • 897
    • 898
    • 899
    • 900
    • 901
    • 902
    • 903
    • 904
    • 905
    • 906
    • 907
    • 908
    • 909
    • 910
    • 911
    • 912
    • 913
    • 914
    • 915
    • 916
    • 917
    • 918
    • 919
    • 920
    • 921
    • 922
    • 923
    • 924
    • 925
    • 926
    • 927
    • 928
    • 929
    • 930
    • 931
    • 932
    • 933
    • 934
    • 935
    • 936
    • 937
    • 938
    • 939
    • 940
    • 941
    • 942
    • 943
    • 944
    • 945
    • 946
    • 947
    • 948
    • 949
    • 950
    • 951
    • 952
    • 953
    • 954
    • 955
    • 956
    • 957
    • 958
    • 959
    • 960
    • 961
    • 962
    • 963
    • 964
    • 965
    • 966
    • 967
    • 968
    • 969
    • 970
    • 971
    • 972
    • 973
    • 974
    • 975
    • 976
    • 977
    • 978
    • 979
    • 980
    • 981
    • 982
    • 983
    • 984
    • 985
    • 986
    • 987
    • 988
    • 989
    • 990
    • 991
    • 992
    • 993
    • 994
    • 995
    • 996
    • 997
    • 998
    • 999
    • 1000
    • 1001
    • 1002
    • 1003
    • 1004
    • 1005
    • 1006
    • 1007
    • 1008
    • 1009
    • 1010
    • 1011
    • 1012
    • 1013
    • 1014
    • 1015
    • 1016
    • 1017
    • 1018
    • 1019
    • 1020
    • 1021
    • 1022
    • 1023
    • 1024
    • 1025
    • 1026
    • 1027
    • 1028
    • 1029
    • 1030
    • 1031
    • 1032
    • 1033
    • 1034
    • 1035
    • 1036
    • 1037
    • 1038
    • 1039
    • 1040
    • 1041
    • 1042
    • 1043
    • 1044
    • 1045
    • 1046
    • 1047
    • 1048
    • 1049
    • 1050
    • 1051
    • 1052
    • 1053
    • 1054
    • 1055
    • 1056
    • 1057
    • 1058
    • 1059
    • 1060
    • 1061
    • 1062
    • 1063
    • 1064
    • 1065
    • 1066
    • 1067
    • 1068
    • 1069
    • 1070
    • 1071
    • 1072
    • 1073
    • 1074
    • 1075
    • 1076
    • 1077
    • 1078
    • 1079
    • 1080
    • 1081
    • 1082
    • 1083
    • 1084
    • 1085
    • 1086
    • 1087
    • 1088
    • 1089
    • 1090
    • 1091
    • 1092
    • 1093
    • 1094
    • 1095
    • 1096
    • 1097
    • 1098
    • 1099
    • 1100
    • 1101
    • 1102
    • 1103
    • 1104
    • 1105
    • 1106
    • 1107
    • 1108
    • 1109
    • 1110
    • 1111
    • 1112
    • 1113
    • 1114
    • 1115
    • 1116
    • 1117
    • 1118
    • 1119
    • 1120
    • 1121
    • 1122
    • 1123
    • 1124
    • 1125
    • 1126
    • 1127
    • 1128
    • 1129
    • 1130
    • 1131
    • 1132
    • 1133
    • 1134
    • 1135
    • 1136
    • 1137
    • 1138
    • 1139
    • 1140
    • 1141
    • 1142
    • 1143
    • 1144
    • 1145
    • 1146
    • 1147
    • 1148
    • 1149
    • 1150
    • 1151
    • 1152
    • 1153
    • 1154
    • 1155
    • 1156
    • 1157
    • 1158
    • 1159
    • 1160
    • 1161
    • 1162
    • 1163
    • 1164
    • 1165
    • 1166
    • 1167
    • 1168
    • 1169
    • 1170
    • 1171
    • 1172
    • 1173
    • 1174
    • 1175
    • 1176
    • 1177
    • 1178
    • 1179
    • 1180
    • 1181
    • 1182
    • 1183
    • 1184
    • 1185
    • 1186
    • 1187
    • 1188
    • 1189
    • 1190
    • 1191
    • 1192
    • 1193
    • 1194
    • 1195
    • 1196
    • 1197
    • 1198
    • 1199
    • 1200
    • 1201
    • 1202
    • 1203
    • 1204
    • 1205
    • 1206
    • 1207
    • 1208
    • 1209
    • 1210
    • 1211
    • 1212
    • 1213
    • 1214
    • 1215
    • 1216
    • 1217
    • 1218
    • 1219
    • 1220
    • 1221
    • 1222
    • 1223
    • 1224
    • 1225
    • 1226
    • 1227
    • 1228
    • 1229
    • 1230
    • 1231
    • 1232
    • 1233
    • 1234
    • 1235
    • 1236
    • 1237
    • 1238
    • 1239
    • 1240
    • 1241
    • 1242
    • 1243
    • 1244
    • 1245
    • 1246
    • 1247
    • 1248
    • 1249
    • 1250
    • 1251
    • 1252
    • 1253
    • 1254
    • 1255
    • 1256
    • 1257
    • 1258
    • 1259
    • 1260
    • 1261
    • 1262
    • 1263
    • 1264
    • 1265
    • 1266
    • 1267
    • 1268
    • 1269
    • 1270
    • 1271
    • 1272
    • 1273
    • 1274
    • 1275
    • 1276
    • 1277
    • 1278
    • 1279
    • 1280
    • 1281
    • 1282
    • 1283
    • 1284
    • 1285
    • 1286
    • 1287
    • 1288
    • 1289
    • 1290
    • 1291
    • 1292
    • 1293
    • 1294
    • 1295
    • 1296
    • 1297
    • 1298
    • 1299
    • 1300
    • 1301
    • 1302
    • 1303
    • 1304
    • 1305
    • 1306
    • 1307
    • 1308
    • 1309
    • 1310
    • 1311
    • 1312
    • 1313
    • 1314
    • 1315
    • 1316
    • 1317
    • 1318
    • 1319
    • 1320
    • 1321
    • 1322
    • 1323
    • 1324
    • 1325
    • 1326
    • 1327
    • 1328
    • 1329
    • 1330
    • 1331
    • 1332
    • 1333
    • 1334
    • 1335
    • 1336
    • 1337
    • 1338
    • 1339
    • 1340
    • 1341
    • 1342
    • 1343
    • 1344
    • 1345
    • 1346
    • 1347
    • 1348
    • 1349
    • 1350
    • 1351
    • 1352
    • 1353
    • 1354
    • 1355
    • 1356
    • 1357
    • 1358
    • 1359
    • 1360
    • 1361
    • 1362
    • 1363
    • 1364
    • 1365
    • 1366
    • 1367
    • 1368
    • 1369
    • 1370
    • 1371
    • 1372
    • 1373
    • 1374
    • 1375
    • 1376
    • 1377
    • 1378
    • 1379
    • 1380
    • 1381
    • 1382
    • 1383
    • 1384
    • 1385
    • 1386
    • 1387
    • 1388
    • 1389
    • 1390
    • 1391
    • 1392
    • 1393
    • 1394
    • 1395
    • 1396
    • 1397
    • 1398
    • 1399
    • 1400
    • 1401
    • 1402
    • 1403
    • 1404
    • 1405
    • 1406
    • 1407
    • 1408
    • 1409
    • 1410
    • 1411
    • 1412
    • 1413
    • 1414
    • 1415
    • 1416
    • 1417
    • 1418
    • 1419
    • 1420
    • 1421
    • 1422
    • 1423
    • 1424
    • 1425
    • 1426
    • 1427
    • 1428
    • 1429
    • 1430
    • 1431
    • 1432
    • 1433
    • 1434
    • 1435
    • 1436
    • 1437
    • 1438
    • 1439
    • 1440
    • 1441
    • 1442
    • 1443
    • 1444
    • 1445
    • 1446
    • 1447
    • 1448
    • 1449
    • 1450
    • 1451
    • 1452
    • 1453
    • 1454
    • 1455
    • 1456
    • 1457
    • 1458
    • 1459
    • 1460
    • 1461
    • 1462
    • 1463
    • 1464
    • 1465
    • 1466
    • 1467
    • 1468
    • 1469
    • 1470
    • 1471
    • 1472
    • 1473
    • 1474
    • 1475
    • 1476
    • 1477
    • 1478
    • 1479
    • 1480
    • 1481
    • 1482
    • 1483
    • 1484
    • 1485
    • 1486
    • 1487
    • 1488
    • 1489
    • 1490
    • 1491
    • 1492
    • 1493
    • 1494
    • 1495
    • 1496
    • 1497
    • 1498
    • 1499
    • 1500
    • 1501
    • 1502
    • 1503
    • 1504
    • 1505
    • 1506
    • 1507
    • 1508
    • 1509
    • 1510
    • 1511
    • 1512
    • 1513
    • 1514
    • 1515
    • 1516
    • 1517
    • 1518
    • 1519
    • 1520
    • 1521
    • 1522
    • 1523
    • 1524
    • 1525
    • 1526
    • 1527
    • 1528
    • 1529
    • 1530
    • 1531
    • 1532
    • 1533
    • 1534
    • 1535
    • 1536
    • 1537
    • 1538
    • 1539
    • 1540
    • 1541
    • 1542
    • 1543
    • 1544
    • 1545
    • 1546
    • 1547
    • 1548
    • 1549
    • 1550
    • 1551
    • 1552
    • 1553
    • 1554
    • 1555
    • 1556
    • 1557
    • 1558
    • 1559
    • 1560
    • 1561
    • 1562
    • 1563
    • 1564
    • 1565
    • 1566
    • 1567
    • 1568
    • 1569
    • 1570
    • 1571
    • 1572
    • 1573
    • 1574
    • 1575
    • 1576
    • 1577
    • 1578
    • 1579
    • 1580
    • 1581
    • 1582
    • 1583
    • 1584
    • 1585
    • 1586
    • 1587
    • 1588
    • 1589
    • 1590
    • 1591
    • 1592
    • 1593
    • 1594
    • 1595
    • 1596
    • 1597
    • 1598
    • 1599
    • 1600
    • 1601
    • 1602
    • 1603
    • 1604
    • 1605
    • 1606
    • 1607
    • 1608
    • 1609
    • 1610
    • 1611
    • 1612
    • 1613
    • 1614
    • 1615
    • 1616
    • 1617
    • 1618
    • 1619
    • 1620
    • 1621
    • 1622
    • 1623
    • 1624
    • 1625
    • 1626
    • 1627
    • 1628
    • 1629
    • 1630
    • 1631
    • 1632
    • 1633
    • 1634
    • 1635
    • 1636
    • 1637
    • 1638
    • 1639
    • 1640
    • 1641
    • 1642
    • 1643
    • 1644
    • 1645
    • 1646
    • 1647
    • 1648
    • 1649
    • 1650
    • 1651
    • 1652
    • 1653
    • 1654
    • 1655
    • 1656
    • 1657

    5、开启手机分身后所有应用的显示

    在这里插入图片描述

    个人区域存放所有应用

    工作区域显示双开的应用

    实现的逻辑类ProfileSelectManageApplications

    /*
     * Copyright (C) 2019 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.dashboard.profileselector;
    
    import android.os.Bundle;
    
    import androidx.fragment.app.Fragment;
    
    import com.android.settings.applications.manageapplications.ManageApplications;
    
    /**
     * Application Setting page for personal/managed profile.
     */
    public class ProfileSelectManageApplications extends ProfileSelectFragment {
    
        @Override
        public Fragment[] getFragments() {
            final Bundle workOnly = getArguments() != null ? getArguments().deepCopy() : new Bundle();
            workOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.WORK);
            final Fragment workFragment = new ManageApplications();
            workFragment.setArguments(workOnly);
    
            final Bundle personalOnly = getArguments() != null ? getArguments() : new Bundle();
            personalOnly.putInt(EXTRA_PROFILE, ProfileSelectFragment.ProfileType.PERSONAL);
            final Fragment personalFragment = new ManageApplications();
            personalFragment.setArguments(personalOnly);
            return new Fragment[]{
                    personalFragment, //0
                    workFragment
            };
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
  • 相关阅读:
    数博会精彩回顾 | 彰显科研实力,中创算力荣获数字化影响力企业奖
    洛谷-Directed Roads-(基环树总结)
    MySQL 中的事务理解
    MySQL数据库:2、MySQL的下载与安装、基本使用、系统服务制作
    一文看懂推荐系统:排序02:Multi-gate Mixture-of-Experts (MMoE)
    RabbitMQ:发布确认模式
    电子学会2022年6月青少年软件编程(图形化)等级考试试卷(三级)答案解析
    【SpringMVC】JSR 303与拦截器注释使用
    数字化档案管理系统解决方案
    StopWatch使用注意S
  • 原文地址:https://blog.csdn.net/qq_45146250/article/details/126266848