blob: cb5f0a70161543ca29ad4a258053af03aeb1b487 [file] [log] [blame]
/*
* Copyright (C) 2015 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.devicepolicy;
import static org.mockito.Mockito.mock;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.test.mock.MockContext;
import android.util.ArrayMap;
import org.junit.Assert;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Context used throughout DPMS tests.
*/
public class DpmMockContext extends MockContext {
/**
* User-id of a non-system user we use throughout unit tests.
*/
public static final int CALLER_USER_HANDLE = 20;
/**
* UID corresponding to {@link #CALLER_USER_HANDLE}.
*/
public static final int CALLER_UID = UserHandle.getUid(CALLER_USER_HANDLE, 20123);
/**
* UID used when a caller is on the system user.
*/
public static final int CALLER_SYSTEM_USER_UID = 20321;
/**
* PID of the caller.
*/
public static final int CALLER_PID = 22222;
/**
* UID of the system server.
*/
public static final int SYSTEM_UID = android.os.Process.SYSTEM_UID;
/**
* PID of the system server.
*/
public static final int SYSTEM_PID = 11111;
public static final String ANOTHER_PACKAGE_NAME = "com.another.package.name";
public static final int ANOTHER_UID = UserHandle.getUid(UserHandle.USER_SYSTEM, 18434);
private final MockSystemServices mMockSystemServices;
public static class MockBinder {
public int callingUid = CALLER_UID;
public int callingPid = CALLER_PID;
public final Map<Integer, List<String>> callingPermissions = new ArrayMap<>();
public long clearCallingIdentity() {
final long token = (((long) callingUid) << 32) | (callingPid);
callingUid = SYSTEM_UID;
callingPid = SYSTEM_PID;
return token;
}
public void restoreCallingIdentity(long token) {
callingUid = (int) (token >> 32);
callingPid = (int) token;
}
public int getCallingUid() {
return callingUid;
}
public int getCallingPid() {
return callingPid;
}
public UserHandle getCallingUserHandle() {
return new UserHandle(UserHandle.getUserId(getCallingUid()));
}
public boolean isCallerUidMyUid() {
return callingUid == SYSTEM_UID;
}
}
private final Context realTestContext;
/**
* Use this instance to verify unimplemented methods such as {@link #sendBroadcast}.
* (Spying on {@code this} instance will confuse mockito somehow and I got weired "wrong number
* of arguments" exceptions.)
*/
public final Context spiedContext;
public final MockBinder binder;
public final Resources resources;
/** TODO: Migrate everything to use {@link #permissions} to avoid confusion. */
@Deprecated
public final List<String> callerPermissions = new ArrayList<>();
/** Less confusing alias for {@link #callerPermissions}. */
public final List<String> permissions = callerPermissions;
public String packageName = null;
public ApplicationInfo applicationInfo = null;
public DpmMockContext(MockSystemServices mockSystemServices, Context context) {
mMockSystemServices = mockSystemServices;
realTestContext = context;
binder = new MockBinder();
resources = mock(Resources.class);
spiedContext = mock(Context.class);
}
@Override
public Resources getResources() {
return resources;
}
@Override
public Resources.Theme getTheme() {
return spiedContext.getTheme();
}
@Override
public String getPackageName() {
if (packageName != null) {
return packageName;
}
return super.getPackageName();
}
@Override
public ApplicationInfo getApplicationInfo() {
if (applicationInfo != null) {
return applicationInfo;
}
return super.getApplicationInfo();
}
@Override
public Object getSystemService(String name) {
switch (name) {
case Context.ALARM_SERVICE:
return mMockSystemServices.alarmManager;
case Context.USER_SERVICE:
return mMockSystemServices.userManager;
case Context.POWER_SERVICE:
return mMockSystemServices.powerManager;
case Context.WIFI_SERVICE:
return mMockSystemServices.wifiManager;
case Context.ACCOUNT_SERVICE:
return mMockSystemServices.accountManager;
}
throw new UnsupportedOperationException();
}
@Override
public String getSystemServiceName(Class<?> serviceClass) {
return realTestContext.getSystemServiceName(serviceClass);
}
@Override
public PackageManager getPackageManager() {
return mMockSystemServices.packageManager;
}
public UserManagerInternal getUserManagerInternal() {
return mMockSystemServices.userManagerInternal;
}
@Override
public void enforceCallingOrSelfPermission(String permission, String message) {
if (UserHandle.isSameApp(binder.getCallingUid(), SYSTEM_UID)) {
return; // Assume system has all permissions.
}
List<String> permissions = binder.callingPermissions.get(binder.getCallingUid());
if (permissions == null) {
// TODO: delete the following line. to do this without breaking any tests, first it's
// necessary to remove all tests that set it directly.
permissions = callerPermissions;
// throw new UnsupportedOperationException(
// "Caller UID " + binder.getCallingUid() + " doesn't exist");
}
if (!permissions.contains(permission)) {
throw new SecurityException("Caller doesn't have " + permission + " : " + message);
}
}
@Override
public void sendBroadcast(Intent intent) {
spiedContext.sendBroadcast(intent);
}
@Override
public void sendBroadcast(Intent intent, String receiverPermission) {
spiedContext.sendBroadcast(intent, receiverPermission);
}
@Override
public void sendBroadcastMultiplePermissions(Intent intent, String[] receiverPermissions) {
spiedContext.sendBroadcastMultiplePermissions(intent, receiverPermissions);
}
@Override
public void sendBroadcastAsUserMultiplePermissions(Intent intent, UserHandle user,
String[] receiverPermissions) {
spiedContext.sendBroadcastAsUserMultiplePermissions(intent, user, receiverPermissions);
}
@Override
public void sendBroadcast(Intent intent, String receiverPermission, Bundle options) {
spiedContext.sendBroadcast(intent, receiverPermission, options);
}
@Override
public void sendBroadcast(Intent intent, String receiverPermission, int appOp) {
spiedContext.sendBroadcast(intent, receiverPermission, appOp);
}
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission) {
spiedContext.sendOrderedBroadcast(intent, receiverPermission);
}
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler,
initialCode, initialData, initialExtras);
}
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission, Bundle options,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcast(intent, receiverPermission, options, resultReceiver,
scheduler,
initialCode, initialData, initialExtras);
}
@Override
public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcast(intent, receiverPermission, appOp, resultReceiver,
scheduler,
initialCode, initialData, initialExtras);
}
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user) {
if (binder.callingPid != SYSTEM_PID) {
// Unless called as the system process, can only call if the target user is the
// calling user.
// (The actual check is more complex; we may need to change it later.)
Assert.assertEquals(UserHandle.getUserId(binder.getCallingUid()), user.getIdentifier());
}
spiedContext.sendBroadcastAsUser(intent, user);
}
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission) {
spiedContext.sendBroadcastAsUser(intent, user, receiverPermission);
}
@Override
public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission,
int appOp) {
spiedContext.sendBroadcastAsUser(intent, user, receiverPermission, appOp);
}
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
int initialCode, String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, resultReceiver,
scheduler, initialCode, initialData, initialExtras);
resultReceiver.onReceive(spiedContext, intent);
}
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp,
resultReceiver,
scheduler, initialCode, initialData, initialExtras);
}
@Override
public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
String receiverPermission, int appOp, Bundle options, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
spiedContext.sendOrderedBroadcastAsUser(intent, user, receiverPermission, appOp, options,
resultReceiver, scheduler, initialCode, initialData, initialExtras);
}
@Override
public void sendStickyBroadcast(Intent intent) {
spiedContext.sendStickyBroadcast(intent);
}
@Override
public void sendStickyOrderedBroadcast(Intent intent, BroadcastReceiver resultReceiver,
Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
spiedContext.sendStickyOrderedBroadcast(intent, resultReceiver, scheduler, initialCode,
initialData, initialExtras);
}
@Override
public void removeStickyBroadcast(Intent intent) {
spiedContext.removeStickyBroadcast(intent);
}
@Override
public void sendStickyBroadcastAsUser(Intent intent, UserHandle user) {
spiedContext.sendStickyBroadcastAsUser(intent, user);
}
@Override
public void sendStickyOrderedBroadcastAsUser(Intent intent, UserHandle user,
BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
String initialData, Bundle initialExtras) {
spiedContext.sendStickyOrderedBroadcastAsUser(intent, user, resultReceiver, scheduler, initialCode,
initialData, initialExtras);
}
@Override
public void removeStickyBroadcastAsUser(Intent intent, UserHandle user) {
spiedContext.removeStickyBroadcastAsUser(intent, user);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
mMockSystemServices.registerReceiver(receiver, filter, null);
return spiedContext.registerReceiver(receiver, filter);
}
@Override
public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
String broadcastPermission, Handler scheduler) {
mMockSystemServices.registerReceiver(receiver, filter, scheduler);
return spiedContext.registerReceiver(receiver, filter, broadcastPermission, scheduler);
}
@Override
public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user,
IntentFilter filter, String broadcastPermission, Handler scheduler) {
mMockSystemServices.registerReceiver(receiver, filter, scheduler);
return spiedContext.registerReceiverAsUser(receiver, user, filter, broadcastPermission,
scheduler);
}
@Override
public void unregisterReceiver(BroadcastReceiver receiver) {
mMockSystemServices.unregisterReceiver(receiver);
spiedContext.unregisterReceiver(receiver);
}
@Override
public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
throws PackageManager.NameNotFoundException {
return mMockSystemServices.createPackageContextAsUser(packageName, flags, user);
}
@Override
public ContentResolver getContentResolver() {
return mMockSystemServices.contentResolver;
}
@Override
public int getUserId() {
return UserHandle.getUserId(binder.getCallingUid());
}
}