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 package com.android.settings.applications; 17 18 import android.content.Context; 19 import android.content.pm.PackageManager; 20 import android.content.pm.ResolveInfo; 21 import android.os.UserHandle; 22 import android.os.UserManager; 23 import android.util.ArrayMap; 24 import android.util.Log; 25 26 import com.android.settings.Utils; 27 import com.android.settingslib.applications.ApplicationsState; 28 import com.android.settingslib.applications.ApplicationsState.AppEntry; 29 import com.android.settingslib.applications.ApplicationsState.AppFilter; 30 31 import java.util.ArrayList; 32 import java.util.List; 33 import java.util.Map; 34 35 /** 36 * Creates a application filter to restrict UI display of applications. 37 * This is to avoid users from changing the per apps locale 38 * Also provides app filters that can use the info. 39 */ 40 public class AppStateLocaleBridge extends AppStateBaseBridge { 41 private static final String TAG = AppStateLocaleBridge.class.getSimpleName(); 42 43 private final Context mContext; 44 private final Map<Integer, AppInfoByProfiles> mUserIdToAppInfoByProfiles = new ArrayMap<>(); 45 AppStateLocaleBridge(Context context, ApplicationsState appState, Callback callback, UserManager userManager)46 public AppStateLocaleBridge(Context context, ApplicationsState appState, 47 Callback callback, UserManager userManager) { 48 super(appState, callback); 49 mContext = context; 50 collectLocaleBridgeInfo(userManager); 51 } 52 53 @Override updateExtraInfo(AppEntry app, String packageName, int uid)54 protected void updateExtraInfo(AppEntry app, String packageName, int uid) { 55 AppInfoByProfiles appInfoByProfiles = getAppInfo(UserHandle.getUserId(uid)); 56 57 app.extraInfo = AppLocaleUtil.canDisplayLocaleUi(appInfoByProfiles.mContextAsUser, 58 app.info, appInfoByProfiles.mListInfos) ? Boolean.TRUE : Boolean.FALSE; 59 } 60 61 @Override loadAllExtraInfo()62 protected void loadAllExtraInfo() { 63 final List<AppEntry> allApps = mAppSession.getAllApps(); 64 for (int i = 0; i < allApps.size(); i++) { 65 AppEntry app = allApps.get(i); 66 AppInfoByProfiles appInfoByProfiles = getAppInfo(UserHandle.getUserId(app.info.uid)); 67 68 app.extraInfo = AppLocaleUtil.canDisplayLocaleUi(appInfoByProfiles.mContextAsUser, 69 app.info, appInfoByProfiles.mListInfos) ? Boolean.TRUE : Boolean.FALSE; 70 } 71 } 72 73 /** For the Settings which shows category of per app's locale. */ 74 public static final AppFilter FILTER_APPS_LOCALE = 75 new AppFilter() { 76 @Override 77 public void init() { 78 } 79 80 @Override 81 public boolean filterApp(AppEntry entry) { 82 if (entry.extraInfo == null) { 83 Log.d(TAG, "[" + entry.info.packageName + "]" + " has No extra info."); 84 return false; 85 } 86 return entry.extraInfo == Boolean.TRUE; 87 } 88 }; 89 collectLocaleBridgeInfo(UserManager userManager)90 private void collectLocaleBridgeInfo(UserManager userManager) { 91 List<Integer> userIds = new ArrayList<>(); 92 93 userIds.add(mContext.getUserId()); 94 int workUserId = Utils.getManagedProfileId(userManager, mContext.getUserId()); 95 if (workUserId != UserHandle.USER_NULL) { 96 userIds.add(workUserId); 97 } 98 99 // Separate the app information by profiles. 100 for (int userId : userIds) { 101 if (!mUserIdToAppInfoByProfiles.containsKey(userId)) { 102 mUserIdToAppInfoByProfiles.put(userId, new AppInfoByProfiles(mContext, userId)); 103 } 104 } 105 } 106 getAppInfo(int userId)107 private AppInfoByProfiles getAppInfo(int userId) { 108 AppInfoByProfiles info; 109 if (mUserIdToAppInfoByProfiles.containsKey(userId)) { 110 info = mUserIdToAppInfoByProfiles.get(userId); 111 } else { 112 info = new AppInfoByProfiles(mContext, userId); 113 mUserIdToAppInfoByProfiles.put(userId, info); 114 } 115 116 return info; 117 } 118 119 /** 120 * The app information by profiles. 121 */ 122 private static class AppInfoByProfiles { 123 public final Context mContextAsUser; 124 public final List<ResolveInfo> mListInfos; 125 AppInfoByProfiles(Context context, int userId)126 private AppInfoByProfiles(Context context, int userId) { 127 mContextAsUser = context.createContextAsUser(UserHandle.of(userId), 0); 128 mListInfos = mContextAsUser.getPackageManager().queryIntentActivities( 129 AppLocaleUtil.LAUNCHER_ENTRY_INTENT, PackageManager.GET_META_DATA); 130 } 131 } 132 } 133