/* * 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> 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 callerPermissions = new ArrayList<>(); /** Less confusing alias for {@link #callerPermissions}. */ public final List 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 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 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()); } }