Merge "Skip resetting the shouldNotFreeze flag while re-evaluating oom adj" into sc-dev am: 98b57c304d
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15141325 Change-Id: Ib29575fc8f4eb5098a078ebc5cf428ecbc34de70
This commit is contained in:
@@ -212,6 +212,23 @@ public final class CachedAppOptimizer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private final OnPropertiesChangedListener mOnNativeBootFlagsChangedListener =
|
||||||
|
new OnPropertiesChangedListener() {
|
||||||
|
@Override
|
||||||
|
public void onPropertiesChanged(Properties properties) {
|
||||||
|
synchronized (mPhenotypeFlagLock) {
|
||||||
|
for (String name : properties.getKeyset()) {
|
||||||
|
if (KEY_FREEZER_DEBOUNCE_TIMEOUT.equals(name)) {
|
||||||
|
updateFreezerDebounceTimeout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mTestCallback != null) {
|
||||||
|
mTestCallback.onPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private final class SettingsContentObserver extends ContentObserver {
|
private final class SettingsContentObserver extends ContentObserver {
|
||||||
SettingsContentObserver() {
|
SettingsContentObserver() {
|
||||||
super(mAm.mHandler);
|
super(mAm.mHandler);
|
||||||
@@ -328,6 +345,10 @@ public final class CachedAppOptimizer {
|
|||||||
// TODO: initialize flags to default and only update them if values are set in DeviceConfig
|
// TODO: initialize flags to default and only update them if values are set in DeviceConfig
|
||||||
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
||||||
ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener);
|
ActivityThread.currentApplication().getMainExecutor(), mOnFlagsChangedListener);
|
||||||
|
DeviceConfig.addOnPropertiesChangedListener(
|
||||||
|
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
|
||||||
|
ActivityThread.currentApplication().getMainExecutor(),
|
||||||
|
mOnNativeBootFlagsChangedListener);
|
||||||
mAm.mContext.getContentResolver().registerContentObserver(
|
mAm.mContext.getContentResolver().registerContentObserver(
|
||||||
CACHED_APP_FREEZER_ENABLED_URI, false, mSettingsObserver);
|
CACHED_APP_FREEZER_ENABLED_URI, false, mSettingsObserver);
|
||||||
synchronized (mPhenotypeFlagLock) {
|
synchronized (mPhenotypeFlagLock) {
|
||||||
|
|||||||
@@ -1530,9 +1530,11 @@ public class OomAdjuster {
|
|||||||
state.setAdjTarget(null);
|
state.setAdjTarget(null);
|
||||||
state.setEmpty(false);
|
state.setEmpty(false);
|
||||||
state.setCached(false);
|
state.setCached(false);
|
||||||
state.setNoKillOnForcedAppStandbyAndIdle(false);
|
|
||||||
state.resetAllowStartFgsState();
|
state.resetAllowStartFgsState();
|
||||||
app.mOptRecord.setShouldNotFreeze(false);
|
if (!cycleReEval) {
|
||||||
|
// Don't reset this flag when doing cycles re-evaluation.
|
||||||
|
app.mOptRecord.setShouldNotFreeze(false);
|
||||||
|
}
|
||||||
|
|
||||||
final int appUid = app.info.uid;
|
final int appUid = app.info.uid;
|
||||||
final int logUid = mService.mCurOomAdjUid;
|
final int logUid = mService.mCurOomAdjUid;
|
||||||
@@ -1983,6 +1985,11 @@ public class OomAdjuster {
|
|||||||
|
|
||||||
final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;
|
final boolean clientIsSystem = clientProcState < PROCESS_STATE_TOP;
|
||||||
|
|
||||||
|
if (client.mOptRecord.shouldNotFreeze()) {
|
||||||
|
// Propagate the shouldNotFreeze flag down the bindings.
|
||||||
|
app.mOptRecord.setShouldNotFreeze(true);
|
||||||
|
}
|
||||||
|
|
||||||
if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
|
if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
|
||||||
if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
|
if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
|
||||||
continue;
|
continue;
|
||||||
@@ -2019,9 +2026,6 @@ public class OomAdjuster {
|
|||||||
// Similar to BIND_WAIVE_PRIORITY, keep it unfrozen.
|
// Similar to BIND_WAIVE_PRIORITY, keep it unfrozen.
|
||||||
if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
|
if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
|
||||||
app.mOptRecord.setShouldNotFreeze(true);
|
app.mOptRecord.setShouldNotFreeze(true);
|
||||||
// Similarly, we shouldn't kill it when it's in forced-app-standby
|
|
||||||
// mode and cached & idle state.
|
|
||||||
app.mState.setNoKillOnForcedAppStandbyAndIdle(true);
|
|
||||||
}
|
}
|
||||||
// Not doing bind OOM management, so treat
|
// Not doing bind OOM management, so treat
|
||||||
// this guy more like a started service.
|
// this guy more like a started service.
|
||||||
@@ -2226,9 +2230,6 @@ public class OomAdjuster {
|
|||||||
// unfrozen.
|
// unfrozen.
|
||||||
if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
|
if (clientAdj < ProcessList.CACHED_APP_MIN_ADJ) {
|
||||||
app.mOptRecord.setShouldNotFreeze(true);
|
app.mOptRecord.setShouldNotFreeze(true);
|
||||||
// Similarly, we shouldn't kill it when it's in forced-app-standby
|
|
||||||
// mode and cached & idle state.
|
|
||||||
app.mState.setNoKillOnForcedAppStandbyAndIdle(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
|
if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
|
||||||
@@ -2302,6 +2303,10 @@ public class OomAdjuster {
|
|||||||
// we are going to consider it empty.
|
// we are going to consider it empty.
|
||||||
clientProcState = PROCESS_STATE_CACHED_EMPTY;
|
clientProcState = PROCESS_STATE_CACHED_EMPTY;
|
||||||
}
|
}
|
||||||
|
if (client.mOptRecord.shouldNotFreeze()) {
|
||||||
|
// Propagate the shouldNotFreeze flag down the bindings.
|
||||||
|
app.mOptRecord.setShouldNotFreeze(true);
|
||||||
|
}
|
||||||
String adjType = null;
|
String adjType = null;
|
||||||
if (adj > clientAdj) {
|
if (adj > clientAdj) {
|
||||||
if (state.hasShownUi() && !state.getCachedIsHomeProcess()
|
if (state.hasShownUi() && !state.getCachedIsHomeProcess()
|
||||||
|
|||||||
@@ -357,13 +357,6 @@ final class ProcessStateRecord {
|
|||||||
@ElapsedRealtimeLong
|
@ElapsedRealtimeLong
|
||||||
private long mLastInvisibleTime;
|
private long mLastInvisibleTime;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether or not this process could be killed when it's in forced-app-standby mode
|
|
||||||
* and cached & idle state.
|
|
||||||
*/
|
|
||||||
@GuardedBy("mService")
|
|
||||||
private boolean mNoKillOnForcedAppStandbyAndIdle;
|
|
||||||
|
|
||||||
// Below are the cached task info for OomAdjuster only
|
// Below are the cached task info for OomAdjuster only
|
||||||
private static final int VALUE_INVALID = -1;
|
private static final int VALUE_INVALID = -1;
|
||||||
private static final int VALUE_FALSE = 0;
|
private static final int VALUE_FALSE = 0;
|
||||||
@@ -1134,16 +1127,6 @@ final class ProcessStateRecord {
|
|||||||
return mLastInvisibleTime;
|
return mLastInvisibleTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mService")
|
|
||||||
void setNoKillOnForcedAppStandbyAndIdle(boolean shouldNotKill) {
|
|
||||||
mNoKillOnForcedAppStandbyAndIdle = shouldNotKill;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GuardedBy("mService")
|
|
||||||
boolean shouldNotKillOnForcedAppStandbyAndIdle() {
|
|
||||||
return mNoKillOnForcedAppStandbyAndIdle;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GuardedBy({"mService", "mProcLock"})
|
@GuardedBy({"mService", "mProcLock"})
|
||||||
void dump(PrintWriter pw, String prefix, long nowUptime) {
|
void dump(PrintWriter pw, String prefix, long nowUptime) {
|
||||||
if (mReportedInteraction || mFgInteractionTime != 0) {
|
if (mReportedInteraction || mFgInteractionTime != 0) {
|
||||||
|
|||||||
@@ -94,6 +94,17 @@ public class ActivityManagerTest {
|
|||||||
"com.android.servicestests.apps.simpleservicetestapp.ACTION_FGS_STATS_TEST";
|
"com.android.servicestests.apps.simpleservicetestapp.ACTION_FGS_STATS_TEST";
|
||||||
private static final String EXTRA_MESSENGER = "extra_messenger";
|
private static final String EXTRA_MESSENGER = "extra_messenger";
|
||||||
|
|
||||||
|
private static final String EXTRA_CALLBACK = "callback";
|
||||||
|
private static final String EXTRA_COMMAND = "command";
|
||||||
|
private static final String EXTRA_FLAGS = "flags";
|
||||||
|
private static final String EXTRA_TARGET_PACKAGE = "target_package";
|
||||||
|
|
||||||
|
private static final int COMMAND_INVALID = 0;
|
||||||
|
private static final int COMMAND_EMPTY = 1;
|
||||||
|
private static final int COMMAND_BIND_SERVICE = 2;
|
||||||
|
private static final int COMMAND_UNBIND_SERVICE = 3;
|
||||||
|
private static final int COMMAND_STOP_SELF = 4;
|
||||||
|
|
||||||
private IActivityManager mService;
|
private IActivityManager mService;
|
||||||
private IRemoteCallback mCallback;
|
private IRemoteCallback mCallback;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
@@ -333,6 +344,12 @@ public class ActivityManagerTest {
|
|||||||
SettingsSession<String> amConstantsSettings = null;
|
SettingsSession<String> amConstantsSettings = null;
|
||||||
DeviceConfigSession<Long> freezerDebounceTimeout = null;
|
DeviceConfigSession<Long> freezerDebounceTimeout = null;
|
||||||
MyServiceConnection autoConnection = null;
|
MyServiceConnection autoConnection = null;
|
||||||
|
final ActivityManager am = mContext.getSystemService(ActivityManager.class);
|
||||||
|
final PackageManager pm = mContext.getPackageManager();
|
||||||
|
final int uid1 = pm.getPackageUid(TEST_APP1, 0);
|
||||||
|
final int uid2 = pm.getPackageUid(TEST_APP2, 0);
|
||||||
|
final MyUidImportanceListener uid1Listener = new MyUidImportanceListener(uid1);
|
||||||
|
final MyUidImportanceListener uid2Listener = new MyUidImportanceListener(uid2);
|
||||||
try {
|
try {
|
||||||
if (!freezerWasEnabled) {
|
if (!freezerWasEnabled) {
|
||||||
freezerEnabled = new SettingsSession<>(
|
freezerEnabled = new SettingsSession<>(
|
||||||
@@ -346,7 +363,7 @@ public class ActivityManagerTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
freezerDebounceTimeout = new DeviceConfigSession<>(
|
freezerDebounceTimeout = new DeviceConfigSession<>(
|
||||||
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
|
DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
|
||||||
CachedAppOptimizer.KEY_FREEZER_DEBOUNCE_TIMEOUT,
|
CachedAppOptimizer.KEY_FREEZER_DEBOUNCE_TIMEOUT,
|
||||||
DeviceConfig::getLong, CachedAppOptimizer.DEFAULT_FREEZER_DEBOUNCE_TIMEOUT);
|
DeviceConfig::getLong, CachedAppOptimizer.DEFAULT_FREEZER_DEBOUNCE_TIMEOUT);
|
||||||
freezerDebounceTimeout.set(waitFor);
|
freezerDebounceTimeout.set(waitFor);
|
||||||
@@ -359,13 +376,20 @@ public class ActivityManagerTest {
|
|||||||
amConstantsSettings.set(
|
amConstantsSettings.set(
|
||||||
ActivityManagerConstants.KEY_MAX_SERVICE_INACTIVITY + "=" + waitFor);
|
ActivityManagerConstants.KEY_MAX_SERVICE_INACTIVITY + "=" + waitFor);
|
||||||
|
|
||||||
|
runShellCommand("cmd deviceidle whitelist +" + TEST_APP1);
|
||||||
|
runShellCommand("cmd deviceidle whitelist +" + TEST_APP2);
|
||||||
|
|
||||||
|
am.addOnUidImportanceListener(uid1Listener,
|
||||||
|
RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE);
|
||||||
|
am.addOnUidImportanceListener(uid2Listener, RunningAppProcessInfo.IMPORTANCE_CACHED);
|
||||||
|
|
||||||
final Intent intent = new Intent();
|
final Intent intent = new Intent();
|
||||||
intent.setClassName(TEST_APP1, TEST_CLASS);
|
intent.setClassName(TEST_APP1, TEST_CLASS);
|
||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
autoConnection = new MyServiceConnection(latch);
|
autoConnection = new MyServiceConnection(latch);
|
||||||
mContext.bindService(intent, autoConnection,
|
mContext.bindService(intent, autoConnection,
|
||||||
Context.BIND_AUTO_CREATE | Context.BIND_ALLOW_OOM_MANAGEMENT);
|
Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY);
|
||||||
try {
|
try {
|
||||||
assertTrue("Timeout to bind to service " + intent.getComponent(),
|
assertTrue("Timeout to bind to service " + intent.getComponent(),
|
||||||
latch.await(AWAIT_TIMEOUT, TimeUnit.MILLISECONDS));
|
latch.await(AWAIT_TIMEOUT, TimeUnit.MILLISECONDS));
|
||||||
@@ -383,6 +407,37 @@ public class ActivityManagerTest {
|
|||||||
|
|
||||||
// It still shouldn't be frozen, although it's been in cached state.
|
// It still shouldn't be frozen, although it's been in cached state.
|
||||||
assertFalse(TEST_APP1 + " shouldn't be frozen now.", isAppFrozen(TEST_APP1));
|
assertFalse(TEST_APP1 + " shouldn't be frozen now.", isAppFrozen(TEST_APP1));
|
||||||
|
|
||||||
|
final CountDownLatch[] latchHolder = new CountDownLatch[1];
|
||||||
|
final IRemoteCallback callback = new IRemoteCallback.Stub() {
|
||||||
|
@Override
|
||||||
|
public void sendResult(Bundle bundle) {
|
||||||
|
if (bundle != null) {
|
||||||
|
latchHolder[0].countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Bind from app1 to app2 without BIND_WAIVE_PRIORITY.
|
||||||
|
final Bundle extras = new Bundle();
|
||||||
|
extras.putBinder(EXTRA_CALLBACK, callback.asBinder());
|
||||||
|
latchHolder[0] = new CountDownLatch(1);
|
||||||
|
sendCommand(COMMAND_BIND_SERVICE, TEST_APP1, TEST_APP2, extras);
|
||||||
|
assertTrue("Timed out to bind to " + TEST_APP2, latchHolder[0].await(
|
||||||
|
waitFor, TimeUnit.MILLISECONDS));
|
||||||
|
|
||||||
|
// Stop service in app1
|
||||||
|
extras.clear();
|
||||||
|
sendCommand(COMMAND_STOP_SELF, TEST_APP1, TEST_APP1, extras);
|
||||||
|
|
||||||
|
assertTrue(TEST_APP2 + " should be in cached", uid2Listener.waitFor(
|
||||||
|
RunningAppProcessInfo.IMPORTANCE_CACHED, waitFor));
|
||||||
|
|
||||||
|
// Wait for the freezer kick in if there is any.
|
||||||
|
Thread.sleep(waitFor * 4);
|
||||||
|
|
||||||
|
// It still shouldn't be frozen, although it's been in cached state.
|
||||||
|
assertFalse(TEST_APP2 + " shouldn't be frozen now.", isAppFrozen(TEST_APP2));
|
||||||
} finally {
|
} finally {
|
||||||
toggleScreenOn(true);
|
toggleScreenOn(true);
|
||||||
if (amConstantsSettings != null) {
|
if (amConstantsSettings != null) {
|
||||||
@@ -397,9 +452,26 @@ public class ActivityManagerTest {
|
|||||||
if (autoConnection != null) {
|
if (autoConnection != null) {
|
||||||
mContext.unbindService(autoConnection);
|
mContext.unbindService(autoConnection);
|
||||||
}
|
}
|
||||||
|
am.removeOnUidImportanceListener(uid1Listener);
|
||||||
|
am.removeOnUidImportanceListener(uid2Listener);
|
||||||
|
sendCommand(COMMAND_UNBIND_SERVICE, TEST_APP1, TEST_APP2, null);
|
||||||
|
sendCommand(COMMAND_UNBIND_SERVICE, TEST_APP2, TEST_APP1, null);
|
||||||
|
runShellCommand("cmd deviceidle whitelist -" + TEST_APP1);
|
||||||
|
runShellCommand("cmd deviceidle whitelist -" + TEST_APP2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendCommand(int command, String sourcePkg, String targetPkg, Bundle extras) {
|
||||||
|
final Intent intent = new Intent();
|
||||||
|
intent.setClassName(sourcePkg, TEST_CLASS);
|
||||||
|
intent.putExtra(EXTRA_COMMAND, command);
|
||||||
|
intent.putExtra(EXTRA_TARGET_PACKAGE, targetPkg);
|
||||||
|
if (extras != null) {
|
||||||
|
intent.putExtras(extras);
|
||||||
|
}
|
||||||
|
mContext.startService(intent);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isFreezerEnabled() throws Exception {
|
private boolean isFreezerEnabled() throws Exception {
|
||||||
final String output = runShellCommand("dumpsys activity settings");
|
final String output = runShellCommand("dumpsys activity settings");
|
||||||
final Matcher matcher = Pattern.compile("\\b" + CachedAppOptimizer.KEY_USE_FREEZER
|
final Matcher matcher = Pattern.compile("\\b" + CachedAppOptimizer.KEY_USE_FREEZER
|
||||||
|
|||||||
@@ -16,29 +16,106 @@
|
|||||||
package com.android.servicestests.apps.simpleservicetestapp;
|
package com.android.servicestests.apps.simpleservicetestapp;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.IRemoteCallback;
|
import android.os.IRemoteCallback;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
public class SimpleService extends Service {
|
public class SimpleService extends Service {
|
||||||
private static final String TAG = "SimpleService";
|
private static final String TAG = "SimpleService";
|
||||||
|
|
||||||
|
private static final String TEST_CLASS =
|
||||||
|
"com.android.servicestests.apps.simpleservicetestapp.SimpleService";
|
||||||
|
|
||||||
|
private static final String EXTRA_CALLBACK = "callback";
|
||||||
|
private static final String EXTRA_COMMAND = "command";
|
||||||
|
private static final String EXTRA_FLAGS = "flags";
|
||||||
|
private static final String EXTRA_TARGET_PACKAGE = "target_package";
|
||||||
|
|
||||||
|
private static final int COMMAND_INVALID = 0;
|
||||||
|
private static final int COMMAND_EMPTY = 1;
|
||||||
|
private static final int COMMAND_BIND_SERVICE = 2;
|
||||||
|
private static final int COMMAND_UNBIND_SERVICE = 3;
|
||||||
|
private static final int COMMAND_STOP_SELF = 4;
|
||||||
|
|
||||||
|
private ArrayMap<String, ServiceConnection> mServiceConnections = new ArrayMap<>();
|
||||||
|
|
||||||
private final IRemoteCallback.Stub mBinder = new IRemoteCallback.Stub() {
|
private final IRemoteCallback.Stub mBinder = new IRemoteCallback.Stub() {
|
||||||
@Override
|
@Override
|
||||||
public void sendResult(Bundle bundle) {
|
public void sendResult(Bundle bundle) {
|
||||||
Process.killProcess(Process.myPid());
|
if (bundle == null) {
|
||||||
|
Process.killProcess(Process.myPid());
|
||||||
|
} else {
|
||||||
|
// No-op for now.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
Log.i(TAG, "onStartCommand");
|
Log.i(TAG, "onStartCommand");
|
||||||
|
int command = intent.getIntExtra(EXTRA_COMMAND, COMMAND_INVALID);
|
||||||
|
if (command != COMMAND_INVALID) {
|
||||||
|
final String targetPkg = intent.getStringExtra(EXTRA_TARGET_PACKAGE);
|
||||||
|
Log.i(TAG, "Received command " + command + " targetPkg=" + targetPkg);
|
||||||
|
switch (command) {
|
||||||
|
case COMMAND_BIND_SERVICE:
|
||||||
|
final Bundle extras = intent.getExtras();
|
||||||
|
bindToService(targetPkg, intent.getIntExtra(EXTRA_FLAGS, 0),
|
||||||
|
IRemoteCallback.Stub.asInterface(extras.getBinder(EXTRA_CALLBACK)));
|
||||||
|
break;
|
||||||
|
case COMMAND_UNBIND_SERVICE:
|
||||||
|
unbindService(targetPkg);
|
||||||
|
break;
|
||||||
|
case COMMAND_STOP_SELF:
|
||||||
|
stopSelf();
|
||||||
|
return START_NOT_STICKY;
|
||||||
|
}
|
||||||
|
}
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void bindToService(String targetPkg, int flags, IRemoteCallback callback) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.setClassName(targetPkg, TEST_CLASS);
|
||||||
|
final ServiceConnection conn = new ServiceConnection() {
|
||||||
|
@Override
|
||||||
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
|
if (callback != null) {
|
||||||
|
try {
|
||||||
|
callback.sendResult(new Bundle());
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onServiceDisconnected(ComponentName name) {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (getApplicationContext().bindService(intent, conn, BIND_AUTO_CREATE | flags)) {
|
||||||
|
mServiceConnections.put(targetPkg, conn);
|
||||||
|
} else if (callback != null) {
|
||||||
|
try {
|
||||||
|
callback.sendResult(null);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unbindService(String targetPkg) {
|
||||||
|
final ServiceConnection conn = mServiceConnections.remove(targetPkg);
|
||||||
|
if (conn != null) {
|
||||||
|
getApplicationContext().unbindService(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IBinder onBind(Intent intent) {
|
public IBinder onBind(Intent intent) {
|
||||||
return mBinder;
|
return mBinder;
|
||||||
|
|||||||
Reference in New Issue
Block a user