fix: 首次提交

This commit is contained in:
2024-12-09 11:25:23 +08:00
parent d0c01071e9
commit 2c2109a5f3
4741 changed files with 290641 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
/*
* 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.settingslib.testutils;
import static com.google.common.truth.Truth.assertThat;
import android.graphics.drawable.Drawable;
import org.robolectric.Shadows;
import org.robolectric.shadows.ShadowDrawable;
public class DrawableTestHelper {
public static void assertDrawableResId(Drawable drawable, int resId) {
final ShadowDrawable shadow = Shadows.shadowOf(drawable);
assertThat(shadow.getCreatedFromResId()).isEqualTo(resId);
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2023 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.settingslib.testutils;
import org.robolectric.util.ReflectionHelpers;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class OverpoweredReflectionHelper extends ReflectionHelpers {
/**
* Robolectric upstream does not rely on or encourage this behaviour.
*
* @param field
*/
private static void makeFieldVeryAccessible(Field field) {
field.setAccessible(true);
// remove 'final' modifier if present
if ((field.getModifiers() & Modifier.FINAL) == Modifier.FINAL) {
Field modifiersField = getModifiersField();
modifiersField.setAccessible(true);
try {
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
}
}
private static Field getModifiersField() {
try {
return Field.class.getDeclaredField("modifiers");
} catch (NoSuchFieldException e) {
try {
Method getFieldsMethod =
Class.class.getDeclaredMethod("getDeclaredFields0", boolean.class);
getFieldsMethod.setAccessible(true);
Field[] fields = (Field[]) getFieldsMethod.invoke(Field.class, false);
for (Field modifiersField : fields) {
if ("modifiers".equals(modifiersField.getName())) {
return modifiersField;
}
}
} catch (ReflectiveOperationException innerE) {
throw new AssertionError(innerE);
}
}
throw new AssertionError();
}
/**
* Reflectively set the value of a static field.
*
* @param field Field object.
* @param fieldNewValue The new value.
*/
public static void setStaticField(Field field, Object fieldNewValue) {
try {
makeFieldVeryAccessible(field);
field.setAccessible(true);
field.set(null, fieldNewValue);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Reflectively set the value of a static field.
*
* @param clazz Target class.
* @param fieldName The field name.
* @param fieldNewValue The new value.
*/
public static void setStaticField(Class<?> clazz, String fieldName, Object fieldNewValue) {
try {
setStaticField(clazz.getDeclaredField(fieldName), fieldNewValue);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -0,0 +1,100 @@
/*
* 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.settingslib.testutils.shadow;
import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_ALL;
import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_AUDIO;
import static android.bluetooth.BluetoothAdapter.ACTIVE_DEVICE_PHONE_CALL;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.os.ParcelUuid;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.List;
@Implements(value = BluetoothAdapter.class)
public class ShadowBluetoothAdapter extends org.robolectric.shadows.ShadowBluetoothAdapter {
private List<Integer> mSupportedProfiles;
private List<BluetoothDevice> mMostRecentlyConnectedDevices;
private BluetoothProfile.ServiceListener mServiceListener;
private ParcelUuid[] mParcelUuids;
@Implementation
protected boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
int profile) {
mServiceListener = listener;
return true;
}
public BluetoothProfile.ServiceListener getServiceListener() {
return mServiceListener;
}
@Implementation
protected List<Integer> getSupportedProfiles() {
return mSupportedProfiles;
}
public void setSupportedProfiles(List<Integer> supportedProfiles) {
mSupportedProfiles = supportedProfiles;
}
@Implementation
protected List<BluetoothDevice> getMostRecentlyConnectedDevices() {
return mMostRecentlyConnectedDevices;
}
public void setMostRecentlyConnectedDevices(List<BluetoothDevice> list) {
mMostRecentlyConnectedDevices = list;
}
@Implementation
protected boolean removeActiveDevice(int profiles) {
if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL
&& profiles != ACTIVE_DEVICE_ALL) {
return false;
}
return true;
}
@Implementation
protected boolean setActiveDevice(BluetoothDevice device, int profiles) {
if (device == null) {
return false;
}
if (profiles != ACTIVE_DEVICE_AUDIO && profiles != ACTIVE_DEVICE_PHONE_CALL
&& profiles != ACTIVE_DEVICE_ALL) {
return false;
}
return true;
}
@Implementation
protected ParcelUuid[] getUuids() {
return mParcelUuids;
}
public void setUuids(ParcelUuid[] uuids) {
mParcelUuids = uuids;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2023 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.settingslib.testutils.shadow;
import android.Manifest;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.hardware.display.ColorDisplayManager;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@Implements(ColorDisplayManager.class)
public class ShadowColorDisplayManager extends org.robolectric.shadows.ShadowColorDisplayManager {
private boolean mIsReduceBrightColorsActivated;
@Implementation
@SystemApi
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public boolean setReduceBrightColorsActivated(boolean activated) {
mIsReduceBrightColorsActivated = activated;
return true;
}
@Implementation
@SystemApi
public boolean isReduceBrightColorsActivated() {
return mIsReduceBrightColorsActivated;
}
}

View File

@@ -0,0 +1,44 @@
/*
* 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.settingslib.testutils.shadow;
import android.content.Context;
import android.telecom.DefaultDialerManager;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
@Implements(DefaultDialerManager.class)
public class ShadowDefaultDialerManager {
private static String sDefaultDialer;
@Resetter
public static void reset() {
sDefaultDialer = null;
}
@Implementation
protected static String getDefaultDialerApplication(Context context) {
return sDefaultDialer;
}
public static void setDefaultDialerApplication(String dialer) {
sDefaultDialer = dialer;
}
}

View File

@@ -0,0 +1,41 @@
/*
* 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.settingslib.testutils.shadow;
import static org.mockito.Mockito.mock;
import com.android.internal.jank.InteractionJankMonitor;
import org.mockito.Mockito;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
@Implements(InteractionJankMonitor.class)
public class ShadowInteractionJankMonitor {
public static final InteractionJankMonitor MOCK_INSTANCE = mock(InteractionJankMonitor.class);
@Resetter
public static void reset() {
Mockito.reset(MOCK_INSTANCE);
}
@Implementation
public static InteractionJankMonitor getInstance() {
return MOCK_INSTANCE;
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) 2023 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.settingslib.testutils.shadow;
import android.content.AttributionSource;
import android.content.Context;
import android.content.PermissionChecker;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import java.util.HashMap;
import java.util.Map;
/** Shadow class of {@link PermissionChecker}. */
@Implements(PermissionChecker.class)
public class ShadowPermissionChecker {
private static final Map<String, Map<String, Integer>> RESULTS = new HashMap<>();
/** Set the result of permission check for a specific permission. */
public static void setResult(String packageName, String permission, int result) {
if (!RESULTS.containsKey(packageName)) {
RESULTS.put(packageName, new HashMap<>());
}
RESULTS.get(packageName).put(permission, result);
}
/** Check the permission of calling package. */
@Implementation
public static int checkCallingPermissionForDataDelivery(
Context context,
String permission,
String packageName,
String attributionTag,
String message) {
return RESULTS.containsKey(packageName) && RESULTS.get(packageName).containsKey(permission)
? RESULTS.get(packageName).get(permission)
: PermissionChecker.checkCallingPermissionForDataDelivery(
context, permission, packageName, attributionTag, message);
}
/** Check general permission. */
@Implementation
public static int checkPermissionForDataDelivery(
Context context,
String permission,
int pid,
int uid,
String packageName,
String attributionTag,
String message) {
return RESULTS.containsKey(packageName) && RESULTS.get(packageName).containsKey(permission)
? RESULTS.get(packageName).get(permission)
: PermissionChecker.checkPermissionForDataDelivery(
context, permission, pid, uid, packageName, attributionTag, message);
}
/** Check general permission. */
@Implementation
public static int checkPermissionForPreflight(@NonNull Context context,
@NonNull String permission, int pid, int uid, @Nullable String packageName) {
return checkPermissionForPreflight(context, permission, new AttributionSource(
uid, packageName, null /*attributionTag*/));
}
/** Check general permission. */
@Implementation
public static int checkPermissionForPreflight(@NonNull Context context,
@NonNull String permission, @NonNull AttributionSource attributionSource) {
final String packageName = attributionSource.getPackageName();
return RESULTS.containsKey(packageName) && RESULTS.get(packageName).containsKey(permission)
? RESULTS.get(packageName).get(permission)
: PermissionChecker.checkPermissionForPreflight(
context, permission, attributionSource);
}
}

View File

@@ -0,0 +1,110 @@
/*
* Copyright 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.settingslib.testutils.shadow;
import android.media.MediaRoute2Info;
import android.media.MediaRouter2Manager;
import android.media.RoutingSessionInfo;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.List;
@Implements(MediaRouter2Manager.class)
public class ShadowRouter2Manager {
private List<MediaRoute2Info> mAvailableRoutes = new ArrayList<>();
private List<MediaRoute2Info> mAllRoutes;
private List<MediaRoute2Info> mDeselectableRoutes;
private List<RoutingSessionInfo> mRemoteSessions;
private List<RoutingSessionInfo> mRoutingSessions;
private RoutingSessionInfo mSystemRoutingSession;
@Implementation
protected List<MediaRoute2Info> getAvailableRoutes(String packageName) {
return mAvailableRoutes;
}
public void setAvailableRoutes(List<MediaRoute2Info> infos) {
mAvailableRoutes = infos;
}
@Implementation
protected List<MediaRoute2Info> getAllRoutes() {
return mAllRoutes;
}
public void setAllRoutes(List<MediaRoute2Info> infos) {
mAllRoutes = infos;
}
@Implementation
protected List<RoutingSessionInfo> getRemoteSessions() {
return mRemoteSessions;
}
public void setRemoteSessions(List<RoutingSessionInfo> infos) {
mRemoteSessions = infos;
}
@Implementation
protected List<RoutingSessionInfo> getRoutingSessions(String packageName) {
return mRoutingSessions;
}
public void setRoutingSessions(List<RoutingSessionInfo> infos) {
mRoutingSessions = infos;
}
@Implementation
public RoutingSessionInfo getSystemRoutingSession(@Nullable String packageName) {
return mSystemRoutingSession;
}
public void setSystemRoutingSession(RoutingSessionInfo sessionInfo) {
mSystemRoutingSession = sessionInfo;
}
@Implementation
public List<MediaRoute2Info> getDeselectableRoutes(@NonNull RoutingSessionInfo sessionInfo) {
return mDeselectableRoutes;
}
public void setDeselectableRoutes(List<MediaRoute2Info> routes) {
mDeselectableRoutes = routes;
}
public static ShadowRouter2Manager getShadow() {
return (ShadowRouter2Manager) Shadow.extract(
MediaRouter2Manager.getInstance(RuntimeEnvironment.application));
}
@Implementation
protected List<MediaRoute2Info> getTransferableRoutes(String packageName) {
return mAvailableRoutes;
}
public void setTransferableRoutes(List<MediaRoute2Info> infos) {
mAvailableRoutes = infos;
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2023 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.settingslib.testutils.shadow;
import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
import android.content.ContentResolver;
import android.provider.Settings;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.shadows.ShadowSettings;
@Implements(value = Settings.Secure.class)
public class ShadowSecure extends ShadowSettings.ShadowSecure {
@Implementation(minSdk = JELLY_BEAN_MR1)
public static boolean putStringForUser(ContentResolver cr, String name, String value,
int userHandle) {
return putString(cr, name, value);
}
}

View File

@@ -0,0 +1,46 @@
/*
* 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.settingslib.testutils.shadow;
import android.content.ComponentName;
import android.content.Context;
import com.android.internal.telephony.SmsApplication;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.annotation.Resetter;
@Implements(SmsApplication.class)
public class ShadowSmsApplication {
private static ComponentName sDefaultSmsApplication;
@Resetter
public static void reset() {
sDefaultSmsApplication = null;
}
@Implementation
protected static ComponentName getDefaultSmsApplication(Context context, boolean update) {
return sDefaultSmsApplication;
}
public static void setDefaultSmsApplication(ComponentName cn) {
sDefaultSmsApplication = cn;
}
}

View File

@@ -0,0 +1,105 @@
/*
* 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.settingslib.testutils.shadow;
import android.annotation.UserIdInt;
import android.content.Context;
import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
import android.os.UserHandle;
import android.os.UserManager;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.versioning.AndroidVersions.NMR1;
import org.robolectric.versioning.AndroidVersions.U;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Implements(value = UserManager.class)
public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager {
private List<UserInfo> mUserInfos = addProfile(0, "Owner");
private final Map<Integer, UserProperties> mUserPropertiesMap = new HashMap<>();
@Implementation
protected static UserManager get(Context context) {
return (UserManager) context.getSystemService(Context.USER_SERVICE);
}
@Implementation
protected int[] getProfileIdsWithDisabled(int userId) {
return mUserInfos.stream().mapToInt(s -> s.id).toArray();
}
@Implementation
protected List<UserInfo> getProfiles() {
return mUserInfos;
}
public List<UserInfo> addProfile(int id, String name) {
List<UserInfo> userInfoList = mUserInfos;
if (userInfoList == null) {
userInfoList = new ArrayList<>();
}
final UserInfo userInfo = new UserInfo();
userInfo.id = id;
userInfo.name = name;
userInfoList.add(userInfo);
return userInfoList;
}
@Implementation
protected List<UserInfo> getProfiles(@UserIdInt int userHandle) {
return getProfiles();
}
/**
* @return {@code false} by default, or the value specified via {@link #setIsAdminUser(boolean)}
*/
@Implementation(minSdk = NMR1.SDK_INT)
public boolean isAdminUser() {
return getUserInfo(UserHandle.myUserId()).isAdmin();
}
/**
* Sets that the current user is an admin user; controls the return value of
* {@link UserManager#isAdminUser}.
*/
public void setIsAdminUser(boolean isAdminUser) {
UserInfo userInfo = getUserInfo(UserHandle.myUserId());
if (isAdminUser) {
userInfo.flags |= UserInfo.FLAG_ADMIN;
} else {
userInfo.flags &= ~UserInfo.FLAG_ADMIN;
}
}
public void setupUserProperty(int userId, int showInSettings) {
UserProperties userProperties = new UserProperties(new UserProperties.Builder()
.setShowInSettings(showInSettings).build());
mUserPropertiesMap.putIfAbsent(userId, userProperties);
}
@Implementation(minSdk = U.SDK_INT)
protected UserProperties getUserProperties(UserHandle user) {
return mUserPropertiesMap.getOrDefault(user.getIdentifier(),
new UserProperties(new UserProperties.Builder().build()));
}
}