1 /* 2 * Copyright (C) 2024 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 package android.app.fgsstarttesthelper; 17 18 import static android.app.fgsstarttesthelper.FgsTestCommon.ACTION_START_NEW_LOGIC_TEST; 19 import static android.app.fgsstarttesthelper.FgsTestCommon.EXTRA_REPLY_INTENT; 20 21 import android.app.ForegroundServiceStartNotAllowedException; 22 import android.app.job.JobInfo; 23 import android.app.job.JobParameters; 24 import android.app.job.JobScheduler; 25 import android.app.job.JobService; 26 import android.content.BroadcastReceiver; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.os.Bundle; 31 import android.util.Log; 32 33 import java.util.concurrent.atomic.AtomicInteger; 34 35 public class FgsNewLogicTest extends BroadcastReceiver { 36 static final String TAG = "FgsNewLogicTest"; 37 38 private static final int JOB_ID = 123454; 39 40 @Override onReceive(Context context, Intent intent)41 public void onReceive(Context context, Intent intent) { 42 Log.i(TAG, "onReceive: " + intent + " extras=" + intent.getExtras()); 43 if (ACTION_START_NEW_LOGIC_TEST.equals(intent.getAction())) { 44 runTest(context, intent.getParcelableExtra(EXTRA_REPLY_INTENT, Intent.class)); 45 } 46 } 47 runTest(Context context, Intent replyIntent)48 private void runTest(Context context, Intent replyIntent) { 49 Log.i(TAG, "runTest: replyIntent=" + replyIntent); 50 51 try { 52 final var extras = new Bundle(); 53 extras.putParcelable(EXTRA_REPLY_INTENT, replyIntent); 54 55 final var job = new JobInfo.Builder(JOB_ID, new ComponentName(context, Fgs.class)) 56 .setExpedited(true) 57 .setTransientExtras(extras) 58 .build(); 59 60 final var result = context.getSystemService(JobScheduler.class).schedule(job); 61 if (result != JobScheduler.RESULT_SUCCESS) { 62 throw new RuntimeException("JobScheduler.schedule() returned " + result); 63 } 64 65 Log.i(TAG, "runTest done"); 66 } catch (Throwable e) { 67 Log.i(TAG, "runTest failed", e); 68 var reply = new FgsNewLogicMessage(); 69 reply.setFgsStarted(false); 70 reply.setUnexpectedErrorMessage("Caught unexpected exception: " + e); 71 72 Log.w(TAG, "Sending back reply intent with message " + reply); 73 reply.setToIntent(replyIntent); 74 context.sendBroadcast(replyIntent); 75 } 76 } 77 78 public static class Fgs extends JobService { 79 public static final AtomicInteger sJobStartCount = new AtomicInteger(0); 80 81 @Override onStartJob(JobParameters params)82 public boolean onStartJob(JobParameters params) { 83 final var replyIntent = params.getTransientExtras().getParcelable( 84 EXTRA_REPLY_INTENT, Intent.class); 85 Log.i(TAG, "onStartJob: replyIntent=" + replyIntent); 86 sJobStartCount.incrementAndGet(); 87 88 var reply = new FgsNewLogicMessage(); 89 reply.setFgsStarted(false); 90 reply.setUnexpectedErrorMessage("Unexpected error"); 91 92 try { 93 startForeground(1, FgsTestCommon.createNotification(this)); 94 95 reply.setFgsStarted(true); 96 reply.setUnexpectedErrorMessage(null); 97 98 Log.w(TAG, "FGS started "); 99 } catch (ForegroundServiceStartNotAllowedException e) { 100 Log.w(TAG, "Received ForegroundServiceStartNotAllowedException", e); 101 reply.setFgsStarted(false); 102 reply.setUnexpectedErrorMessage(null); 103 } catch (Throwable e) { 104 Log.w(TAG, "startForeground failed", e); 105 reply.setFgsStarted(false); 106 reply.setUnexpectedErrorMessage("Caught unexpected exception: " + e); 107 } 108 109 reply.setToIntent(replyIntent); 110 111 Log.w(TAG, "Sending back reply intent with message " + reply); 112 sendBroadcast(replyIntent); 113 114 return false; 115 } 116 117 @Override onStopJob(JobParameters params)118 public boolean onStopJob(JobParameters params) { 119 return false; 120 } 121 } 122 } 123