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