use of android.os.RemoteCallback in project android_frameworks_base by ResurrectionRemix.
the class ActiveServices method bindServiceLocked.
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String callingPackage, final int userId) throws TransactionTooLargeException {
if (DEBUG_SERVICE)
Slog.v(TAG_SERVICE, "bindService: " + service + " type=" + resolvedType + " conn=" + connection.asBinder() + " flags=0x" + Integer.toHexString(flags));
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException("Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when binding service " + service);
}
ActivityRecord activity = null;
if (token != null) {
activity = ActivityRecord.isInStackLocked(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
}
int clientLabel = 0;
PendingIntent clientIntent = null;
final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;
if (isCallerSystem) {
// Hacky kind of thing -- allow system stuff to tell us
// what they are, so we can report this elsewhere for
// others to know why certain services are running.
service.setDefusable(true);
clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT);
if (clientIntent != null) {
clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
if (clientLabel != 0) {
// There are no useful extras in the intent, trash them.
// System code calling with this stuff just needs to know
// this will happen.
service = service.cloneFilter();
}
}
}
if ((flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
mAm.enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, "BIND_TREAT_LIKE_ACTIVITY");
}
if ((flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0 && !isCallerSystem) {
throw new SecurityException("Non-system caller " + caller + " (pid=" + Binder.getCallingPid() + ") set BIND_ALLOW_WHITELIST_MANAGEMENT when binding service " + service);
}
final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
if (res == null) {
return 0;
}
if (res.record == null) {
return -1;
}
ServiceRecord s = res.record;
boolean permissionsReviewRequired = false;
// when done to start the bound service's process to completing the binding.
if (mAm.mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(s.packageName, s.userId)) {
permissionsReviewRequired = true;
// Show a permission review UI only for binding from a foreground app
if (!callerFg) {
Slog.w(TAG, "u" + s.userId + " Binding to a service in package" + s.packageName + " requires a permissions review");
return 0;
}
final ServiceRecord serviceRecord = s;
final Intent serviceIntent = service;
RemoteCallback callback = new RemoteCallback(new RemoteCallback.OnResultListener() {
@Override
public void onResult(Bundle result) {
synchronized (mAm) {
final long identity = Binder.clearCallingIdentity();
try {
if (!mPendingServices.contains(serviceRecord)) {
return;
}
// otherwise we unbind because the user didn't approve.
if (!mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(serviceRecord.packageName, serviceRecord.userId)) {
try {
bringUpServiceLocked(serviceRecord, serviceIntent.getFlags(), callerFg, false, false);
} catch (RemoteException e) {
/* ignore - local call */
}
} else {
unbindServiceLocked(connection);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
});
final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName);
intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);
if (DEBUG_PERMISSIONS_REVIEW) {
Slog.i(TAG, "u" + s.userId + " Launching permission review for package " + s.packageName);
}
mAm.mHandler.post(new Runnable() {
@Override
public void run() {
mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
}
});
}
}
final long origId = Binder.clearCallingIdentity();
try {
if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
if (DEBUG_SERVICE)
Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: " + s);
}
if ((flags & Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (!s.hasAutoCreateConnections()) {
// This is the first binding, let the tracker know.
ServiceState stracker = s.getTracker();
if (stracker != null) {
stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(), s.lastActivity);
}
}
}
mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState, s.appInfo.uid, s.name, s.processName);
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity, connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
b.client.connections.add(c);
if ((c.flags & Context.BIND_ABOVE_CLIENT) != 0) {
b.client.hasAboveClient = true;
}
if ((c.flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
s.whitelistManager = true;
}
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
if ((flags & Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) {
return 0;
}
}
if (s.app != null) {
if ((flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
s.app.treatLikeActivity = true;
}
if (s.whitelistManager) {
s.app.whitelistManager = true;
}
// This could have made the service more important.
mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities || s.app.treatLikeActivity, b.client);
mAm.updateOomAdjLocked(s.app);
}
if (DEBUG_SERVICE)
Slog.v(TAG_SERVICE, "Bind " + s + " with " + b + ": received=" + b.intent.received + " apps=" + b.intent.apps.size() + " doRebind=" + b.intent.doRebind);
if (s.app != null && b.intent.received) {
// publish the connection.
try {
c.conn.connected(s.name, b.intent.binder);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortName + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e);
}
// rebound, then do so.
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
getServiceMap(s.userId).ensureNotStartingBackground(s);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
use of android.os.RemoteCallback in project Resurrection_packages_apps_Settings by ResurrectionRemix.
the class DeviceAdminAdd method onCreate.
@Override
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
mHandler = new Handler(getMainLooper());
mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
mAppOps = (AppOpsManager) getSystemService(Context.APP_OPS_SERVICE);
PackageManager packageManager = getPackageManager();
if ((getIntent().getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
Log.w(TAG, "Cannot start ADD_DEVICE_ADMIN as a new task");
finish();
return;
}
mIsCalledFromSupportDialog = getIntent().getBooleanExtra(EXTRA_CALLED_FROM_SUPPORT_DIALOG, false);
String action = getIntent().getAction();
ComponentName who = (ComponentName) getIntent().getParcelableExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN);
if (who == null) {
String packageName = getIntent().getStringExtra(EXTRA_DEVICE_ADMIN_PACKAGE_NAME);
for (ComponentName component : mDPM.getActiveAdmins()) {
if (component.getPackageName().equals(packageName)) {
who = component;
mUninstalling = true;
break;
}
}
if (who == null) {
Log.w(TAG, "No component specified in " + action);
finish();
return;
}
}
if (action != null && action.equals(DevicePolicyManager.ACTION_SET_PROFILE_OWNER)) {
setResult(RESULT_CANCELED);
setFinishOnTouchOutside(true);
mAddingProfileOwner = true;
mProfileOwnerName = getIntent().getStringExtra(DevicePolicyManager.EXTRA_PROFILE_OWNER_NAME);
String callingPackage = getCallingPackage();
if (callingPackage == null || !callingPackage.equals(who.getPackageName())) {
Log.e(TAG, "Unknown or incorrect caller");
finish();
return;
}
try {
PackageInfo packageInfo = packageManager.getPackageInfo(callingPackage, 0);
if ((packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
Log.e(TAG, "Cannot set a non-system app as a profile owner");
finish();
return;
}
} catch (NameNotFoundException nnfe) {
Log.e(TAG, "Cannot find the package " + callingPackage);
finish();
return;
}
}
ActivityInfo ai;
try {
ai = packageManager.getReceiverInfo(who, PackageManager.GET_META_DATA);
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Unable to retrieve device policy " + who, e);
finish();
return;
}
// invalid device admin.
if (!mDPM.isAdminActive(who)) {
List<ResolveInfo> avail = packageManager.queryBroadcastReceivers(new Intent(DeviceAdminReceiver.ACTION_DEVICE_ADMIN_ENABLED), PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS);
int count = avail == null ? 0 : avail.size();
boolean found = false;
for (int i = 0; i < count; i++) {
ResolveInfo ri = avail.get(i);
if (ai.packageName.equals(ri.activityInfo.packageName) && ai.name.equals(ri.activityInfo.name)) {
try {
// We didn't retrieve the meta data for all possible matches, so
// need to use the activity info of this specific one that was retrieved.
ri.activityInfo = ai;
DeviceAdminInfo dpi = new DeviceAdminInfo(this, ri);
found = true;
} catch (XmlPullParserException e) {
Log.w(TAG, "Bad " + ri.activityInfo, e);
} catch (IOException e) {
Log.w(TAG, "Bad " + ri.activityInfo, e);
}
break;
}
}
if (!found) {
Log.w(TAG, "Request to add invalid device admin: " + who);
finish();
return;
}
}
ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
try {
mDeviceAdmin = new DeviceAdminInfo(this, ri);
} catch (XmlPullParserException e) {
Log.w(TAG, "Unable to retrieve device policy " + who, e);
finish();
return;
} catch (IOException e) {
Log.w(TAG, "Unable to retrieve device policy " + who, e);
finish();
return;
}
// "OK" immediately.
if (DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN.equals(getIntent().getAction())) {
mRefreshing = false;
if (mDPM.isAdminActive(who)) {
if (mDPM.isRemovingAdmin(who, android.os.Process.myUserHandle().getIdentifier())) {
Log.w(TAG, "Requested admin is already being removed: " + who);
finish();
return;
}
ArrayList<DeviceAdminInfo.PolicyInfo> newPolicies = mDeviceAdmin.getUsedPolicies();
for (int i = 0; i < newPolicies.size(); i++) {
DeviceAdminInfo.PolicyInfo pi = newPolicies.get(i);
if (!mDPM.hasGrantedPolicy(who, pi.ident)) {
mRefreshing = true;
break;
}
}
if (!mRefreshing) {
// Nothing changed (or policies were removed) - return immediately
setResult(Activity.RESULT_OK);
finish();
return;
}
}
}
// need to prompt for permission. Just add and finish.
if (mAddingProfileOwner && !mDPM.hasUserSetupCompleted()) {
addAndFinish();
return;
}
mAddMsgText = getIntent().getCharSequenceExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION);
setContentView(R.layout.device_admin_add);
mAdminIcon = (ImageView) findViewById(R.id.admin_icon);
mAdminName = (TextView) findViewById(R.id.admin_name);
mAdminDescription = (TextView) findViewById(R.id.admin_description);
mProfileOwnerWarning = (TextView) findViewById(R.id.profile_owner_warning);
mAddMsg = (TextView) findViewById(R.id.add_msg);
mAddMsgExpander = (ImageView) findViewById(R.id.add_msg_expander);
final View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
toggleMessageEllipsis(mAddMsg);
}
};
mAddMsgExpander.setOnClickListener(onClickListener);
mAddMsg.setOnClickListener(onClickListener);
// Determine whether the message can be collapsed - getLineCount() gives the correct
// number of lines only after a layout pass.
mAddMsg.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
final int maxLines = getEllipsizedLines();
// hide the icon if number of visible lines does not exceed maxLines
boolean hideMsgExpander = mAddMsg.getLineCount() <= maxLines;
mAddMsgExpander.setVisibility(hideMsgExpander ? View.GONE : View.VISIBLE);
if (hideMsgExpander) {
mAddMsg.setOnClickListener(null);
((View) mAddMsgExpander.getParent()).invalidate();
}
mAddMsg.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
// toggleMessageEllipsis also handles initial layout:
toggleMessageEllipsis(mAddMsg);
mAdminWarning = (TextView) findViewById(R.id.admin_warning);
mAdminPolicies = (ViewGroup) findViewById(R.id.admin_policies);
mSupportMessage = (TextView) findViewById(R.id.admin_support_message);
mCancelButton = (Button) findViewById(R.id.cancel_button);
mCancelButton.setFilterTouchesWhenObscured(true);
mCancelButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_DECLINED_BY_USER, mDeviceAdmin.getActivityInfo().applicationInfo.uid);
finish();
}
});
mUninstallButton = (Button) findViewById(R.id.uninstall_button);
mUninstallButton.setFilterTouchesWhenObscured(true);
mUninstallButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
EventLog.writeEvent(EventLogTags.EXP_DET_DEVICE_ADMIN_UNINSTALLED_BY_USER, mDeviceAdmin.getActivityInfo().applicationInfo.uid);
mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
finish();
}
});
mActionButton = (Button) findViewById(R.id.action_button);
mActionButton.setFilterTouchesWhenObscured(true);
mActionButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (mAdding) {
addAndFinish();
} else if (isManagedProfile(mDeviceAdmin) && mDeviceAdmin.getComponent().equals(mDPM.getProfileOwner())) {
final int userId = UserHandle.myUserId();
UserDialogs.createRemoveDialog(DeviceAdminAdd.this, userId, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
UserManager um = UserManager.get(DeviceAdminAdd.this);
um.removeUser(userId);
finish();
}
}).show();
} else if (mUninstalling) {
mDPM.uninstallPackageWithActiveAdmins(mDeviceAdmin.getPackageName());
finish();
} else if (!mWaitingForRemoveMsg) {
try {
// Don't allow the admin to put a dialog up in front
// of us while we interact with the user.
ActivityManagerNative.getDefault().stopAppSwitches();
} catch (RemoteException e) {
}
mWaitingForRemoveMsg = true;
mDPM.getRemoveWarning(mDeviceAdmin.getComponent(), new RemoteCallback(new RemoteCallback.OnResultListener() {
@Override
public void onResult(Bundle result) {
CharSequence msg = result != null ? result.getCharSequence(DeviceAdminReceiver.EXTRA_DISABLE_WARNING) : null;
continueRemoveAction(msg);
}
}, mHandler));
// Don't want to wait too long.
getWindow().getDecorView().getHandler().postDelayed(new Runnable() {
@Override
public void run() {
continueRemoveAction(null);
}
}, 2 * 1000);
}
}
});
}
use of android.os.RemoteCallback in project android_frameworks_base by DirtyUnicorns.
the class ActiveServices method bindServiceLocked.
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String callingPackage, final int userId) throws TransactionTooLargeException {
if (DEBUG_SERVICE)
Slog.v(TAG_SERVICE, "bindService: " + service + " type=" + resolvedType + " conn=" + connection.asBinder() + " flags=0x" + Integer.toHexString(flags));
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException("Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when binding service " + service);
}
ActivityRecord activity = null;
if (token != null) {
activity = ActivityRecord.isInStackLocked(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
}
int clientLabel = 0;
PendingIntent clientIntent = null;
final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;
if (isCallerSystem) {
// Hacky kind of thing -- allow system stuff to tell us
// what they are, so we can report this elsewhere for
// others to know why certain services are running.
service.setDefusable(true);
clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT);
if (clientIntent != null) {
clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
if (clientLabel != 0) {
// There are no useful extras in the intent, trash them.
// System code calling with this stuff just needs to know
// this will happen.
service = service.cloneFilter();
}
}
}
if ((flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
mAm.enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, "BIND_TREAT_LIKE_ACTIVITY");
}
if ((flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0 && !isCallerSystem) {
throw new SecurityException("Non-system caller " + caller + " (pid=" + Binder.getCallingPid() + ") set BIND_ALLOW_WHITELIST_MANAGEMENT when binding service " + service);
}
final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
if (res == null) {
return 0;
}
if (res.record == null) {
return -1;
}
ServiceRecord s = res.record;
boolean permissionsReviewRequired = false;
// when done to start the bound service's process to completing the binding.
if (mAm.mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(s.packageName, s.userId)) {
permissionsReviewRequired = true;
// Show a permission review UI only for binding from a foreground app
if (!callerFg) {
Slog.w(TAG, "u" + s.userId + " Binding to a service in package" + s.packageName + " requires a permissions review");
return 0;
}
final ServiceRecord serviceRecord = s;
final Intent serviceIntent = service;
RemoteCallback callback = new RemoteCallback(new RemoteCallback.OnResultListener() {
@Override
public void onResult(Bundle result) {
synchronized (mAm) {
final long identity = Binder.clearCallingIdentity();
try {
if (!mPendingServices.contains(serviceRecord)) {
return;
}
// otherwise we unbind because the user didn't approve.
if (!mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(serviceRecord.packageName, serviceRecord.userId)) {
try {
bringUpServiceLocked(serviceRecord, serviceIntent.getFlags(), callerFg, false, false);
} catch (RemoteException e) {
/* ignore - local call */
}
} else {
unbindServiceLocked(connection);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
});
final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName);
intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);
if (DEBUG_PERMISSIONS_REVIEW) {
Slog.i(TAG, "u" + s.userId + " Launching permission review for package " + s.packageName);
}
mAm.mHandler.post(new Runnable() {
@Override
public void run() {
mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
}
});
}
}
final long origId = Binder.clearCallingIdentity();
try {
if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
if (DEBUG_SERVICE)
Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: " + s);
}
if ((flags & Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (!s.hasAutoCreateConnections()) {
// This is the first binding, let the tracker know.
ServiceState stracker = s.getTracker();
if (stracker != null) {
stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(), s.lastActivity);
}
}
}
mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState, s.appInfo.uid, s.name, s.processName);
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity, connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
b.client.connections.add(c);
if ((c.flags & Context.BIND_ABOVE_CLIENT) != 0) {
b.client.hasAboveClient = true;
}
if ((c.flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
s.whitelistManager = true;
}
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
if ((flags & Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) {
return 0;
}
}
if (s.app != null) {
if ((flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
s.app.treatLikeActivity = true;
}
if (s.whitelistManager) {
s.app.whitelistManager = true;
}
// This could have made the service more important.
mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities || s.app.treatLikeActivity, b.client);
mAm.updateOomAdjLocked(s.app);
}
if (DEBUG_SERVICE)
Slog.v(TAG_SERVICE, "Bind " + s + " with " + b + ": received=" + b.intent.received + " apps=" + b.intent.apps.size() + " doRebind=" + b.intent.doRebind);
if (s.app != null && b.intent.received) {
// publish the connection.
try {
c.conn.connected(s.name, b.intent.binder);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortName + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e);
}
// rebound, then do so.
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
getServiceMap(s.userId).ensureNotStartingBackground(s);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
use of android.os.RemoteCallback in project android_frameworks_base by AOSPA.
the class SyncManager method scheduleSync.
/**
* @param minDelayMillis The sync can't land before this delay expires.
*/
private void scheduleSync(Account requestedAccount, int userId, int reason, String requestedAuthority, Bundle extras, int targetSyncState, final long minDelayMillis) {
final boolean isLoggable = Log.isLoggable(TAG, Log.VERBOSE);
if (extras == null) {
extras = new Bundle();
}
if (isLoggable) {
Log.d(TAG, "one-time sync for: " + requestedAccount + " " + extras.toString() + " " + requestedAuthority);
}
AccountAndUser[] accounts = null;
if (requestedAccount != null) {
if (userId != UserHandle.USER_ALL) {
accounts = new AccountAndUser[] { new AccountAndUser(requestedAccount, userId) };
} else {
for (AccountAndUser runningAccount : mRunningAccounts) {
if (requestedAccount.equals(runningAccount.account)) {
accounts = ArrayUtils.appendElement(AccountAndUser.class, accounts, runningAccount);
}
}
}
} else {
accounts = mRunningAccounts;
}
if (ArrayUtils.isEmpty(accounts)) {
if (isLoggable) {
Slog.v(TAG, "scheduleSync: no accounts configured, dropping");
}
return;
}
final boolean uploadOnly = extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false);
final boolean manualSync = extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
if (manualSync) {
extras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, true);
extras.putBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, true);
}
final boolean ignoreSettings = extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
int source;
if (uploadOnly) {
source = SyncStorageEngine.SOURCE_LOCAL;
} else if (manualSync) {
source = SyncStorageEngine.SOURCE_USER;
} else if (requestedAuthority == null) {
source = SyncStorageEngine.SOURCE_POLL;
} else {
// This isn't strictly server, since arbitrary callers can (and do) request
// a non-forced two-way sync on a specific url.
source = SyncStorageEngine.SOURCE_SERVER;
}
for (AccountAndUser account : accounts) {
// If userId is specified, do not sync accounts of other users
if (userId >= UserHandle.USER_SYSTEM && account.userId >= UserHandle.USER_SYSTEM && userId != account.userId) {
continue;
}
// Compile a list of authorities that have sync adapters.
// For each authority sync each account that matches a sync adapter.
final HashSet<String> syncableAuthorities = new HashSet<String>();
for (RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapter : mSyncAdapters.getAllServices(account.userId)) {
syncableAuthorities.add(syncAdapter.type.authority);
}
// syncable.
if (requestedAuthority != null) {
final boolean hasSyncAdapter = syncableAuthorities.contains(requestedAuthority);
syncableAuthorities.clear();
if (hasSyncAdapter)
syncableAuthorities.add(requestedAuthority);
}
for (String authority : syncableAuthorities) {
int isSyncable = computeSyncable(account.account, account.userId, authority);
if (isSyncable == AuthorityInfo.NOT_SYNCABLE) {
continue;
}
final RegisteredServicesCache.ServiceInfo<SyncAdapterType> syncAdapterInfo = mSyncAdapters.getServiceInfo(SyncAdapterType.newKey(authority, account.account.type), account.userId);
if (syncAdapterInfo == null) {
continue;
}
final int owningUid = syncAdapterInfo.uid;
if (isSyncable == AuthorityInfo.SYNCABLE_NO_ACCOUNT_ACCESS) {
if (isLoggable) {
Slog.v(TAG, " Not scheduling sync operation: " + "isSyncable == SYNCABLE_NO_ACCOUNT_ACCESS");
}
Bundle finalExtras = new Bundle(extras);
String packageName = syncAdapterInfo.componentName.getPackageName();
// If the app did not run and has no account access, done
if (!mPackageManagerInternal.wasPackageEverLaunched(packageName, userId)) {
continue;
}
mAccountManagerInternal.requestAccountAccess(account.account, packageName, userId, new RemoteCallback((Bundle result) -> {
if (result != null && result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT)) {
scheduleSync(account.account, userId, reason, authority, finalExtras, targetSyncState, minDelayMillis);
}
}));
continue;
}
final boolean allowParallelSyncs = syncAdapterInfo.type.allowParallelSyncs();
final boolean isAlwaysSyncable = syncAdapterInfo.type.isAlwaysSyncable();
if (isSyncable < 0 && isAlwaysSyncable) {
mSyncStorageEngine.setIsSyncable(account.account, account.userId, authority, AuthorityInfo.SYNCABLE);
isSyncable = AuthorityInfo.SYNCABLE;
}
if (targetSyncState != AuthorityInfo.UNDEFINED && targetSyncState != isSyncable) {
continue;
}
if (!syncAdapterInfo.type.supportsUploading() && uploadOnly) {
continue;
}
boolean syncAllowed = // Always allow if the isSyncable state is unknown.
(isSyncable < 0) || ignoreSettings || (mSyncStorageEngine.getMasterSyncAutomatically(account.userId) && mSyncStorageEngine.getSyncAutomatically(account.account, account.userId, authority));
if (!syncAllowed) {
if (isLoggable) {
Log.d(TAG, "scheduleSync: sync of " + account + ", " + authority + " is not allowed, dropping request");
}
continue;
}
SyncStorageEngine.EndPoint info = new SyncStorageEngine.EndPoint(account.account, authority, account.userId);
long delayUntil = mSyncStorageEngine.getDelayUntilTime(info);
final String owningPackage = syncAdapterInfo.componentName.getPackageName();
if (isSyncable == AuthorityInfo.NOT_INITIALIZED) {
// Initialisation sync.
Bundle newExtras = new Bundle();
newExtras.putBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, true);
if (isLoggable) {
Slog.v(TAG, "schedule initialisation Sync:" + ", delay until " + delayUntil + ", run by " + 0 + ", flexMillis " + 0 + ", source " + source + ", account " + account + ", authority " + authority + ", extras " + newExtras);
}
postScheduleSyncMessage(new SyncOperation(account.account, account.userId, owningUid, owningPackage, reason, source, authority, newExtras, allowParallelSyncs), minDelayMillis);
} else if (targetSyncState == AuthorityInfo.UNDEFINED || targetSyncState == isSyncable) {
if (isLoggable) {
Slog.v(TAG, "scheduleSync:" + " delay until " + delayUntil + ", source " + source + ", account " + account + ", authority " + authority + ", extras " + extras);
}
postScheduleSyncMessage(new SyncOperation(account.account, account.userId, owningUid, owningPackage, reason, source, authority, extras, allowParallelSyncs), minDelayMillis);
}
}
}
}
use of android.os.RemoteCallback in project android_frameworks_base by crdroidandroid.
the class ActiveServices method bindServiceLocked.
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, final IServiceConnection connection, int flags, String callingPackage, final int userId) throws TransactionTooLargeException {
if (DEBUG_SERVICE)
Slog.v(TAG_SERVICE, "bindService: " + service + " type=" + resolvedType + " conn=" + connection.asBinder() + " flags=0x" + Integer.toHexString(flags));
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException("Unable to find app for caller " + caller + " (pid=" + Binder.getCallingPid() + ") when binding service " + service);
}
ActivityRecord activity = null;
if (token != null) {
activity = ActivityRecord.isInStackLocked(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
}
int clientLabel = 0;
PendingIntent clientIntent = null;
final boolean isCallerSystem = callerApp.info.uid == Process.SYSTEM_UID;
if (isCallerSystem) {
// Hacky kind of thing -- allow system stuff to tell us
// what they are, so we can report this elsewhere for
// others to know why certain services are running.
service.setDefusable(true);
clientIntent = service.getParcelableExtra(Intent.EXTRA_CLIENT_INTENT);
if (clientIntent != null) {
clientLabel = service.getIntExtra(Intent.EXTRA_CLIENT_LABEL, 0);
if (clientLabel != 0) {
// There are no useful extras in the intent, trash them.
// System code calling with this stuff just needs to know
// this will happen.
service = service.cloneFilter();
}
}
}
if ((flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
mAm.enforceCallingPermission(android.Manifest.permission.MANAGE_ACTIVITY_STACKS, "BIND_TREAT_LIKE_ACTIVITY");
}
if ((flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0 && !isCallerSystem) {
throw new SecurityException("Non-system caller " + caller + " (pid=" + Binder.getCallingPid() + ") set BIND_ALLOW_WHITELIST_MANAGEMENT when binding service " + service);
}
final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;
ServiceLookupResult res = retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
if (res == null) {
return 0;
}
if (res.record == null) {
return -1;
}
ServiceRecord s = res.record;
boolean permissionsReviewRequired = false;
// when done to start the bound service's process to completing the binding.
if (mAm.mPermissionReviewRequired || Build.PERMISSIONS_REVIEW_REQUIRED) {
if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(s.packageName, s.userId)) {
permissionsReviewRequired = true;
// Show a permission review UI only for binding from a foreground app
if (!callerFg) {
Slog.w(TAG, "u" + s.userId + " Binding to a service in package" + s.packageName + " requires a permissions review");
return 0;
}
final ServiceRecord serviceRecord = s;
final Intent serviceIntent = service;
RemoteCallback callback = new RemoteCallback(new RemoteCallback.OnResultListener() {
@Override
public void onResult(Bundle result) {
synchronized (mAm) {
final long identity = Binder.clearCallingIdentity();
try {
if (!mPendingServices.contains(serviceRecord)) {
return;
}
// otherwise we unbind because the user didn't approve.
if (!mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(serviceRecord.packageName, serviceRecord.userId)) {
try {
bringUpServiceLocked(serviceRecord, serviceIntent.getFlags(), callerFg, false, false);
} catch (RemoteException e) {
/* ignore - local call */
}
} else {
unbindServiceLocked(connection);
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
}
});
final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
intent.putExtra(Intent.EXTRA_PACKAGE_NAME, s.packageName);
intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);
if (DEBUG_PERMISSIONS_REVIEW) {
Slog.i(TAG, "u" + s.userId + " Launching permission review for package " + s.packageName);
}
mAm.mHandler.post(new Runnable() {
@Override
public void run() {
mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
}
});
}
}
final long origId = Binder.clearCallingIdentity();
IBinder ibinder = connection.asBinder();
ArrayList<ConnectionRecord> list = s.connections.get(ibinder);
if (list != null && list.size() >= MAX_SERVICE_COUNT) {
Slog.e(TAG_SERVICE, s + " has already bind " + MAX_SERVICE_COUNT + " connections. Not allow to bind more.");
return 0;
}
try {
if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {
if (DEBUG_SERVICE)
Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: " + s);
}
if ((flags & Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (!s.hasAutoCreateConnections()) {
// This is the first binding, let the tracker know.
ServiceState stracker = s.getTracker();
if (stracker != null) {
stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(), s.lastActivity);
}
}
}
mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState, s.appInfo.uid, s.name, s.processName);
AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
ConnectionRecord c = new ConnectionRecord(b, activity, connection, flags, clientLabel, clientIntent);
IBinder binder = connection.asBinder();
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
s.connections.put(binder, clist);
}
clist.add(c);
b.connections.add(c);
if (activity != null) {
if (activity.connections == null) {
activity.connections = new HashSet<ConnectionRecord>();
}
activity.connections.add(c);
}
b.client.connections.add(c);
if ((c.flags & Context.BIND_ABOVE_CLIENT) != 0) {
b.client.hasAboveClient = true;
}
if ((c.flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0) {
s.whitelistManager = true;
}
if (s.app != null) {
updateServiceClientActivitiesLocked(s.app, c, true);
}
clist = mServiceConnections.get(binder);
if (clist == null) {
clist = new ArrayList<ConnectionRecord>();
mServiceConnections.put(binder, clist);
}
clist.add(c);
if ((flags & Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false, permissionsReviewRequired) != null) {
return 0;
}
}
if (s.app != null) {
if ((flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {
s.app.treatLikeActivity = true;
}
if (s.whitelistManager) {
s.app.whitelistManager = true;
}
// This could have made the service more important.
mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities || s.app.treatLikeActivity, b.client);
mAm.updateOomAdjLocked(s.app);
}
if (DEBUG_SERVICE)
Slog.v(TAG_SERVICE, "Bind " + s + " with " + b + ": received=" + b.intent.received + " apps=" + b.intent.apps.size() + " doRebind=" + b.intent.doRebind);
if (s.app != null && b.intent.received) {
// publish the connection.
try {
c.conn.connected(s.name, b.intent.binder);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + s.shortName + " to connection " + c.conn.asBinder() + " (in " + c.binding.client.processName + ")", e);
}
// rebound, then do so.
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
} else if (!b.intent.requested) {
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
getServiceMap(s.userId).ensureNotStartingBackground(s);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
Aggregations