Merge "Use a single interface for reading pre-Q and pre-S role state."

This commit is contained in:
TreeHugger Robot
2021-01-15 21:47:58 +00:00
committed by Android (Google) Code Review
6 changed files with 329 additions and 326 deletions

View File

@@ -1,171 +0,0 @@
/*
* 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);
}
}

View File

@@ -0,0 +1,291 @@
/*
* 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);
}
}

View File

@@ -1,5 +1,5 @@
/*
* 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.
@@ -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);
}

View File

@@ -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.
@@ -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);
@@ -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<>();
@@ -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();
@@ -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;

View File

@@ -21,14 +21,11 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.WorkerThread;
import android.os.Environment;
import android.os.Handler;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.BackgroundThread;
@@ -38,13 +35,6 @@ import com.android.internal.util.function.pooled.PooledLambda;
import com.android.role.persistence.RolesPersistence;
import com.android.role.persistence.RolesState;
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.ArrayList;
import java.util.List;
import java.util.Map;
@@ -59,22 +49,16 @@ class RoleUserState {
public static final int VERSION_UNDEFINED = -1;
private static final String ROLES_FILE_NAME = "roles.xml";
private static final long WRITE_DELAY_MILLIS = 200;
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_VERSION = "version";
private static final String ATTRIBUTE_NAME = "name";
private static final String ATTRIBUTE_PACKAGES_HASH = "packagesHash";
private final RolesPersistence mPersistence = RolesPersistence.createInstance();
@UserIdInt
private final int mUserId;
@NonNull
private final LegacyRoleStateProvider mLegacyStateProvider;
@NonNull
private final Callback mCallback;
@@ -108,10 +92,13 @@ class RoleUserState {
* Create a new user state, and read its state from disk if previously persisted.
*
* @param userId the user id for this user state
* @param legacyStateProvider the provider for legacy role state
* @param callback the callback for this user state
*/
public RoleUserState(@UserIdInt int userId, @NonNull Callback callback) {
public RoleUserState(@UserIdInt int userId,
@NonNull LegacyRoleStateProvider legacyStateProvider, @NonNull Callback callback) {
mUserId = userId;
mLegacyStateProvider = legacyStateProvider;
mCallback = callback;
readFile();
@@ -368,102 +355,27 @@ class RoleUserState {
private void readFile() {
synchronized (mLock) {
RolesState roles = mPersistence.readForUser(UserHandle.of(mUserId));
if (roles == null) {
readLegacyFileLocked();
scheduleWriteFileLocked();
return;
RolesState roleState = mPersistence.readForUser(UserHandle.of(mUserId));
Map<String, Set<String>> roles;
if (roleState != null) {
mVersion = roleState.getVersion();
mPackagesHash = roleState.getPackagesHash();
roles = roleState.getRoles();
} else {
roles = mLegacyStateProvider.getLegacyRoleState(mUserId);
}
mVersion = roles.getVersion();
mPackagesHash = roles.getPackagesHash();
mRoles.clear();
for (Map.Entry<String, Set<String>> entry : roles.getRoles().entrySet()) {
for (Map.Entry<String, Set<String>> entry : roles.entrySet()) {
String roleName = entry.getKey();
ArraySet<String> roleHolders = new ArraySet<>(entry.getValue());
mRoles.put(roleName, roleHolders);
}
}
}
private void readLegacyFileLocked() {
File file = getFile(mUserId);
try (FileInputStream in = new AtomicFile(file).openRead()) {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(in, null);
parseXmlLocked(parser);
Slog.i(LOG_TAG, "Read roles.xml successfully");
} catch (FileNotFoundException e) {
Slog.i(LOG_TAG, "roles.xml not found");
} catch (XmlPullParserException | IOException e) {
throw new IllegalStateException("Failed to parse roles.xml: " + file, e);
}
}
private void parseXmlLocked(@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)) {
parseRolesLocked(parser);
return;
if (roleState == null) {
scheduleWriteFileLocked();
}
}
Slog.w(LOG_TAG, "Missing <" + TAG_ROLES + "> in roles.xml");
}
private void parseRolesLocked(@NonNull XmlPullParser parser) throws IOException,
XmlPullParserException {
mVersion = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_VERSION));
mPackagesHash = parser.getAttributeValue(null, ATTRIBUTE_PACKAGES_HASH);
mRoles.clear();
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);
ArraySet<String> roleHolders = parseRoleHoldersLocked(parser);
mRoles.put(roleName, roleHolders);
}
}
}
@NonNull
private ArraySet<String> parseRoleHoldersLocked(@NonNull XmlPullParser parser)
throws IOException, XmlPullParserException {
ArraySet<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;
}
/**
@@ -549,11 +461,6 @@ class RoleUserState {
}
}
@NonNull
private static File getFile(@UserIdInt int userId) {
return new File(Environment.getUserSystemDirectory(userId), ROLES_FILE_NAME);
}
/**
* Callback for a user state.
*/

View File

@@ -160,7 +160,7 @@ import com.android.server.pm.UserManagerService;
import com.android.server.pm.dex.SystemServerDexLoadReporter;
import com.android.server.policy.PermissionPolicyService;
import com.android.server.policy.PhoneWindowManager;
import com.android.server.policy.role.LegacyRoleResolutionPolicy;
import com.android.server.policy.role.LegacyRoleStateProviderImpl;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.power.ThermalManagerService;
@@ -2021,7 +2021,7 @@ public final class SystemServer implements Dumpable {
// Grants default permissions and defines roles
t.traceBegin("StartRoleManagerService");
mSystemServiceManager.startService(new RoleManagerService(
mSystemContext, new LegacyRoleResolutionPolicy(mSystemContext)));
mSystemContext, new LegacyRoleStateProviderImpl(mSystemContext)));
t.traceEnd();
// We need to always start this service, regardless of whether the