1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.cts.deviceandprofileowner; 18 19 import android.app.WallpaperManager; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.graphics.Bitmap; 25 import android.os.Process; 26 import android.os.UserHandle; 27 import android.os.UserManager; 28 import com.android.compatibility.common.util.BitmapUtils; 29 30 import java.io.Closeable; 31 import java.io.IOException; 32 import java.lang.reflect.Method; 33 import java.util.concurrent.ArrayBlockingQueue; 34 import java.util.concurrent.BlockingQueue; 35 import java.util.concurrent.TimeUnit; 36 37 /** 38 * These tests verify that the device / profile owner can use appropriate API for customization 39 * (DevicePolicyManager.setUserIcon(), WallpaperManager.setBitmap(), etc.) even in case, 40 * when appropriate restrictions are set. The tested restrictions are 41 * {@link UserManager#DISALLOW_SET_WALLPAPER} and {@link UserManager#DISALLOW_SET_USER_ICON}. 42 */ 43 public class CustomizationRestrictionsTest extends BaseDeviceAdminTest { 44 45 private static final int BROADCAST_TIMEOUT_SEC = 3; 46 47 // Class sets/resets restriction in try-with-resources statement. 48 private class RestrictionApplicator implements Closeable { 49 private final String mRestriction; 50 RestrictionApplicator(String restriction) { 51 mRestriction = restriction; 52 mDevicePolicyManager.addUserRestriction(ADMIN_RECEIVER_COMPONENT, mRestriction); 53 } 54 55 @Override 56 public void close() throws IOException { 57 mDevicePolicyManager.clearUserRestriction(ADMIN_RECEIVER_COMPONENT, mRestriction); 58 } 59 } 60 61 // Class subscribes/unsubscribe for broadcast notification in try-with-resources statement. 62 private class BroadcastReceiverRegistrator implements Closeable { 63 private final BlockingBroadcastReceiver mReceiver; 64 public BroadcastReceiverRegistrator(String action) { 65 final IntentFilter filter = new IntentFilter(); 66 filter.addAction(action); 67 mReceiver = new BlockingBroadcastReceiver(); 68 mContext.registerReceiver(mReceiver, filter); 69 } 70 71 @Override 72 public void close() throws IOException { 73 mContext.unregisterReceiver(mReceiver); 74 } 75 76 public void waitForBroadcast() throws Exception { 77 mReceiver.waitForBroadcast(); 78 } 79 } 80 81 private class BlockingBroadcastReceiver extends BroadcastReceiver { 82 private BlockingQueue<Integer> mQueue = new ArrayBlockingQueue<Integer> (1); 83 84 @Override 85 public void onReceive(Context context, Intent intent) { 86 assertTrue(mQueue.add(0)); 87 } 88 89 public void waitForBroadcast() throws Exception { 90 Integer result = mQueue.poll(BROADCAST_TIMEOUT_SEC, TimeUnit.SECONDS); 91 assertNotNull(result); 92 } 93 } 94 95 private static int getUserId() throws Exception { 96 UserHandle userHandle = Process.myUserHandle(); 97 Class<?>[] noParam = {}; 98 Class<?> userHandleClass = userHandle.getClass(); 99 Method methodGetIdentifier = userHandleClass.getDeclaredMethod("getIdentifier", noParam); 100 return (Integer) methodGetIdentifier.invoke(userHandle, null); 101 } 102 103 private Bitmap getUserIcon() throws Exception { 104 Class<?>[] paramInt = new Class[1]; 105 paramInt[0] = Integer.TYPE; 106 Class<?> umClass = mUserManager.getClass(); 107 Method methodGetUserIcon = umClass.getDeclaredMethod("getUserIcon", paramInt); 108 return (Bitmap) methodGetUserIcon.invoke(mUserManager, getUserId()); 109 } 110 111 // The idea of testing is check if a DO/PO can set a wallpapper despite the 112 // DISALLOW_SET_WALLPAPER restriction is set. But we can't use 113 // pixel-by-pixel comparison of the reference bitmap (the bitmap we want to be a 114 // wallpaper) and current wallpaper bitmap, because the reference bitmap can be 115 // processed while setting (e.g. crop or scale), and getter may return us different 116 // (but visually the same) Bitmap object. Thus in this test we check if the new 117 // wallpaper is different from the old one after we ran a setter method. 118 public void testDisallowSetWallpaper_allowed() throws Exception { 119 final WallpaperManager wallpaperManager = WallpaperManager.getInstance(mContext); 120 final Bitmap originalWallpaper = BitmapUtils.getWallpaperBitmap(mContext); 121 final Bitmap originalWallpaperCopy = 122 originalWallpaper.copy(originalWallpaper.getConfig(), false); 123 124 try ( 125 // Set restriction and subscribe for the broadcast. 126 final RestrictionApplicator restr = 127 new RestrictionApplicator(UserManager.DISALLOW_SET_WALLPAPER); 128 final BroadcastReceiverRegistrator bcast = 129 new BroadcastReceiverRegistrator(Intent.ACTION_WALLPAPER_CHANGED); 130 ) { 131 assertTrue(mUserManager.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER)); 132 133 // Checking setBitmap() method. 134 Bitmap oldWallpaper = originalWallpaperCopy; 135 wallpaperManager.setBitmap(BitmapUtils.generateRandomBitmap(97, 73)); 136 bcast.waitForBroadcast(); 137 Bitmap newWallpaper = BitmapUtils.getWallpaperBitmap(mContext); 138 assertFalse(BitmapUtils.compareBitmaps(newWallpaper, oldWallpaper)); 139 140 // Checking setStream() method. 141 oldWallpaper = newWallpaper; 142 final Bitmap wallpaperForStream = BitmapUtils.generateRandomBitmap(83, 69); 143 wallpaperManager.setStream(BitmapUtils.bitmapToInputStream(wallpaperForStream)); 144 bcast.waitForBroadcast(); 145 newWallpaper = BitmapUtils.getWallpaperBitmap(mContext); 146 assertFalse(BitmapUtils.compareBitmaps(newWallpaper, oldWallpaper)); 147 148 // Checking setResource() method. 149 oldWallpaper = newWallpaper; 150 wallpaperManager.setResource(R.raw.wallpaper); 151 bcast.waitForBroadcast(); 152 newWallpaper = BitmapUtils.getWallpaperBitmap(mContext); 153 assertFalse(BitmapUtils.compareBitmaps(newWallpaper, oldWallpaper)); 154 } finally { 155 wallpaperManager.setBitmap(originalWallpaperCopy); 156 } 157 assertFalse(mUserManager.hasUserRestriction(UserManager.DISALLOW_SET_WALLPAPER)); 158 } 159 160 // The idea behind this test is similar to testDisallowSetWallpaper_allowed 161 public void testDisallowSetUserIcon_allowed() throws Exception { 162 final Bitmap originalIcon = getUserIcon(); 163 164 try ( 165 // Apply restriction. 166 final RestrictionApplicator restr = 167 new RestrictionApplicator(UserManager.DISALLOW_SET_USER_ICON); 168 ) { 169 assertTrue(mUserManager.hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON)); 170 final Bitmap randomBmp = BitmapUtils.generateRandomBitmap(17, 31); 171 mDevicePolicyManager.setUserIcon(ADMIN_RECEIVER_COMPONENT, randomBmp); 172 final Bitmap currentIcon = getUserIcon(); 173 assertNotSame(randomBmp, currentIcon); 174 assertFalse(BitmapUtils.compareBitmaps(originalIcon, currentIcon)); 175 } finally { 176 if (originalIcon == null) { 177 // There is no way to restore absence of an icon. Thus set white 178 // icon for esthetic reasons. 179 mDevicePolicyManager.setUserIcon(ADMIN_RECEIVER_COMPONENT, 180 BitmapUtils.generateWhiteBitmap(20, 20)); 181 } else { 182 mDevicePolicyManager.setUserIcon(ADMIN_RECEIVER_COMPONENT, originalIcon); 183 } 184 } 185 assertFalse(mUserManager.hasUserRestriction(UserManager.DISALLOW_SET_USER_ICON)); 186 } 187 } 188