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