1 /* 2 * Copyright (C) 2019 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.install.lib; 18 19 import static android.app.PendingIntent.FLAG_MUTABLE; 20 21 import android.app.PendingIntent; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.IntentFilter; 26 import android.content.IntentSender; 27 import android.content.pm.PackageInstaller; 28 import android.os.SystemClock; 29 import android.util.Log; 30 31 import androidx.test.InstrumentationRegistry; 32 33 import java.util.concurrent.BlockingQueue; 34 import java.util.concurrent.LinkedBlockingQueue; 35 import java.util.concurrent.TimeUnit; 36 37 /** 38 * Helper for making IntentSenders whose results are sent back to the test 39 * app. 40 */ 41 public class LocalIntentSender extends BroadcastReceiver { 42 private static final String TAG = "cts.install.lib"; 43 private final BlockingQueue<Intent> mResults = new LinkedBlockingQueue<>(); 44 45 @Override onReceive(Context context, Intent intent)46 public void onReceive(Context context, Intent intent) { 47 Log.i(TAG, "Received intent " + prettyPrint(intent)); 48 mResults.add(intent); 49 } 50 51 /** 52 * Get a LocalIntentSender. 53 */ getIntentSender()54 public IntentSender getIntentSender() { 55 Context context = InstrumentationRegistry.getTargetContext(); 56 // Generate a unique string to ensure each LocalIntentSender gets its own results. 57 String action = LocalIntentSender.class.getName() + SystemClock.elapsedRealtime(); 58 context.registerReceiver(this, new IntentFilter(action), 59 Context.RECEIVER_EXPORTED_UNAUDITED); 60 Intent intent = new Intent(action).setPackage(context.getPackageName()) 61 .addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 62 PendingIntent pending = PendingIntent.getBroadcast(context, 0, intent, FLAG_MUTABLE); 63 return pending.getIntentSender(); 64 } 65 66 /** 67 * Returns and remove the most early Intent received by this LocalIntentSender. 68 */ getResult()69 public Intent getResult() throws InterruptedException { 70 Intent intent = mResults.take(); 71 Log.i(TAG, "Taking intent " + prettyPrint(intent)); 72 return intent; 73 } 74 75 /** 76 * Similar to {@link #getResult()}, but with a timeout. 77 */ pollResult(long timeout, TimeUnit unit)78 public Intent pollResult(long timeout, TimeUnit unit) throws InterruptedException { 79 return mResults.poll(timeout, unit); 80 } 81 prettyPrint(Intent intent)82 private static String prettyPrint(Intent intent) { 83 int sessionId = intent.getIntExtra(PackageInstaller.EXTRA_SESSION_ID, -1); 84 int status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, 85 PackageInstaller.STATUS_FAILURE); 86 String message = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE); 87 return String.format("%s: {\n" 88 + "sessionId = %d\n" 89 + "status = %d\n" 90 + "message = %s\n" 91 + "}", intent, sessionId, status, message); 92 } 93 } 94