Loading services/core/java/com/android/server/am/ActiveServices.java +5 −7 Original line number Diff line number Diff line Loading @@ -1841,7 +1841,7 @@ public final class ActiveServices { ServiceState stracker = r.getTracker(); if (stracker != null) { stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); SystemClock.uptimeMillis()); } } if (alreadyStartedOp) { Loading @@ -1863,7 +1863,7 @@ public final class ActiveServices { ServiceState stracker = r.getTracker(); if (stracker != null) { stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); SystemClock.uptimeMillis()); } mAm.mAppOpsService.finishOperation( AppOpsManager.getToken(mAm.mAppOpsService), Loading Loading @@ -3765,6 +3765,7 @@ public final class ActiveServices { } } final long now = SystemClock.uptimeMillis(); // Check to see if the service had been started as foreground, but being // brought down before actually showing a notification. That is not allowed. if (r.fgRequired) { Loading @@ -3774,8 +3775,7 @@ public final class ActiveServices { r.fgWaiting = false; ServiceState stracker = r.getTracker(); if (stracker != null) { stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), now); } mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService), AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null); Loading Loading @@ -3834,8 +3834,7 @@ public final class ActiveServices { decActiveForegroundAppLocked(smap, r); ServiceState stracker = r.getTracker(); if (stracker != null) { stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), now); } mAm.mAppOpsService.finishOperation( AppOpsManager.getToken(mAm.mAppOpsService), Loading Loading @@ -3902,7 +3901,6 @@ public final class ActiveServices { } int memFactor = mAm.mProcessStats.getMemFactorLocked(); long now = SystemClock.uptimeMillis(); if (r.tracker != null) { r.tracker.setStarted(false, memFactor, now); r.tracker.setBound(false, memFactor, now); Loading services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java +200 −0 Original line number Diff line number Diff line Loading @@ -19,23 +19,37 @@ package com.android.server.am; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.app.ActivityManager; import android.app.ActivityManager.OnUidImportanceListener; import android.app.ActivityManager.RecentTaskInfo; import android.app.ActivityManager.RunningAppProcessInfo; import android.app.IActivityManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.DropBoxManager; import android.os.Handler; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.support.test.uiautomator.UiDevice; import android.test.suitebuilder.annotation.LargeTest; import android.text.TextUtils; import android.util.Log; import androidx.test.InstrumentationRegistry; import androidx.test.filters.FlakyTest; Loading Loading @@ -65,6 +79,12 @@ public class ActivityManagerTest { private static final long AWAIT_TIMEOUT = 2000; private static final long CHECK_INTERVAL = 100; private static final String TEST_FGS_CLASS = "com.android.servicestests.apps.simpleservicetestapp.SimpleFgService"; private static final String ACTION_FGS_STATS_TEST = "com.android.servicestests.apps.simpleservicetestapp.ACTION_FGS_STATS_TEST"; private static final String EXTRA_MESSENGER = "extra_messenger"; private IActivityManager mService; private IRemoteCallback mCallback; private Context mContext; Loading Loading @@ -204,4 +224,184 @@ public class ActivityManagerTest { public void onServiceDisconnected(ComponentName name) { } } /** * Note: This test actually only works in eng build. It'll always pass * in user and userdebug build, because the expected exception won't be * thrown in those builds. */ @LargeTest @Test public void testFgsProcStatsTracker() throws Exception { final PackageManager pm = mContext.getPackageManager(); final long timeout = 5000; int uid = pm.getPackageUid(TEST_APP, 0); final MyUidImportanceListener uidListener1 = new MyUidImportanceListener(uid); final MyUidImportanceListener uidListener2 = new MyUidImportanceListener(uid); final ActivityManager am = mContext.getSystemService(ActivityManager.class); final CountDownLatch[] latchHolder = new CountDownLatch[1]; final H handler = new H(Looper.getMainLooper(), latchHolder); final Messenger messenger = new Messenger(handler); final DropBoxManager dbox = mContext.getSystemService(DropBoxManager.class); final CountDownLatch dboxLatch = new CountDownLatch(1); final BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String tag_wtf = "system_server_wtf"; if (tag_wtf.equals(intent.getStringExtra(DropBoxManager.EXTRA_TAG))) { final DropBoxManager.Entry e = dbox.getNextEntry(tag_wtf, intent.getLongExtra( DropBoxManager.EXTRA_TIME, 0) - 1); final String text = e.getText(8192); if (TextUtils.isEmpty(text)) { return; } if (text.indexOf("can't store negative values") == -1) { return; } dboxLatch.countDown(); } } }; try { mContext.registerReceiver(receiver, new IntentFilter(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED)); am.addOnUidImportanceListener(uidListener1, RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE); am.addOnUidImportanceListener(uidListener2, RunningAppProcessInfo.IMPORTANCE_GONE); runShellCommand("cmd deviceidle whitelist +" + TEST_APP); toggleScreenOn(true); final Intent intent = new Intent(ACTION_FGS_STATS_TEST); final ComponentName cn = ComponentName.unflattenFromString( TEST_APP + "/" + TEST_FGS_CLASS); final Bundle bundle = new Bundle(); intent.setComponent(cn); bundle.putBinder(EXTRA_MESSENGER, messenger.getBinder()); intent.putExtras(bundle); latchHolder[0] = new CountDownLatch(1); mContext.startForegroundService(intent); assertTrue("Timed out to start fg service", uidListener1.waitFor( RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, timeout)); assertTrue("Timed out to get the remote messenger", latchHolder[0].await( timeout, TimeUnit.MILLISECONDS)); Thread.sleep(timeout); latchHolder[0] = new CountDownLatch(1); handler.sendRemoteMessage(H.MSG_STOP_FOREGROUND, 0, 0, null); assertTrue("Timed out to wait for stop fg", latchHolder[0].await( timeout, TimeUnit.MILLISECONDS)); Thread.sleep(timeout); latchHolder[0] = new CountDownLatch(1); handler.sendRemoteMessage(H.MSG_START_FOREGROUND, 0, 0, null); assertTrue("Timed out to wait for start fg", latchHolder[0].await( timeout, TimeUnit.MILLISECONDS)); toggleScreenOn(false); latchHolder[0] = new CountDownLatch(1); handler.sendRemoteMessage(H.MSG_STOP_FOREGROUND, 0, 0, null); assertTrue("Timed out to wait for stop fg", latchHolder[0].await( timeout, TimeUnit.MILLISECONDS)); assertFalse("There shouldn't be negative values", dboxLatch.await( timeout * 2, TimeUnit.MILLISECONDS)); } finally { toggleScreenOn(true); runShellCommand("cmd deviceidle whitelist -" + TEST_APP); am.removeOnUidImportanceListener(uidListener1); am.removeOnUidImportanceListener(uidListener2); am.forceStopPackage(TEST_APP); mContext.unregisterReceiver(receiver); } } /** * Make sure the screen state. */ private void toggleScreenOn(final boolean screenon) throws Exception { if (screenon) { runShellCommand("input keyevent KEYCODE_WAKEUP"); runShellCommand("wm dismiss-keyguard"); } else { runShellCommand("input keyevent KEYCODE_SLEEP"); } // Since the screen on/off intent is ordered, they will not be sent right now. Thread.sleep(2_000); } private class H extends Handler { static final int MSG_INIT = 0; static final int MSG_DONE = 1; static final int MSG_START_FOREGROUND = 2; static final int MSG_STOP_FOREGROUND = 3; private Messenger mRemoteMessenger; private CountDownLatch[] mLatchHolder; H(Looper looper, CountDownLatch[] latchHolder) { super(looper); mLatchHolder = latchHolder; } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_INIT: mRemoteMessenger = (Messenger) msg.obj; mLatchHolder[0].countDown(); break; case MSG_DONE: mLatchHolder[0].countDown(); break; } } void sendRemoteMessage(int what, int arg1, int arg2, Object obj) { Message msg = Message.obtain(); msg.what = what; msg.arg1 = arg1; msg.arg2 = arg2; msg.obj = obj; try { mRemoteMessenger.send(msg); } catch (RemoteException e) { } msg.recycle(); } } private static class MyUidImportanceListener implements OnUidImportanceListener { final CountDownLatch[] mLatchHolder = new CountDownLatch[1]; private final int mExpectedUid; private int mExpectedImportance; private int mCurrentImportance = RunningAppProcessInfo.IMPORTANCE_GONE; MyUidImportanceListener(int uid) { mExpectedUid = uid; } @Override public void onUidImportance(int uid, int importance) { if (uid == mExpectedUid) { synchronized (this) { if (importance == mExpectedImportance && mLatchHolder[0] != null) { mLatchHolder[0].countDown(); } mCurrentImportance = importance; } Log.i(TAG, "uid " + uid + " importance: " + importance); } } boolean waitFor(int expectedImportance, long timeout) throws Exception { synchronized (this) { mExpectedImportance = expectedImportance; if (mCurrentImportance == expectedImportance) { return true; } mLatchHolder[0] = new CountDownLatch(1); } return mLatchHolder[0].await(timeout, TimeUnit.MILLISECONDS); } } } services/tests/servicestests/test-apps/SimpleServiceTestApp/AndroidManifest.xml +4 −0 Original line number Diff line number Diff line Loading @@ -17,9 +17,13 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.servicestests.apps.simpleservicetestapp"> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <application> <service android:name=".SimpleService" android:exported="true" /> <service android:name=".SimpleFgService" android:exported="true" /> </application> </manifest> services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleFgService.java 0 → 100644 +113 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.android.servicestests.apps.simpleservicetestapp; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; import com.android.internal.R; public class SimpleFgService extends Service { private static final String TAG = SimpleFgService.class.getSimpleName(); private static final String NOTIFICATION_CHANNEL_ID = TAG; private static final int NOTIFICATION_ID = 1; private static final int MSG_INIT = 0; private static final int MSG_DONE = 1; private static final int MSG_START_FOREGROUND = 2; private static final int MSG_STOP_FOREGROUND = 3; private static final String ACTION_FGS_STATS_TEST = "com.android.servicestests.apps.simpleservicetestapp.ACTION_FGS_STATS_TEST"; private static final String EXTRA_MESSENGER = "extra_messenger"; private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_START_FOREGROUND: { Log.i(TAG, "startForeground"); startForeground(NOTIFICATION_ID, mNotification); sendRemoteMessage(MSG_DONE, 0, 0, null); } break; case MSG_STOP_FOREGROUND: { Log.i(TAG, "stopForeground"); stopForeground(true); sendRemoteMessage(MSG_DONE, 0, 0, null); } break; } } }; private final Messenger mMessenger = new Messenger(mHandler); private Notification mNotification; private Messenger mRemoteMessenger; @Override public void onCreate() { Log.i(TAG, "onCreate"); final NotificationManager nm = getSystemService(NotificationManager.class); nm.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)); mNotification = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID) .setContentTitle(TAG) .setSmallIcon(R.drawable.ic_info) .build(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand"); startForeground(NOTIFICATION_ID, mNotification); if (ACTION_FGS_STATS_TEST.equals(intent.getAction())) { mRemoteMessenger = new Messenger(intent.getExtras().getBinder(EXTRA_MESSENGER)); sendRemoteMessage(MSG_INIT, 0, 0, mMessenger); } return START_NOT_STICKY; } private void sendRemoteMessage(int what, int arg1, int arg2, Object obj) { final Message msg = Message.obtain(); msg.what = what; msg.arg1 = arg1; msg.arg2 = arg2; msg.obj = obj; try { mRemoteMessenger.send(msg); } catch (RemoteException e) { } } @Override public void onDestroy() { Log.i(TAG, "onDestroy"); mNotification = null; } @Override public IBinder onBind(Intent intent) { return null; } } Loading
services/core/java/com/android/server/am/ActiveServices.java +5 −7 Original line number Diff line number Diff line Loading @@ -1841,7 +1841,7 @@ public final class ActiveServices { ServiceState stracker = r.getTracker(); if (stracker != null) { stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); SystemClock.uptimeMillis()); } } if (alreadyStartedOp) { Loading @@ -1863,7 +1863,7 @@ public final class ActiveServices { ServiceState stracker = r.getTracker(); if (stracker != null) { stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); SystemClock.uptimeMillis()); } mAm.mAppOpsService.finishOperation( AppOpsManager.getToken(mAm.mAppOpsService), Loading Loading @@ -3765,6 +3765,7 @@ public final class ActiveServices { } } final long now = SystemClock.uptimeMillis(); // Check to see if the service had been started as foreground, but being // brought down before actually showing a notification. That is not allowed. if (r.fgRequired) { Loading @@ -3774,8 +3775,7 @@ public final class ActiveServices { r.fgWaiting = false; ServiceState stracker = r.getTracker(); if (stracker != null) { stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), now); } mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService), AppOpsManager.OP_START_FOREGROUND, r.appInfo.uid, r.packageName, null); Loading Loading @@ -3834,8 +3834,7 @@ public final class ActiveServices { decActiveForegroundAppLocked(smap, r); ServiceState stracker = r.getTracker(); if (stracker != null) { stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity); stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), now); } mAm.mAppOpsService.finishOperation( AppOpsManager.getToken(mAm.mAppOpsService), Loading Loading @@ -3902,7 +3901,6 @@ public final class ActiveServices { } int memFactor = mAm.mProcessStats.getMemFactorLocked(); long now = SystemClock.uptimeMillis(); if (r.tracker != null) { r.tracker.setStarted(false, memFactor, now); r.tracker.setBound(false, memFactor, now); Loading
services/tests/servicestests/src/com/android/server/am/ActivityManagerTest.java +200 −0 Original line number Diff line number Diff line Loading @@ -19,23 +19,37 @@ package com.android.server.am; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import android.app.ActivityManager; import android.app.ActivityManager.OnUidImportanceListener; import android.app.ActivityManager.RecentTaskInfo; import android.app.ActivityManager.RunningAppProcessInfo; import android.app.IActivityManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.os.Bundle; import android.os.DropBoxManager; import android.os.Handler; import android.os.IBinder; import android.os.IRemoteCallback; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; import android.support.test.uiautomator.UiDevice; import android.test.suitebuilder.annotation.LargeTest; import android.text.TextUtils; import android.util.Log; import androidx.test.InstrumentationRegistry; import androidx.test.filters.FlakyTest; Loading Loading @@ -65,6 +79,12 @@ public class ActivityManagerTest { private static final long AWAIT_TIMEOUT = 2000; private static final long CHECK_INTERVAL = 100; private static final String TEST_FGS_CLASS = "com.android.servicestests.apps.simpleservicetestapp.SimpleFgService"; private static final String ACTION_FGS_STATS_TEST = "com.android.servicestests.apps.simpleservicetestapp.ACTION_FGS_STATS_TEST"; private static final String EXTRA_MESSENGER = "extra_messenger"; private IActivityManager mService; private IRemoteCallback mCallback; private Context mContext; Loading Loading @@ -204,4 +224,184 @@ public class ActivityManagerTest { public void onServiceDisconnected(ComponentName name) { } } /** * Note: This test actually only works in eng build. It'll always pass * in user and userdebug build, because the expected exception won't be * thrown in those builds. */ @LargeTest @Test public void testFgsProcStatsTracker() throws Exception { final PackageManager pm = mContext.getPackageManager(); final long timeout = 5000; int uid = pm.getPackageUid(TEST_APP, 0); final MyUidImportanceListener uidListener1 = new MyUidImportanceListener(uid); final MyUidImportanceListener uidListener2 = new MyUidImportanceListener(uid); final ActivityManager am = mContext.getSystemService(ActivityManager.class); final CountDownLatch[] latchHolder = new CountDownLatch[1]; final H handler = new H(Looper.getMainLooper(), latchHolder); final Messenger messenger = new Messenger(handler); final DropBoxManager dbox = mContext.getSystemService(DropBoxManager.class); final CountDownLatch dboxLatch = new CountDownLatch(1); final BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String tag_wtf = "system_server_wtf"; if (tag_wtf.equals(intent.getStringExtra(DropBoxManager.EXTRA_TAG))) { final DropBoxManager.Entry e = dbox.getNextEntry(tag_wtf, intent.getLongExtra( DropBoxManager.EXTRA_TIME, 0) - 1); final String text = e.getText(8192); if (TextUtils.isEmpty(text)) { return; } if (text.indexOf("can't store negative values") == -1) { return; } dboxLatch.countDown(); } } }; try { mContext.registerReceiver(receiver, new IntentFilter(DropBoxManager.ACTION_DROPBOX_ENTRY_ADDED)); am.addOnUidImportanceListener(uidListener1, RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE); am.addOnUidImportanceListener(uidListener2, RunningAppProcessInfo.IMPORTANCE_GONE); runShellCommand("cmd deviceidle whitelist +" + TEST_APP); toggleScreenOn(true); final Intent intent = new Intent(ACTION_FGS_STATS_TEST); final ComponentName cn = ComponentName.unflattenFromString( TEST_APP + "/" + TEST_FGS_CLASS); final Bundle bundle = new Bundle(); intent.setComponent(cn); bundle.putBinder(EXTRA_MESSENGER, messenger.getBinder()); intent.putExtras(bundle); latchHolder[0] = new CountDownLatch(1); mContext.startForegroundService(intent); assertTrue("Timed out to start fg service", uidListener1.waitFor( RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE, timeout)); assertTrue("Timed out to get the remote messenger", latchHolder[0].await( timeout, TimeUnit.MILLISECONDS)); Thread.sleep(timeout); latchHolder[0] = new CountDownLatch(1); handler.sendRemoteMessage(H.MSG_STOP_FOREGROUND, 0, 0, null); assertTrue("Timed out to wait for stop fg", latchHolder[0].await( timeout, TimeUnit.MILLISECONDS)); Thread.sleep(timeout); latchHolder[0] = new CountDownLatch(1); handler.sendRemoteMessage(H.MSG_START_FOREGROUND, 0, 0, null); assertTrue("Timed out to wait for start fg", latchHolder[0].await( timeout, TimeUnit.MILLISECONDS)); toggleScreenOn(false); latchHolder[0] = new CountDownLatch(1); handler.sendRemoteMessage(H.MSG_STOP_FOREGROUND, 0, 0, null); assertTrue("Timed out to wait for stop fg", latchHolder[0].await( timeout, TimeUnit.MILLISECONDS)); assertFalse("There shouldn't be negative values", dboxLatch.await( timeout * 2, TimeUnit.MILLISECONDS)); } finally { toggleScreenOn(true); runShellCommand("cmd deviceidle whitelist -" + TEST_APP); am.removeOnUidImportanceListener(uidListener1); am.removeOnUidImportanceListener(uidListener2); am.forceStopPackage(TEST_APP); mContext.unregisterReceiver(receiver); } } /** * Make sure the screen state. */ private void toggleScreenOn(final boolean screenon) throws Exception { if (screenon) { runShellCommand("input keyevent KEYCODE_WAKEUP"); runShellCommand("wm dismiss-keyguard"); } else { runShellCommand("input keyevent KEYCODE_SLEEP"); } // Since the screen on/off intent is ordered, they will not be sent right now. Thread.sleep(2_000); } private class H extends Handler { static final int MSG_INIT = 0; static final int MSG_DONE = 1; static final int MSG_START_FOREGROUND = 2; static final int MSG_STOP_FOREGROUND = 3; private Messenger mRemoteMessenger; private CountDownLatch[] mLatchHolder; H(Looper looper, CountDownLatch[] latchHolder) { super(looper); mLatchHolder = latchHolder; } @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_INIT: mRemoteMessenger = (Messenger) msg.obj; mLatchHolder[0].countDown(); break; case MSG_DONE: mLatchHolder[0].countDown(); break; } } void sendRemoteMessage(int what, int arg1, int arg2, Object obj) { Message msg = Message.obtain(); msg.what = what; msg.arg1 = arg1; msg.arg2 = arg2; msg.obj = obj; try { mRemoteMessenger.send(msg); } catch (RemoteException e) { } msg.recycle(); } } private static class MyUidImportanceListener implements OnUidImportanceListener { final CountDownLatch[] mLatchHolder = new CountDownLatch[1]; private final int mExpectedUid; private int mExpectedImportance; private int mCurrentImportance = RunningAppProcessInfo.IMPORTANCE_GONE; MyUidImportanceListener(int uid) { mExpectedUid = uid; } @Override public void onUidImportance(int uid, int importance) { if (uid == mExpectedUid) { synchronized (this) { if (importance == mExpectedImportance && mLatchHolder[0] != null) { mLatchHolder[0].countDown(); } mCurrentImportance = importance; } Log.i(TAG, "uid " + uid + " importance: " + importance); } } boolean waitFor(int expectedImportance, long timeout) throws Exception { synchronized (this) { mExpectedImportance = expectedImportance; if (mCurrentImportance == expectedImportance) { return true; } mLatchHolder[0] = new CountDownLatch(1); } return mLatchHolder[0].await(timeout, TimeUnit.MILLISECONDS); } } }
services/tests/servicestests/test-apps/SimpleServiceTestApp/AndroidManifest.xml +4 −0 Original line number Diff line number Diff line Loading @@ -17,9 +17,13 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.servicestests.apps.simpleservicetestapp"> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <application> <service android:name=".SimpleService" android:exported="true" /> <service android:name=".SimpleFgService" android:exported="true" /> </application> </manifest>
services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleFgService.java 0 → 100644 +113 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.android.servicestests.apps.simpleservicetestapp; import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.Messenger; import android.os.RemoteException; import android.util.Log; import com.android.internal.R; public class SimpleFgService extends Service { private static final String TAG = SimpleFgService.class.getSimpleName(); private static final String NOTIFICATION_CHANNEL_ID = TAG; private static final int NOTIFICATION_ID = 1; private static final int MSG_INIT = 0; private static final int MSG_DONE = 1; private static final int MSG_START_FOREGROUND = 2; private static final int MSG_STOP_FOREGROUND = 3; private static final String ACTION_FGS_STATS_TEST = "com.android.servicestests.apps.simpleservicetestapp.ACTION_FGS_STATS_TEST"; private static final String EXTRA_MESSENGER = "extra_messenger"; private final Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_START_FOREGROUND: { Log.i(TAG, "startForeground"); startForeground(NOTIFICATION_ID, mNotification); sendRemoteMessage(MSG_DONE, 0, 0, null); } break; case MSG_STOP_FOREGROUND: { Log.i(TAG, "stopForeground"); stopForeground(true); sendRemoteMessage(MSG_DONE, 0, 0, null); } break; } } }; private final Messenger mMessenger = new Messenger(mHandler); private Notification mNotification; private Messenger mRemoteMessenger; @Override public void onCreate() { Log.i(TAG, "onCreate"); final NotificationManager nm = getSystemService(NotificationManager.class); nm.createNotificationChannel(new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_LOW)); mNotification = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID) .setContentTitle(TAG) .setSmallIcon(R.drawable.ic_info) .build(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i(TAG, "onStartCommand"); startForeground(NOTIFICATION_ID, mNotification); if (ACTION_FGS_STATS_TEST.equals(intent.getAction())) { mRemoteMessenger = new Messenger(intent.getExtras().getBinder(EXTRA_MESSENGER)); sendRemoteMessage(MSG_INIT, 0, 0, mMessenger); } return START_NOT_STICKY; } private void sendRemoteMessage(int what, int arg1, int arg2, Object obj) { final Message msg = Message.obtain(); msg.what = what; msg.arg1 = arg1; msg.arg2 = arg2; msg.obj = obj; try { mRemoteMessenger.send(msg); } catch (RemoteException e) { } } @Override public void onDestroy() { Log.i(TAG, "onDestroy"); mNotification = null; } @Override public IBinder onBind(Intent intent) { return null; } }