Skip to content

Commit

Permalink
OboeTester: Create foreground service (#2071)
Browse files Browse the repository at this point in the history
  • Loading branch information
robertwu1 authored Jul 12, 2024
1 parent 4f3ed88 commit 3e468f5
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 4 deletions.
9 changes: 9 additions & 0 deletions apps/OboeTester/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />

<application
android:icon="@mipmap/ic_launcher"
Expand Down Expand Up @@ -140,6 +143,12 @@
android:resource="@xml/service_device_info" />
</service>

<service
android:name=".AudioForegroundService"
android:foregroundServiceType="mediaPlayback|microphone"
android:exported="false">
</service>

<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.mobileer.oboetester;

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ServiceInfo;
import android.os.Build;
import android.os.IBinder;
import android.util.Log;

public class AudioForegroundService extends Service {
private static final String TAG = "OboeTester";
public static final String ACTION_START = "ACTION_START";
public static final String ACTION_STOP = "ACTION_STOP";

@Override
public IBinder onBind(Intent intent) {
// We don't provide binding, so return null
return null;
}

private Notification buildNotification() {
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
manager.createNotificationChannel(new NotificationChannel(
"all",
"All Notifications",
NotificationManager.IMPORTANCE_NONE));

return new Notification.Builder(this, "all")
.setContentTitle("Playing/recording audio")
.setContentText("playing/recording...")
.setSmallIcon(R.drawable.ic_notification)
.build();
}
return null;
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i(TAG, "Receive onStartCommand" + intent);
switch (intent.getAction()) {
case ACTION_START:
Log.i(TAG, "Receive ACTION_START" + intent.getExtras());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
startForeground(1, buildNotification(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
| ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE);
}
break;
case ACTION_STOP:
Log.i(TAG, "Receive ACTION_STOP" + intent.getExtras());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
stopForeground(STOP_FOREGROUND_REMOVE);
}
break;
}
return START_NOT_STICKY;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public class IntentBasedTestSupport {
public static final String KEY_FILE_NAME = "file";
public static final String KEY_BUFFER_BURSTS = "buffer_bursts";
public static final String KEY_BACKGROUND = "background";
public static final String KEY_FOREGROUND_SERVICE = "foreground_service";
public static final String KEY_VOLUME = "volume";

public static final String KEY_VOLUME_TYPE = "volume_type";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public class MainActivity extends BaseOboeTesterActivity {
private Bundle mBundleFromIntent;
private CheckBox mWorkaroundsCheckBox;
private CheckBox mBackgroundCheckBox;
private CheckBox mForegroundServiceCheckBox;
private static String mVersionText;

@Override
Expand Down Expand Up @@ -111,6 +112,7 @@ public void onNothingSelected(AdapterView<?> adapterView) {
NativeEngine.setWorkaroundsEnabled(false);

mBackgroundCheckBox = (CheckBox) findViewById(R.id.boxEnableBackground);
mForegroundServiceCheckBox = (CheckBox) findViewById(R.id.boxEnableForegroundService);

mBuildTextView = (TextView) findViewById(R.id.text_build_info);
mBuildTextView.setText(Build.DISPLAY
Expand Down Expand Up @@ -149,16 +151,19 @@ private void processBundleFromIntent() {
}
Intent intent = getTestIntent(mBundleFromIntent);
if (intent != null) {
setBackgroundFromIntent();
setTogglesFromIntent();
startActivity(intent);
}
mBundleFromIntent = null;
}

private void setBackgroundFromIntent() {
private void setTogglesFromIntent() {
boolean backgroundEnabled = mBundleFromIntent.getBoolean(
IntentBasedTestSupport.KEY_BACKGROUND, false);
TestAudioActivity.setBackgroundEnabled(backgroundEnabled);
boolean foregroundServiceEnabled = mBundleFromIntent.getBoolean(
IntentBasedTestSupport.KEY_FOREGROUND_SERVICE, false);
TestAudioActivity.setBackgroundEnabled(foregroundServiceEnabled);
}

private Intent getTestIntent(Bundle bundle) {
Expand Down Expand Up @@ -255,6 +260,7 @@ private void applyUserOptions() {

NativeEngine.setWorkaroundsEnabled(mWorkaroundsCheckBox.isChecked());
TestAudioActivity.setBackgroundEnabled(mBackgroundCheckBox.isChecked());
TestAudioActivity.setForegroundServiceEnabled(mForegroundServiceCheckBox.isChecked());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

package com.mobileer.oboetester;

import static com.mobileer.oboetester.AudioForegroundService.ACTION_START;
import static com.mobileer.oboetester.AudioForegroundService.ACTION_STOP;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
Expand Down Expand Up @@ -97,6 +100,7 @@ abstract class TestAudioActivity extends AppCompatActivity {
private int mSampleRate;
private int mSingleTestIndex = -1;
private static boolean mBackgroundEnabled;
private static boolean mForegroundServiceEnabled;

protected Bundle mBundleFromIntent;
protected boolean mTestRunningByIntent;
Expand Down Expand Up @@ -183,6 +187,14 @@ public static boolean isBackgroundEnabled() {
return mBackgroundEnabled;
}

public static void setForegroundServiceEnabled(boolean enabled) {
mForegroundServiceEnabled = enabled;
}

public static boolean isForegroundServiceEnabled() {
return mForegroundServiceEnabled;
}

public void onStreamClosed() {
}

Expand Down Expand Up @@ -237,6 +249,9 @@ protected void onStart() {
if (mCommunicationDeviceView != null) {
mCommunicationDeviceView.onStart();
}
if (isForegroundServiceEnabled()) {
enableForegroundService(true);
}
}

protected void resetConfiguration() {
Expand Down Expand Up @@ -300,6 +315,9 @@ protected void onStop() {
if (!isBackgroundEnabled()) {
Log.i(TAG, "onStop() called so stop the test =========================");
onStopTest();
if (isForegroundServiceEnabled()) {
enableForegroundService(false);
}
}
if (mCommunicationDeviceView != null) {
mCommunicationDeviceView.onStop();
Expand All @@ -312,11 +330,23 @@ protected void onDestroy() {
if (isBackgroundEnabled()) {
Log.i(TAG, "onDestroy() called so stop the test =========================");
onStopTest();
if (isForegroundServiceEnabled()) {
enableForegroundService(false);
}
}
mAudioState = AUDIO_STATE_CLOSED;
super.onDestroy();
}

public void enableForegroundService(boolean enabled) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
String action = enabled ? ACTION_START : ACTION_STOP;
Intent serviceIntent = new Intent(action, null, this,
AudioForegroundService.class);
startForegroundService(serviceIntent);
}
}

protected void updateEnabledWidgets() {
if (mOpenButton != null) {
mOpenButton.setBackgroundColor(mAudioState == AUDIO_STATE_OPEN ? COLOR_ACTIVE : COLOR_IDLE);
Expand Down
83 changes: 83 additions & 0 deletions apps/OboeTester/app/src/main/res/drawable/ic_notification.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z"/>
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>

<group android:scaleX="2.61"
android:scaleY="2.61"
android:translateX="22.68"
android:translateY="22.68"
android:tint="#0D49B0">
<path
android:fillColor="#0D49B0"
android:pathData="M17,16.99c-1.35,0 -2.2,0.42 -2.95,0.8 -0.65,0.33 -1.18,0.6 -2.05,0.6 -0.9,0 -1.4,-0.25 -2.05,-0.6 -0.75,-0.38 -1.57,-0.8 -2.95,-0.8s-2.2,0.42 -2.95,0.8c-0.65,0.33 -1.17,0.6 -2.05,0.6v1.95c1.35,0 2.2,-0.42 2.95,-0.8 0.65,-0.33 1.17,-0.6 2.05,-0.6s1.4,0.25 2.05,0.6c0.75,0.38 1.57,0.8 2.95,0.8s2.2,-0.42 2.95,-0.8c0.65,-0.33 1.18,-0.6 2.05,-0.6 0.9,0 1.4,0.25 2.05,0.6 0.75,0.38 1.58,0.8 2.95,0.8v-1.95c-0.9,0 -1.4,-0.25 -2.05,-0.6 -0.75,-0.38 -1.6,-0.8 -2.95,-0.8zM17,12.54c-1.35,0 -2.2,0.43 -2.95,0.8 -0.65,0.32 -1.18,0.6 -2.05,0.6 -0.9,0 -1.4,-0.25 -2.05,-0.6 -0.75,-0.38 -1.57,-0.8 -2.95,-0.8s-2.2,0.43 -2.95,0.8c-0.65,0.32 -1.17,0.6 -2.05,0.6v1.95c1.35,0 2.2,-0.43 2.95,-0.8 0.65,-0.35 1.15,-0.6 2.05,-0.6s1.4,0.25 2.05,0.6c0.75,0.38 1.57,0.8 2.95,0.8s2.2,-0.43 2.95,-0.8c0.65,-0.35 1.15,-0.6 2.05,-0.6s1.4,0.25 2.05,0.6c0.75,0.38 1.58,0.8 2.95,0.8v-1.95c-0.9,0 -1.4,-0.25 -2.05,-0.6 -0.75,-0.38 -1.6,-0.8 -2.95,-0.8zM19.95,4.46c-0.75,-0.38 -1.58,-0.8 -2.95,-0.8s-2.2,0.42 -2.95,0.8c-0.65,0.32 -1.18,0.6 -2.05,0.6 -0.9,0 -1.4,-0.25 -2.05,-0.6 -0.75,-0.37 -1.57,-0.8 -2.95,-0.8s-2.2,0.42 -2.95,0.8c-0.65,0.33 -1.17,0.6 -2.05,0.6v1.93c1.35,0 2.2,-0.43 2.95,-0.8 0.65,-0.33 1.17,-0.6 2.05,-0.6s1.4,0.25 2.05,0.6c0.75,0.38 1.57,0.8 2.95,0.8s2.2,-0.43 2.95,-0.8c0.65,-0.32 1.18,-0.6 2.05,-0.6 0.9,0 1.4,0.25 2.05,0.6 0.75,0.38 1.58,0.8 2.95,0.8L22,5.04c-0.9,0 -1.4,-0.25 -2.05,-0.58zM17,8.09c-1.35,0 -2.2,0.43 -2.95,0.8 -0.65,0.35 -1.15,0.6 -2.05,0.6s-1.4,-0.25 -2.05,-0.6c-0.75,-0.38 -1.57,-0.8 -2.95,-0.8s-2.2,0.43 -2.95,0.8c-0.65,0.35 -1.15,0.6 -2.05,0.6v1.95c1.35,0 2.2,-0.43 2.95,-0.8 0.65,-0.32 1.18,-0.6 2.05,-0.6s1.4,0.25 2.05,0.6c0.75,0.38 1.57,0.8 2.95,0.8s2.2,-0.43 2.95,-0.8c0.65,-0.32 1.18,-0.6 2.05,-0.6 0.9,0 1.4,0.25 2.05,0.6 0.75,0.38 1.58,0.8 2.95,0.8L22,9.49c-0.9,0 -1.4,-0.25 -2.05,-0.6 -0.75,-0.38 -1.6,-0.8 -2.95,-0.8z"/>
</group>

</vector>
14 changes: 12 additions & 2 deletions apps/OboeTester/app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,23 @@
app:layout_constraintTop_toBottomOf="@+id/boxEnableWorkarounds" />


<CheckBox
android:id="@+id/boxEnableForegroundService"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:checked="false"
android:text="enable foreground service"
app:layout_constraintStart_toStartOf="@+id/boxEnableBackground"
app:layout_constraintTop_toBottomOf="@+id/boxEnableBackground" />

<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Mode:"
app:layout_constraintBaseline_toBaselineOf="@+id/spinnerAudioMode"
app:layout_constraintStart_toStartOf="@+id/boxEnableBackground" />
app:layout_constraintStart_toStartOf="@+id/boxEnableForegroundService" />

<Spinner
android:id="@+id/spinnerAudioMode"
Expand All @@ -218,7 +228,7 @@
android:entries="@array/audio_modes"
android:prompt="@string/audio_mode_prompt"
app:layout_constraintStart_toEndOf="@+id/textView2"
app:layout_constraintTop_toBottomOf="@+id/boxEnableBackground" />
app:layout_constraintTop_toBottomOf="@+id/boxEnableForegroundService" />

<TextView
android:id="@+id/deviceView"
Expand Down

0 comments on commit 3e468f5

Please sign in to comment.