package org.altbeacon.bluetooth; import android.app.job.JobParameters; import android.app.job.JobService; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageItemInfo; import android.content.pm.PackageManager; import android.os.Handler; import android.os.HandlerThread; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import org.altbeacon.beacon.logging.LogManager; /** * @hide * Internal library class. Do not use directly. */ @SuppressWarnings("javadoc") @RequiresApi(21) public class BluetoothTestJob extends JobService { private static final String TAG = BluetoothTestJob.class.getSimpleName(); @Nullable private Handler mHandler = null; @Nullable private HandlerThread mHandlerThread = null; private static int sOverrideJobId = -1; /** * Allows configuration of the job id for the Android Job Scheduler. If not configured, this * will default to he value in the AndroidManifest.xml * * WARNING: If using this library in a multi-process application, this method may not work. * This is considered a private API and may be removed at any time. * * the preferred way of setting this is in the AndroidManifest.xml as so: * <code> * <service android:name="org.altbeacon.bluetooth.BluetoothTestJob"> * <meta-data android:name="jobId" android:value="1001" tools:replace="android:value"/> * </service> * </code> * * @param id */ public static void setOverrideJobId(int id) { sOverrideJobId = id; } /** * Returns the job id to be used to schedule this job. This may be set in the * AndroidManifest.xml or in single process applications by using #setOverrideJobId * @param context * @return */ public static int getJobId(Context context) { if (sOverrideJobId >= 0) { LogManager.i(TAG, "Using BluetoothTestJob JobId from static override: "+ sOverrideJobId); return sOverrideJobId; } PackageItemInfo info = null; try { info = context.getPackageManager().getServiceInfo(new ComponentName(context, BluetoothTestJob.class), PackageManager.GET_META_DATA); } catch (PackageManager.NameNotFoundException e) { /* do nothing here */ } if (info != null && info.metaData != null && info.metaData.get("jobId") != null) { int jobId = info.metaData.getInt("jobId"); LogManager.i(TAG, "Using BluetoothTestJob JobId from manifest: "+jobId); return jobId; } else { throw new RuntimeException("Cannot get job id from manifest. " + "Make sure that the BluetoothTestJob is configured in the manifest."); } } public BluetoothTestJob() { } public boolean onStartJob(final JobParameters params) { if(this.mHandlerThread == null) { this.mHandlerThread = new HandlerThread("BluetoothTestThread"); this.mHandlerThread.start(); } if(this.mHandler == null) { this.mHandler = new Handler(this.mHandlerThread.getLooper()); } this.mHandler.post(new Runnable() { public void run() { boolean found = false; LogManager.i(BluetoothTestJob.TAG, "Bluetooth Test Job running"); int testType = params.getExtras().getInt("test_type"); if(testType == BluetoothMedic.NO_TEST) { found = true; LogManager.d(BluetoothTestJob.TAG, "No test specified. Done with job."); } if((testType & BluetoothMedic.SCAN_TEST) == BluetoothMedic.SCAN_TEST) { LogManager.d(BluetoothTestJob.TAG, "Scan test specified."); found = true; if (!BluetoothMedic.getInstance().runScanTest(BluetoothTestJob.this)) { LogManager.d(TAG, "scan test failed"); } } if((testType & BluetoothMedic.TRANSMIT_TEST) == BluetoothMedic.TRANSMIT_TEST) { if(found) { try { Thread.sleep(10000L); } catch (InterruptedException e) { /* do nothing */ } } LogManager.d(BluetoothTestJob.TAG, "Transmit test specified."); found = true; if (!BluetoothMedic.getInstance().runTransmitterTest(BluetoothTestJob.this)) { LogManager.d(TAG, "transmit test failed"); } } if(!found) { LogManager.w(BluetoothTestJob.TAG, "Unknown test type:" + testType + " Exiting."); } BluetoothTestJob.this.jobFinished(params, false); } }); return true; } public boolean onStopJob(JobParameters params) { return true; } }