1 /* 2 * Copyright (C) 2017 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 android.jobscheduler.cts.jobtestapp; 18 19 import static android.jobscheduler.cts.jobtestapp.TestJobSchedulerReceiver.EXTRA_REQUEST_JOB_UID_STATE; 20 import static android.jobscheduler.cts.jobtestapp.TestJobSchedulerReceiver.EXTRA_SET_NOTIFICATION; 21 import static android.jobscheduler.cts.jobtestapp.TestJobSchedulerReceiver.EXTRA_SET_NOTIFICATION_JOB_END_POLICY; 22 import static android.jobscheduler.cts.jobtestapp.TestJobSchedulerReceiver.EXTRA_SLOW_START; 23 import static android.jobscheduler.cts.jobtestapp.TestJobSchedulerReceiver.EXTRA_SLOW_STOP; 24 import static android.jobscheduler.cts.jobtestapp.TestJobSchedulerReceiver.PACKAGE_NAME; 25 26 import android.app.ActivityManager; 27 import android.app.Notification; 28 import android.app.NotificationChannel; 29 import android.app.NotificationManager; 30 import android.app.job.JobParameters; 31 import android.app.job.JobService; 32 import android.content.Intent; 33 import android.os.Bundle; 34 import android.os.Process; 35 import android.util.Log; 36 37 import java.io.BufferedReader; 38 import java.io.FileReader; 39 import java.io.IOException; 40 41 public class TestJobService extends JobService { 42 private static final String TAG = TestJobService.class.getSimpleName(); 43 public static final String ACTION_JOB_STARTED = PACKAGE_NAME + ".action.JOB_STARTED"; 44 public static final String ACTION_JOB_STOPPED = PACKAGE_NAME + ".action.JOB_STOPPED"; 45 public static final String JOB_PARAMS_EXTRA_KEY = PACKAGE_NAME + ".extra.JOB_PARAMETERS"; 46 public static final String JOB_PROC_STATE_KEY = PACKAGE_NAME + ".extra.PROC_STATE"; 47 public static final String JOB_CAPABILITIES_KEY = PACKAGE_NAME + ".extra.CAPABILITIES"; 48 public static final String JOB_OOM_SCORE_ADJ_KEY = PACKAGE_NAME + ".extra.OOM_SCORE_ADJ"; 49 50 // TODO: Move ProcessList.INVALID_ADJ to an app-accessible location and mark it @TestApi 51 public static final int INVALID_ADJ = -10000; // ProcessList.INVALID_ADJ 52 53 @Override onStartJob(JobParameters params)54 public boolean onStartJob(JobParameters params) { 55 Log.i(TAG, "Test job executing: " + params.getJobId()); 56 final Bundle transientExtras = params.getTransientExtras(); 57 final Intent reportJobStartIntent = new Intent(ACTION_JOB_STARTED); 58 reportJobStartIntent.putExtra(JOB_PARAMS_EXTRA_KEY, params); 59 final boolean requestJobUidState = transientExtras != null 60 ? transientExtras.getBoolean(EXTRA_REQUEST_JOB_UID_STATE) : false; 61 if (requestJobUidState) { 62 reportJobStartIntent.putExtra(EXTRA_REQUEST_JOB_UID_STATE, true); 63 reportJobStartIntent.putExtras(getJobUidStateExtras()); 64 } 65 sendBroadcast(reportJobStartIntent); 66 if (transientExtras.getBoolean(EXTRA_SLOW_START)) { 67 try { 68 Thread.sleep(60_000); 69 } catch (InterruptedException e) { 70 Log.e(TAG, "Interrupted sleeping for slow start"); 71 } 72 } 73 if (transientExtras.getBoolean(EXTRA_SET_NOTIFICATION)) { 74 final NotificationManager notificationManager = 75 getSystemService(NotificationManager.class); 76 final NotificationChannel channel = 77 new NotificationChannel(TAG, TAG, NotificationManager.IMPORTANCE_DEFAULT); 78 notificationManager.createNotificationChannel(channel); 79 final Notification notification = new Notification.Builder(this, TAG) 80 .setContentTitle("Test") 81 .setSmallIcon(android.R.mipmap.sym_def_app_icon) 82 .setContentText(TAG) 83 .build(); 84 setNotification(params, params.getJobId(), notification, 85 transientExtras.getInt(EXTRA_SET_NOTIFICATION_JOB_END_POLICY, 86 JobService.JOB_END_NOTIFICATION_POLICY_REMOVE)); 87 } 88 return true; 89 } 90 91 @Override onStopJob(JobParameters params)92 public boolean onStopJob(JobParameters params) { 93 Log.i(TAG, "Test job stopped executing: " + params.getJobId()); 94 final Intent reportJobStopIntent = new Intent(ACTION_JOB_STOPPED); 95 reportJobStopIntent.putExtra(JOB_PARAMS_EXTRA_KEY, params); 96 sendBroadcast(reportJobStopIntent); 97 if (params.getTransientExtras().getBoolean(EXTRA_SLOW_STOP)) { 98 try { 99 Thread.sleep(60_000); 100 } catch (InterruptedException e) { 101 Log.e(TAG, "Interrupted sleeping for slow stop"); 102 } 103 } 104 return true; 105 } 106 getJobUidStateExtras()107 private Bundle getJobUidStateExtras() { 108 final Bundle extras = new Bundle(); 109 extras.putInt(JOB_PROC_STATE_KEY, getProcState()); 110 extras.putInt(JOB_CAPABILITIES_KEY, getCapabilities()); 111 extras.putInt(JOB_OOM_SCORE_ADJ_KEY, getOomScoreAdj()); 112 return extras; 113 } 114 getProcState()115 private int getProcState() { 116 final ActivityManager activityManager = getSystemService(ActivityManager.class); 117 return activityManager.getUidProcessState(Process.myUid()); 118 } 119 getCapabilities()120 private int getCapabilities() { 121 final ActivityManager activityManager = getSystemService(ActivityManager.class); 122 return activityManager.getUidProcessCapabilities(Process.myUid()); 123 } 124 getOomScoreAdj()125 private int getOomScoreAdj() { 126 try (BufferedReader reader = new BufferedReader( 127 new FileReader("/proc/self/oom_score_adj"))) { 128 return Integer.parseInt(reader.readLine().trim()); 129 } catch (IOException | NumberFormatException e) { 130 Log.e(TAG, "Error reading oom_score_adj", e); 131 return INVALID_ADJ; 132 } 133 } 134 } 135