1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.applications; 18 19 import static android.content.pm.PackageManager.GET_ACTIVITIES; 20 21 import static com.android.settingslib.applications.ApplicationsState.AppEntry; 22 import static com.android.settingslib.applications.ApplicationsState.AppFilter; 23 24 import android.content.Context; 25 import android.util.Log; 26 27 import com.android.settings.Utils; 28 import com.android.settingslib.applications.ApplicationsState; 29 30 import java.util.ArrayList; 31 import java.util.Arrays; 32 import java.util.List; 33 34 /** 35 * Filter to display only allowlisted apps on Cloned Apps page. 36 */ 37 public class AppStateClonedAppsBridge extends AppStateBaseBridge{ 38 39 private static final String TAG = "ClonedAppsBridge"; 40 41 private final Context mContext; 42 private final List<String> mAllowedApps; 43 private List<String> mCloneProfileApps = new ArrayList<>(); 44 private int mCloneUserId; 45 AppStateClonedAppsBridge(Context context, ApplicationsState appState, Callback callback)46 public AppStateClonedAppsBridge(Context context, ApplicationsState appState, 47 Callback callback) { 48 super(appState, callback); 49 mContext = context; 50 mAllowedApps = Arrays.asList(mContext.getResources() 51 .getStringArray(com.android.internal.R.array.cloneable_apps)); 52 } 53 54 @Override loadAllExtraInfo()55 protected void loadAllExtraInfo() { 56 mCloneUserId = Utils.getCloneUserId(mContext); 57 if (mCloneUserId != -1) { 58 mCloneProfileApps = mContext.getPackageManager() 59 .getInstalledPackagesAsUser(GET_ACTIVITIES, 60 mCloneUserId).stream().map(x -> x.packageName).toList(); 61 } else if (!mCloneProfileApps.isEmpty()) { 62 // In case we remove clone profile (mCloneUserId becomes -1), the bridge state should 63 // reflect the same by setting cloneProfileApps as empty, without building the entire 64 // page. 65 mCloneProfileApps = new ArrayList<>(); 66 } 67 68 final List<ApplicationsState.AppEntry> allApps = mAppSession.getAllApps(); 69 for (int i = 0; i < allApps.size(); i++) { 70 ApplicationsState.AppEntry app = allApps.get(i); 71 this.updateExtraInfo(app, app.info.packageName, app.info.uid); 72 } 73 } 74 75 @Override updateExtraInfo(AppEntry app, String pkg, int uid)76 protected void updateExtraInfo(AppEntry app, String pkg, int uid) { 77 // Display package if allowlisted but not yet cloned. 78 // Or if the app is present in clone profile alongwith being in allowlist. 79 if (mAllowedApps.contains(pkg) 80 && ((!mCloneProfileApps.contains(pkg) || (app.isClonedProfile())))) { 81 app.extraInfo = Boolean.TRUE; 82 } else { 83 app.extraInfo = Boolean.FALSE; 84 } 85 } 86 87 public static final AppFilter FILTER_APPS_CLONE = 88 new AppFilter() { 89 @Override 90 public void init() { 91 } 92 93 @Override 94 public boolean filterApp(AppEntry entry) { 95 if (entry.extraInfo == null) { 96 Log.d(TAG, "[" + entry.info.packageName + "]" + " has No extra info."); 97 return false; 98 } 99 return (Boolean) entry.extraInfo; 100 } 101 }; 102 } 103