Loading services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.javadeleted 100644 → 0 +0 −171 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.server.policy.role; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.role.RoleManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.provider.Settings; import android.text.TextUtils; import android.util.Slog; import com.android.internal.R; import com.android.internal.telephony.SmsApplication; import com.android.internal.util.CollectionUtils; import com.android.server.LocalServices; import com.android.server.role.LegacyRoleHolderProvider; import com.android.server.role.RoleManagerService; import java.util.Collections; import java.util.List; import java.util.Objects; /** * Logic to retrieve the various legacy(pre-Q) equivalents of role holders. * * Unlike {@link RoleManagerService} this is meant to be pretty high-level to allow for depending * on all kinds of various systems that are historically involved in legacy role resolution, * e.g. {@link SmsApplication} * * @see RoleManagerService#migrateRoleIfNecessary */ public class LegacyRoleResolutionPolicy implements LegacyRoleHolderProvider { private static final boolean DEBUG = false; private static final String LOG_TAG = "LegacyRoleResolutionPol"; @NonNull private final Context mContext; public LegacyRoleResolutionPolicy(@NonNull Context context) { mContext = context; } @NonNull @Override public List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId) { switch (roleName) { case RoleManager.ROLE_ASSISTANT: { String packageName; String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.ASSISTANT, userId); // AssistUtils was using the default assistant app if Settings.Secure.ASSISTANT is // null, while only an empty string means user selected "None". if (setting != null) { if (!setting.isEmpty()) { ComponentName componentName = ComponentName.unflattenFromString(setting); packageName = componentName != null ? componentName.getPackageName() : null; } else { packageName = null; } } else if (mContext.getPackageManager().isDeviceUpgrading()) { String defaultAssistant = mContext.getString(R.string.config_defaultAssistant); packageName = !TextUtils.isEmpty(defaultAssistant) ? defaultAssistant : null; } else { packageName = null; } return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_BROWSER: { PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); String packageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName( userId); return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_DIALER: { String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.DIALER_DEFAULT_APPLICATION, userId); String packageName; if (!TextUtils.isEmpty(setting)) { packageName = setting; } else if (mContext.getPackageManager().isDeviceUpgrading()) { // DefaultDialerManager was using the default dialer app if // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid. // TelecomManager.getSystemDialerPackage() won't work because it might not // be ready. packageName = mContext.getString(R.string.config_defaultDialer); } else { packageName = null; } return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_SMS: { String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.SMS_DEFAULT_APPLICATION, userId); String packageName; if (!TextUtils.isEmpty(setting)) { packageName = setting; } else if (mContext.getPackageManager().isDeviceUpgrading()) { // SmsApplication was using the default SMS app if // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid. packageName = mContext.getString(R.string.config_defaultSms); } else { packageName = null; } return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_HOME: { PackageManager packageManager = mContext.getPackageManager(); String packageName; if (packageManager.isDeviceUpgrading()) { ResolveInfo resolveInfo = packageManager.resolveActivityAsUser( new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME), PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId); packageName = resolveInfo != null && resolveInfo.activityInfo != null ? resolveInfo.activityInfo.packageName : null; if (packageName != null && isSettingsApplication(packageName, userId)) { packageName = null; } } else { packageName = null; } return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_EMERGENCY: { String defaultEmergencyApp = Settings.Secure.getStringForUser( mContext.getContentResolver(), Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION, userId); return CollectionUtils.singletonOrEmpty(defaultEmergencyApp); } default: { Slog.e(LOG_TAG, "Don't know how to find legacy role holders for " + roleName); return Collections.emptyList(); } } } private boolean isSettingsApplication(@NonNull String packageName, @UserIdInt int userId) { PackageManager packageManager = mContext.getPackageManager(); ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(new Intent( Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId); if (resolveInfo == null || resolveInfo.activityInfo == null) { return false; } return Objects.equals(packageName, resolveInfo.activityInfo.packageName); } } services/core/java/com/android/server/policy/role/LegacyRoleStateProviderImpl.java 0 → 100644 +291 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.server.policy.role; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.role.RoleManager; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.os.Environment; import android.provider.Settings; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; import android.util.Slog; import android.util.Xml; import com.android.internal.R; import com.android.server.LocalServices; import com.android.server.role.LegacyRoleStateProvider; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.Objects; import java.util.Set; /** * Implementation to provide legacy role state. */ public class LegacyRoleStateProviderImpl implements LegacyRoleStateProvider { private static final String LOG_TAG = "LegacyRoleState"; private static final String ROLES_FILE_NAME = "roles.xml"; private static final String TAG_ROLES = "roles"; private static final String TAG_ROLE = "role"; private static final String TAG_HOLDER = "holder"; private static final String ATTRIBUTE_NAME = "name"; @NonNull private final Context mContext; public LegacyRoleStateProviderImpl(@NonNull Context context) { mContext = context; } @NonNull @Override public Map<String, Set<String>> getLegacyRoleState(@UserIdInt int userId) { Map<String, Set<String>> roles = readFile(userId); if (roles == null) { roles = readFromLegacySettings(userId); } return roles; } @Nullable private Map<String, Set<String>> readFile(@UserIdInt int userId) { File file = getFile(userId); try (FileInputStream in = new AtomicFile(file).openRead()) { XmlPullParser parser = Xml.newPullParser(); parser.setInput(in, null); Map<String, Set<String>> roles = parseXml(parser); Slog.i(LOG_TAG, "Read legacy roles.xml successfully"); return roles; } catch (FileNotFoundException e) { Slog.i(LOG_TAG, "Legacy roles.xml not found"); return null; } catch (XmlPullParserException | IOException e) { Slog.wtf(LOG_TAG, "Failed to parse legacy roles.xml: " + file, e); return null; } } @NonNull private Map<String, Set<String>> parseXml(@NonNull XmlPullParser parser) throws IOException, XmlPullParserException { int type; int depth; int innerDepth = parser.getDepth() + 1; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { if (depth > innerDepth || type != XmlPullParser.START_TAG) { continue; } if (parser.getName().equals(TAG_ROLES)) { return parseRoles(parser); } } throw new IOException("Missing <" + TAG_ROLES + "> in roles.xml"); } @NonNull private Map<String, Set<String>> parseRoles(@NonNull XmlPullParser parser) throws IOException, XmlPullParserException { Map<String, Set<String>> roles = new ArrayMap<>(); int type; int depth; int innerDepth = parser.getDepth() + 1; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { if (depth > innerDepth || type != XmlPullParser.START_TAG) { continue; } if (parser.getName().equals(TAG_ROLE)) { String roleName = parser.getAttributeValue(null, ATTRIBUTE_NAME); Set<String> roleHolders = parseRoleHoldersLocked(parser); roles.put(roleName, roleHolders); } } return roles; } @NonNull private Set<String> parseRoleHoldersLocked(@NonNull XmlPullParser parser) throws IOException, XmlPullParserException { Set<String> roleHolders = new ArraySet<>(); int type; int depth; int innerDepth = parser.getDepth() + 1; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { if (depth > innerDepth || type != XmlPullParser.START_TAG) { continue; } if (parser.getName().equals(TAG_HOLDER)) { String roleHolder = parser.getAttributeValue(null, ATTRIBUTE_NAME); roleHolders.add(roleHolder); } } return roleHolders; } @NonNull private static File getFile(@UserIdInt int userId) { return new File(Environment.getUserSystemDirectory(userId), ROLES_FILE_NAME); } @NonNull private Map<String, Set<String>> readFromLegacySettings(@UserIdInt int userId) { Map<String, Set<String>> roles = new ArrayMap<>(); // Assistant ContentResolver contentResolver = mContext.getContentResolver(); String assistantSetting = Settings.Secure.getStringForUser(contentResolver, Settings.Secure.ASSISTANT, userId); PackageManager packageManager = mContext.getPackageManager(); String assistantPackageName; // AssistUtils was using the default assistant app if Settings.Secure.ASSISTANT is // null, while only an empty string means user selected "None". if (assistantSetting != null) { if (!assistantSetting.isEmpty()) { ComponentName componentName = ComponentName.unflattenFromString(assistantSetting); assistantPackageName = componentName != null ? componentName.getPackageName() : null; } else { assistantPackageName = null; } } else if (packageManager.isDeviceUpgrading()) { String defaultAssistant = mContext.getString(R.string.config_defaultAssistant); assistantPackageName = !TextUtils.isEmpty(defaultAssistant) ? defaultAssistant : null; } else { assistantPackageName = null; } if (assistantPackageName != null) { roles.put(RoleManager.ROLE_ASSISTANT, Collections.singleton(assistantPackageName)); } // Browser PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); String browserPackageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName( userId); if (browserPackageName != null) { roles.put(RoleManager.ROLE_BROWSER, Collections.singleton(browserPackageName)); } // Dialer String dialerSetting = Settings.Secure.getStringForUser(contentResolver, Settings.Secure.DIALER_DEFAULT_APPLICATION, userId); String dialerPackageName; if (!TextUtils.isEmpty(dialerSetting)) { dialerPackageName = dialerSetting; } else if (packageManager.isDeviceUpgrading()) { // DefaultDialerManager was using the default dialer app if // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid. // TelecomManager.getSystemDialerPackage() won't work because it might not // be ready. dialerPackageName = mContext.getString(R.string.config_defaultDialer); } else { dialerPackageName = null; } if (dialerPackageName != null) { roles.put(RoleManager.ROLE_DIALER, Collections.singleton(dialerPackageName)); } // SMS String smsSetting = Settings.Secure.getStringForUser(contentResolver, Settings.Secure.SMS_DEFAULT_APPLICATION, userId); String smsPackageName; if (!TextUtils.isEmpty(smsSetting)) { smsPackageName = smsSetting; } else if (mContext.getPackageManager().isDeviceUpgrading()) { // SmsApplication was using the default SMS app if // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid. smsPackageName = mContext.getString(R.string.config_defaultSms); } else { smsPackageName = null; } if (smsPackageName != null) { roles.put(RoleManager.ROLE_SMS, Collections.singleton(smsPackageName)); } // Home String homePackageName; if (packageManager.isDeviceUpgrading()) { ResolveInfo resolveInfo = packageManager.resolveActivityAsUser( new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME), PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId); homePackageName = resolveInfo != null && resolveInfo.activityInfo != null ? resolveInfo.activityInfo.packageName : null; if (homePackageName != null && isSettingsApplication(homePackageName, userId)) { homePackageName = null; } } else { homePackageName = null; } if (homePackageName != null) { roles.put(RoleManager.ROLE_HOME, Collections.singleton(homePackageName)); } // Emergency String emergencyPackageName = Settings.Secure.getStringForUser(contentResolver, Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION, userId); if (emergencyPackageName != null) { roles.put(RoleManager.ROLE_EMERGENCY, Collections.singleton(emergencyPackageName)); } return roles; } private boolean isSettingsApplication(@NonNull String packageName, @UserIdInt int userId) { PackageManager packageManager = mContext.getPackageManager(); ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(new Intent( Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId); if (resolveInfo == null || resolveInfo.activityInfo == null) { return false; } return Objects.equals(packageName, resolveInfo.activityInfo.packageName); } } services/core/java/com/android/server/role/LegacyRoleHolderProvider.java→services/core/java/com/android/server/role/LegacyRoleStateProvider.java +13 −10 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * 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. Loading @@ -19,22 +19,25 @@ package com.android.server.role; import android.annotation.NonNull; import android.annotation.UserIdInt; import java.util.List; import java.util.Map; import java.util.Set; /** * A provider for migrating legacy "role"s to their actual role implementation. * Provider for legacy role state. * <p> * The role state may come from two sources, either the different pre-role default app settings, or * the pre-modularization roles.xml file stored in platform. * * @hide */ //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER) public interface LegacyRoleHolderProvider { public interface LegacyRoleStateProvider { /** * Get the list of holders of a legacy "role" before its actual role is introduced. * <p> * This method will only be called for the first time a role is made available in the platform. * Get the legacy role state stored in the platform. * * @param roleName the name of the role * @param userId the user ID * @return a list of holders for the given role * @return a mapping of role name to its set of holders */ @NonNull List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId); Map<String, Set<String>> getLegacyRoleState(@UserIdInt int userId); } services/core/java/com/android/server/role/RoleManagerService.java +4 −31 Original line number Diff line number Diff line Loading @@ -103,7 +103,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C private final Object mLock = new Object(); @NonNull private final LegacyRoleHolderProvider mLegacyRoleHolderProvider; private final LegacyRoleStateProvider mLegacyRoleStateProvider; /** * Maps user id to its state. Loading Loading @@ -139,10 +139,10 @@ public class RoleManagerService extends SystemService implements RoleUserState.C new SparseArray<>(); public RoleManagerService(@NonNull Context context, @NonNull LegacyRoleHolderProvider legacyRoleHolderProvider) { @NonNull LegacyRoleStateProvider legacyRoleStateProvider) { super(context); mLegacyRoleHolderProvider = legacyRoleHolderProvider; mLegacyRoleStateProvider = legacyRoleStateProvider; RoleControllerManager.initializeRemoteServiceComponentName(context); Loading Loading @@ -241,16 +241,6 @@ public class RoleManagerService extends SystemService implements RoleUserState.C return AndroidFuture.completedFuture(null); } //TODO gradually add more role migrations statements here for remaining roles // Make sure to implement LegacyRoleResolutionPolicy#getRoleHolders // for a given role before adding a migration statement for it here maybeMigrateRole(RoleManager.ROLE_ASSISTANT, userId); maybeMigrateRole(RoleManager.ROLE_BROWSER, userId); maybeMigrateRole(RoleManager.ROLE_DIALER, userId); maybeMigrateRole(RoleManager.ROLE_SMS, userId); maybeMigrateRole(RoleManager.ROLE_EMERGENCY, userId); maybeMigrateRole(RoleManager.ROLE_HOME, userId); // Some package state has changed, so grant default roles again. Slog.i(LOG_TAG, "Granting default roles..."); AndroidFuture<Void> future = new AndroidFuture<>(); Loading @@ -266,23 +256,6 @@ public class RoleManagerService extends SystemService implements RoleUserState.C return future; } private void maybeMigrateRole(String role, @UserIdInt int userId) { // Any role for which we have a record are already migrated RoleUserState userState = getOrCreateUserState(userId); if (!userState.isRoleAvailable(role)) { List<String> roleHolders = mLegacyRoleHolderProvider.getLegacyRoleHolders(role, userId); if (roleHolders.isEmpty()) { return; } Slog.i(LOG_TAG, "Migrating " + role + ", legacy holders: " + roleHolders); userState.addRoleName(role); int size = roleHolders.size(); for (int i = 0; i < size; i++) { userState.addRoleHolder(role, roleHolders.get(i)); } } } @Nullable private String computePackageStateHash(@UserIdInt int userId) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); Loading Loading @@ -327,7 +300,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C synchronized (mLock) { RoleUserState userState = mUserStates.get(userId); if (userState == null) { userState = new RoleUserState(userId, this); userState = new RoleUserState(userId, mLegacyRoleStateProvider, this); mUserStates.put(userId, userState); } return userState; Loading services/core/java/com/android/server/role/RoleUserState.java +19 −112 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/policy/role/LegacyRoleResolutionPolicy.javadeleted 100644 → 0 +0 −171 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.server.policy.role; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.role.RoleManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.provider.Settings; import android.text.TextUtils; import android.util.Slog; import com.android.internal.R; import com.android.internal.telephony.SmsApplication; import com.android.internal.util.CollectionUtils; import com.android.server.LocalServices; import com.android.server.role.LegacyRoleHolderProvider; import com.android.server.role.RoleManagerService; import java.util.Collections; import java.util.List; import java.util.Objects; /** * Logic to retrieve the various legacy(pre-Q) equivalents of role holders. * * Unlike {@link RoleManagerService} this is meant to be pretty high-level to allow for depending * on all kinds of various systems that are historically involved in legacy role resolution, * e.g. {@link SmsApplication} * * @see RoleManagerService#migrateRoleIfNecessary */ public class LegacyRoleResolutionPolicy implements LegacyRoleHolderProvider { private static final boolean DEBUG = false; private static final String LOG_TAG = "LegacyRoleResolutionPol"; @NonNull private final Context mContext; public LegacyRoleResolutionPolicy(@NonNull Context context) { mContext = context; } @NonNull @Override public List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId) { switch (roleName) { case RoleManager.ROLE_ASSISTANT: { String packageName; String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.ASSISTANT, userId); // AssistUtils was using the default assistant app if Settings.Secure.ASSISTANT is // null, while only an empty string means user selected "None". if (setting != null) { if (!setting.isEmpty()) { ComponentName componentName = ComponentName.unflattenFromString(setting); packageName = componentName != null ? componentName.getPackageName() : null; } else { packageName = null; } } else if (mContext.getPackageManager().isDeviceUpgrading()) { String defaultAssistant = mContext.getString(R.string.config_defaultAssistant); packageName = !TextUtils.isEmpty(defaultAssistant) ? defaultAssistant : null; } else { packageName = null; } return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_BROWSER: { PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); String packageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName( userId); return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_DIALER: { String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.DIALER_DEFAULT_APPLICATION, userId); String packageName; if (!TextUtils.isEmpty(setting)) { packageName = setting; } else if (mContext.getPackageManager().isDeviceUpgrading()) { // DefaultDialerManager was using the default dialer app if // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid. // TelecomManager.getSystemDialerPackage() won't work because it might not // be ready. packageName = mContext.getString(R.string.config_defaultDialer); } else { packageName = null; } return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_SMS: { String setting = Settings.Secure.getStringForUser(mContext.getContentResolver(), Settings.Secure.SMS_DEFAULT_APPLICATION, userId); String packageName; if (!TextUtils.isEmpty(setting)) { packageName = setting; } else if (mContext.getPackageManager().isDeviceUpgrading()) { // SmsApplication was using the default SMS app if // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid. packageName = mContext.getString(R.string.config_defaultSms); } else { packageName = null; } return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_HOME: { PackageManager packageManager = mContext.getPackageManager(); String packageName; if (packageManager.isDeviceUpgrading()) { ResolveInfo resolveInfo = packageManager.resolveActivityAsUser( new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME), PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId); packageName = resolveInfo != null && resolveInfo.activityInfo != null ? resolveInfo.activityInfo.packageName : null; if (packageName != null && isSettingsApplication(packageName, userId)) { packageName = null; } } else { packageName = null; } return CollectionUtils.singletonOrEmpty(packageName); } case RoleManager.ROLE_EMERGENCY: { String defaultEmergencyApp = Settings.Secure.getStringForUser( mContext.getContentResolver(), Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION, userId); return CollectionUtils.singletonOrEmpty(defaultEmergencyApp); } default: { Slog.e(LOG_TAG, "Don't know how to find legacy role holders for " + roleName); return Collections.emptyList(); } } } private boolean isSettingsApplication(@NonNull String packageName, @UserIdInt int userId) { PackageManager packageManager = mContext.getPackageManager(); ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(new Intent( Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId); if (resolveInfo == null || resolveInfo.activityInfo == null) { return false; } return Objects.equals(packageName, resolveInfo.activityInfo.packageName); } }
services/core/java/com/android/server/policy/role/LegacyRoleStateProviderImpl.java 0 → 100644 +291 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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.server.policy.role; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.role.RoleManager; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ResolveInfo; import android.os.Environment; import android.provider.Settings; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; import android.util.AtomicFile; import android.util.Slog; import android.util.Xml; import com.android.internal.R; import com.android.server.LocalServices; import com.android.server.role.LegacyRoleStateProvider; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Collections; import java.util.Map; import java.util.Objects; import java.util.Set; /** * Implementation to provide legacy role state. */ public class LegacyRoleStateProviderImpl implements LegacyRoleStateProvider { private static final String LOG_TAG = "LegacyRoleState"; private static final String ROLES_FILE_NAME = "roles.xml"; private static final String TAG_ROLES = "roles"; private static final String TAG_ROLE = "role"; private static final String TAG_HOLDER = "holder"; private static final String ATTRIBUTE_NAME = "name"; @NonNull private final Context mContext; public LegacyRoleStateProviderImpl(@NonNull Context context) { mContext = context; } @NonNull @Override public Map<String, Set<String>> getLegacyRoleState(@UserIdInt int userId) { Map<String, Set<String>> roles = readFile(userId); if (roles == null) { roles = readFromLegacySettings(userId); } return roles; } @Nullable private Map<String, Set<String>> readFile(@UserIdInt int userId) { File file = getFile(userId); try (FileInputStream in = new AtomicFile(file).openRead()) { XmlPullParser parser = Xml.newPullParser(); parser.setInput(in, null); Map<String, Set<String>> roles = parseXml(parser); Slog.i(LOG_TAG, "Read legacy roles.xml successfully"); return roles; } catch (FileNotFoundException e) { Slog.i(LOG_TAG, "Legacy roles.xml not found"); return null; } catch (XmlPullParserException | IOException e) { Slog.wtf(LOG_TAG, "Failed to parse legacy roles.xml: " + file, e); return null; } } @NonNull private Map<String, Set<String>> parseXml(@NonNull XmlPullParser parser) throws IOException, XmlPullParserException { int type; int depth; int innerDepth = parser.getDepth() + 1; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { if (depth > innerDepth || type != XmlPullParser.START_TAG) { continue; } if (parser.getName().equals(TAG_ROLES)) { return parseRoles(parser); } } throw new IOException("Missing <" + TAG_ROLES + "> in roles.xml"); } @NonNull private Map<String, Set<String>> parseRoles(@NonNull XmlPullParser parser) throws IOException, XmlPullParserException { Map<String, Set<String>> roles = new ArrayMap<>(); int type; int depth; int innerDepth = parser.getDepth() + 1; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { if (depth > innerDepth || type != XmlPullParser.START_TAG) { continue; } if (parser.getName().equals(TAG_ROLE)) { String roleName = parser.getAttributeValue(null, ATTRIBUTE_NAME); Set<String> roleHolders = parseRoleHoldersLocked(parser); roles.put(roleName, roleHolders); } } return roles; } @NonNull private Set<String> parseRoleHoldersLocked(@NonNull XmlPullParser parser) throws IOException, XmlPullParserException { Set<String> roleHolders = new ArraySet<>(); int type; int depth; int innerDepth = parser.getDepth() + 1; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) { if (depth > innerDepth || type != XmlPullParser.START_TAG) { continue; } if (parser.getName().equals(TAG_HOLDER)) { String roleHolder = parser.getAttributeValue(null, ATTRIBUTE_NAME); roleHolders.add(roleHolder); } } return roleHolders; } @NonNull private static File getFile(@UserIdInt int userId) { return new File(Environment.getUserSystemDirectory(userId), ROLES_FILE_NAME); } @NonNull private Map<String, Set<String>> readFromLegacySettings(@UserIdInt int userId) { Map<String, Set<String>> roles = new ArrayMap<>(); // Assistant ContentResolver contentResolver = mContext.getContentResolver(); String assistantSetting = Settings.Secure.getStringForUser(contentResolver, Settings.Secure.ASSISTANT, userId); PackageManager packageManager = mContext.getPackageManager(); String assistantPackageName; // AssistUtils was using the default assistant app if Settings.Secure.ASSISTANT is // null, while only an empty string means user selected "None". if (assistantSetting != null) { if (!assistantSetting.isEmpty()) { ComponentName componentName = ComponentName.unflattenFromString(assistantSetting); assistantPackageName = componentName != null ? componentName.getPackageName() : null; } else { assistantPackageName = null; } } else if (packageManager.isDeviceUpgrading()) { String defaultAssistant = mContext.getString(R.string.config_defaultAssistant); assistantPackageName = !TextUtils.isEmpty(defaultAssistant) ? defaultAssistant : null; } else { assistantPackageName = null; } if (assistantPackageName != null) { roles.put(RoleManager.ROLE_ASSISTANT, Collections.singleton(assistantPackageName)); } // Browser PackageManagerInternal packageManagerInternal = LocalServices.getService( PackageManagerInternal.class); String browserPackageName = packageManagerInternal.removeLegacyDefaultBrowserPackageName( userId); if (browserPackageName != null) { roles.put(RoleManager.ROLE_BROWSER, Collections.singleton(browserPackageName)); } // Dialer String dialerSetting = Settings.Secure.getStringForUser(contentResolver, Settings.Secure.DIALER_DEFAULT_APPLICATION, userId); String dialerPackageName; if (!TextUtils.isEmpty(dialerSetting)) { dialerPackageName = dialerSetting; } else if (packageManager.isDeviceUpgrading()) { // DefaultDialerManager was using the default dialer app if // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid. // TelecomManager.getSystemDialerPackage() won't work because it might not // be ready. dialerPackageName = mContext.getString(R.string.config_defaultDialer); } else { dialerPackageName = null; } if (dialerPackageName != null) { roles.put(RoleManager.ROLE_DIALER, Collections.singleton(dialerPackageName)); } // SMS String smsSetting = Settings.Secure.getStringForUser(contentResolver, Settings.Secure.SMS_DEFAULT_APPLICATION, userId); String smsPackageName; if (!TextUtils.isEmpty(smsSetting)) { smsPackageName = smsSetting; } else if (mContext.getPackageManager().isDeviceUpgrading()) { // SmsApplication was using the default SMS app if // Settings.Secure.DIALER_DEFAULT_APPLICATION is invalid. smsPackageName = mContext.getString(R.string.config_defaultSms); } else { smsPackageName = null; } if (smsPackageName != null) { roles.put(RoleManager.ROLE_SMS, Collections.singleton(smsPackageName)); } // Home String homePackageName; if (packageManager.isDeviceUpgrading()) { ResolveInfo resolveInfo = packageManager.resolveActivityAsUser( new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME), PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId); homePackageName = resolveInfo != null && resolveInfo.activityInfo != null ? resolveInfo.activityInfo.packageName : null; if (homePackageName != null && isSettingsApplication(homePackageName, userId)) { homePackageName = null; } } else { homePackageName = null; } if (homePackageName != null) { roles.put(RoleManager.ROLE_HOME, Collections.singleton(homePackageName)); } // Emergency String emergencyPackageName = Settings.Secure.getStringForUser(contentResolver, Settings.Secure.EMERGENCY_ASSISTANCE_APPLICATION, userId); if (emergencyPackageName != null) { roles.put(RoleManager.ROLE_EMERGENCY, Collections.singleton(emergencyPackageName)); } return roles; } private boolean isSettingsApplication(@NonNull String packageName, @UserIdInt int userId) { PackageManager packageManager = mContext.getPackageManager(); ResolveInfo resolveInfo = packageManager.resolveActivityAsUser(new Intent( Settings.ACTION_SETTINGS), PackageManager.MATCH_DEFAULT_ONLY | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId); if (resolveInfo == null || resolveInfo.activityInfo == null) { return false; } return Objects.equals(packageName, resolveInfo.activityInfo.packageName); } }
services/core/java/com/android/server/role/LegacyRoleHolderProvider.java→services/core/java/com/android/server/role/LegacyRoleStateProvider.java +13 −10 Original line number Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * 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. Loading @@ -19,22 +19,25 @@ package com.android.server.role; import android.annotation.NonNull; import android.annotation.UserIdInt; import java.util.List; import java.util.Map; import java.util.Set; /** * A provider for migrating legacy "role"s to their actual role implementation. * Provider for legacy role state. * <p> * The role state may come from two sources, either the different pre-role default app settings, or * the pre-modularization roles.xml file stored in platform. * * @hide */ //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER) public interface LegacyRoleHolderProvider { public interface LegacyRoleStateProvider { /** * Get the list of holders of a legacy "role" before its actual role is introduced. * <p> * This method will only be called for the first time a role is made available in the platform. * Get the legacy role state stored in the platform. * * @param roleName the name of the role * @param userId the user ID * @return a list of holders for the given role * @return a mapping of role name to its set of holders */ @NonNull List<String> getLegacyRoleHolders(@NonNull String roleName, @UserIdInt int userId); Map<String, Set<String>> getLegacyRoleState(@UserIdInt int userId); }
services/core/java/com/android/server/role/RoleManagerService.java +4 −31 Original line number Diff line number Diff line Loading @@ -103,7 +103,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C private final Object mLock = new Object(); @NonNull private final LegacyRoleHolderProvider mLegacyRoleHolderProvider; private final LegacyRoleStateProvider mLegacyRoleStateProvider; /** * Maps user id to its state. Loading Loading @@ -139,10 +139,10 @@ public class RoleManagerService extends SystemService implements RoleUserState.C new SparseArray<>(); public RoleManagerService(@NonNull Context context, @NonNull LegacyRoleHolderProvider legacyRoleHolderProvider) { @NonNull LegacyRoleStateProvider legacyRoleStateProvider) { super(context); mLegacyRoleHolderProvider = legacyRoleHolderProvider; mLegacyRoleStateProvider = legacyRoleStateProvider; RoleControllerManager.initializeRemoteServiceComponentName(context); Loading Loading @@ -241,16 +241,6 @@ public class RoleManagerService extends SystemService implements RoleUserState.C return AndroidFuture.completedFuture(null); } //TODO gradually add more role migrations statements here for remaining roles // Make sure to implement LegacyRoleResolutionPolicy#getRoleHolders // for a given role before adding a migration statement for it here maybeMigrateRole(RoleManager.ROLE_ASSISTANT, userId); maybeMigrateRole(RoleManager.ROLE_BROWSER, userId); maybeMigrateRole(RoleManager.ROLE_DIALER, userId); maybeMigrateRole(RoleManager.ROLE_SMS, userId); maybeMigrateRole(RoleManager.ROLE_EMERGENCY, userId); maybeMigrateRole(RoleManager.ROLE_HOME, userId); // Some package state has changed, so grant default roles again. Slog.i(LOG_TAG, "Granting default roles..."); AndroidFuture<Void> future = new AndroidFuture<>(); Loading @@ -266,23 +256,6 @@ public class RoleManagerService extends SystemService implements RoleUserState.C return future; } private void maybeMigrateRole(String role, @UserIdInt int userId) { // Any role for which we have a record are already migrated RoleUserState userState = getOrCreateUserState(userId); if (!userState.isRoleAvailable(role)) { List<String> roleHolders = mLegacyRoleHolderProvider.getLegacyRoleHolders(role, userId); if (roleHolders.isEmpty()) { return; } Slog.i(LOG_TAG, "Migrating " + role + ", legacy holders: " + roleHolders); userState.addRoleName(role); int size = roleHolders.size(); for (int i = 0; i < size; i++) { userState.addRoleHolder(role, roleHolders.get(i)); } } } @Nullable private String computePackageStateHash(@UserIdInt int userId) { ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); Loading Loading @@ -327,7 +300,7 @@ public class RoleManagerService extends SystemService implements RoleUserState.C synchronized (mLock) { RoleUserState userState = mUserStates.get(userId); if (userState == null) { userState = new RoleUserState(userId, this); userState = new RoleUserState(userId, mLegacyRoleStateProvider, this); mUserStates.put(userId, userState); } return userState; Loading
services/core/java/com/android/server/role/RoleUserState.java +19 −112 File changed.Preview size limit exceeded, changes collapsed. Show changes