Search in sources :

Example 1 with RemoteCallback

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;
}
Also used : ServiceState(com.android.internal.app.procstats.ServiceState) Bundle(android.os.Bundle) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) RemoteCallback(android.os.RemoteCallback) RemoteException(android.os.RemoteException) TransactionTooLargeException(android.os.TransactionTooLargeException) IOException(java.io.IOException) DeadObjectException(android.os.DeadObjectException) IBinder(android.os.IBinder) UserHandle(android.os.UserHandle) PendingIntent(android.app.PendingIntent) RemoteException(android.os.RemoteException)

Example 2 with RemoteCallback

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);
            }
        }
    });
}
Also used : DialogInterface(android.content.DialogInterface) ResolveInfo(android.content.pm.ResolveInfo) PackageManager(android.content.pm.PackageManager) ComponentName(android.content.ComponentName) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) ViewTreeObserver(android.view.ViewTreeObserver) ActivityInfo(android.content.pm.ActivityInfo) NameNotFoundException(android.content.pm.PackageManager.NameNotFoundException) NameNotFoundException(android.content.pm.PackageManager.NameNotFoundException) PackageInfo(android.content.pm.PackageInfo) Bundle(android.os.Bundle) Handler(android.os.Handler) Intent(android.content.Intent) IOException(java.io.IOException) ImageView(android.widget.ImageView) View(android.view.View) TextView(android.widget.TextView) RemoteCallback(android.os.RemoteCallback) UserManager(android.os.UserManager) DeviceAdminInfo(android.app.admin.DeviceAdminInfo) RemoteException(android.os.RemoteException)

Example 3 with RemoteCallback

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;
}
Also used : ServiceState(com.android.internal.app.procstats.ServiceState) Bundle(android.os.Bundle) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) RemoteCallback(android.os.RemoteCallback) RemoteException(android.os.RemoteException) TransactionTooLargeException(android.os.TransactionTooLargeException) IOException(java.io.IOException) DeadObjectException(android.os.DeadObjectException) IBinder(android.os.IBinder) UserHandle(android.os.UserHandle) PendingIntent(android.app.PendingIntent) RemoteException(android.os.RemoteException)

Example 4 with RemoteCallback

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);
            }
        }
    }
}
Also used : Bundle(android.os.Bundle) SyncAdapterType(android.content.SyncAdapterType) EndPoint(com.android.server.content.SyncStorageEngine.EndPoint) RemoteCallback(android.os.RemoteCallback) EndPoint(com.android.server.content.SyncStorageEngine.EndPoint) EndPoint(com.android.server.content.SyncStorageEngine.EndPoint) AccountAndUser(android.accounts.AccountAndUser) RegisteredServicesCache(android.content.pm.RegisteredServicesCache) HashSet(java.util.HashSet)

Example 5 with RemoteCallback

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;
}
Also used : ServiceState(com.android.internal.app.procstats.ServiceState) Bundle(android.os.Bundle) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) RemoteCallback(android.os.RemoteCallback) RemoteException(android.os.RemoteException) TransactionTooLargeException(android.os.TransactionTooLargeException) IOException(java.io.IOException) DeadObjectException(android.os.DeadObjectException) IBinder(android.os.IBinder) UserHandle(android.os.UserHandle) PendingIntent(android.app.PendingIntent) RemoteException(android.os.RemoteException)

Aggregations

RemoteCallback (android.os.RemoteCallback)25 Bundle (android.os.Bundle)19 RemoteException (android.os.RemoteException)13 IOException (java.io.IOException)13 Intent (android.content.Intent)12 DeviceAdminInfo (android.app.admin.DeviceAdminInfo)8 ComponentName (android.content.ComponentName)8 ActivityInfo (android.content.pm.ActivityInfo)8 PackageManager (android.content.pm.PackageManager)8 ResolveInfo (android.content.pm.ResolveInfo)8 Handler (android.os.Handler)8 View (android.view.View)8 ImageView (android.widget.ImageView)8 TextView (android.widget.TextView)8 XmlPullParserException (org.xmlpull.v1.XmlPullParserException)8 DialogInterface (android.content.DialogInterface)7 PackageInfo (android.content.pm.PackageInfo)7 NameNotFoundException (android.content.pm.PackageManager.NameNotFoundException)7 UserManager (android.os.UserManager)7 ViewTreeObserver (android.view.ViewTreeObserver)7