Search in sources :

Example 36 with ResolveInfo

use of android.content.pm.ResolveInfo in project android_frameworks_base by ParanoidAndroid.

the class ActivityManagerService method broadcastIntentLocked.

private final int broadcastIntentLocked(ProcessRecord callerApp, String callerPackage, Intent intent, String resolvedType, IIntentReceiver resultTo, int resultCode, String resultData, Bundle map, String requiredPermission, int appOp, boolean ordered, boolean sticky, int callingPid, int callingUid, int userId) {
    intent = new Intent(intent);
    // By default broadcasts do not go to stopped apps.
    intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
    if (DEBUG_BROADCAST_LIGHT)
        Slog.v(TAG, (sticky ? "Broadcast sticky: " : "Broadcast: ") + intent + " ordered=" + ordered + " userid=" + userId);
    if ((resultTo != null) && !ordered) {
        Slog.w(TAG, "Broadcast " + intent + " not ordered but result callback requested!");
    }
    userId = handleIncomingUser(callingPid, callingUid, userId, true, false, "broadcast", callerPackage);
    // If not, we will just skip it.
    if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) {
        if (callingUid != Process.SYSTEM_UID || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) {
            Slog.w(TAG, "Skipping broadcast of " + intent + ": user " + userId + " is stopped");
            return ActivityManager.BROADCAST_SUCCESS;
        }
    }
    /*
         * Prevent non-system code (defined here to be non-persistent
         * processes) from sending protected broadcasts.
         */
    int callingAppId = UserHandle.getAppId(callingUid);
    if (callingAppId == Process.SYSTEM_UID || callingAppId == Process.PHONE_UID || callingAppId == Process.SHELL_UID || callingAppId == Process.BLUETOOTH_UID || callingUid == 0) {
    // Always okay.
    } else if (callerApp == null || !callerApp.persistent) {
        try {
            if (AppGlobals.getPackageManager().isProtectedBroadcast(intent.getAction())) {
                String msg = "Permission Denial: not allowed to send broadcast " + intent.getAction() + " from pid=" + callingPid + ", uid=" + callingUid;
                Slog.w(TAG, msg);
                throw new SecurityException(msg);
            } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())) {
                // just limit it to the caller.
                if (callerApp == null) {
                    String msg = "Permission Denial: not allowed to send broadcast " + intent.getAction() + " from unknown caller.";
                    Slog.w(TAG, msg);
                    throw new SecurityException(msg);
                } else if (intent.getComponent() != null) {
                    // it is being sent to the calling app.
                    if (!intent.getComponent().getPackageName().equals(callerApp.info.packageName)) {
                        String msg = "Permission Denial: not allowed to send broadcast " + intent.getAction() + " to " + intent.getComponent().getPackageName() + " from " + callerApp.info.packageName;
                        Slog.w(TAG, msg);
                        throw new SecurityException(msg);
                    }
                } else {
                    // Limit broadcast to their own package.
                    intent.setPackage(callerApp.info.packageName);
                }
            }
        } catch (RemoteException e) {
            Slog.w(TAG, "Remote exception", e);
            return ActivityManager.BROADCAST_SUCCESS;
        }
    }
    // Handle special intents: if this broadcast is from the package
    // manager about a package being removed, we need to remove all of
    // its activities from the history stack.
    final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(intent.getAction());
    if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction()) || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction()) || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction()) || uidRemoved) {
        if (checkComponentPermission(android.Manifest.permission.BROADCAST_PACKAGE_REMOVED, callingPid, callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) {
            if (uidRemoved) {
                final Bundle intentExtras = intent.getExtras();
                final int uid = intentExtras != null ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
                if (uid >= 0) {
                    BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
                    synchronized (bs) {
                        bs.removeUidStatsLocked(uid);
                    }
                    mAppOpsService.uidRemoved(uid);
                }
            } else {
                // those packages and flush the attribute cache as well.
                if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
                    String[] list = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                    if (list != null && (list.length > 0)) {
                        for (String pkg : list) {
                            forceStopPackageLocked(pkg, -1, false, true, true, false, userId);
                        }
                        sendPackageBroadcastLocked(IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list, userId);
                    }
                } else {
                    Uri data = intent.getData();
                    String ssp;
                    if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
                        if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
                            forceStopPackageLocked(ssp, intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true, false, userId);
                        }
                        if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
                            sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED, new String[] { ssp }, userId);
                            if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
                                mAppOpsService.packageRemoved(intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
                            }
                        }
                    }
                }
            }
        } else {
            String msg = "Permission Denial: " + intent.getAction() + " broadcast from " + callerPackage + " (pid=" + callingPid + ", uid=" + callingUid + ")" + " requires " + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
        }
    // Special case for adding a package: by default turn on compatibility
    // mode.
    } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
        Uri data = intent.getData();
        String ssp;
        if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
            mCompatModePackages.handlePackageAddedLocked(ssp, intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
        }
    }
    /*
         * If this is the time zone changed action, queue up a message that will reset the timezone
         * of all currently running processes. This message will get queued up before the broadcast
         * happens.
         */
    if (intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
        mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
    }
    if (intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
        mHandler.sendEmptyMessage(CLEAR_DNS_CACHE);
    }
    if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
        ProxyProperties proxy = intent.getParcelableExtra("proxy");
        mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY, proxy));
    }
    // Add to the sticky list if requested.
    if (sticky) {
        if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, callingPid, callingUid) != PackageManager.PERMISSION_GRANTED) {
            String msg = "Permission Denial: broadcastIntent() requesting a sticky broadcast from pid=" + callingPid + ", uid=" + callingUid + " requires " + android.Manifest.permission.BROADCAST_STICKY;
            Slog.w(TAG, msg);
            throw new SecurityException(msg);
        }
        if (requiredPermission != null) {
            Slog.w(TAG, "Can't broadcast sticky intent " + intent + " and enforce permission " + requiredPermission);
            return ActivityManager.BROADCAST_STICKY_CANT_HAVE_PERMISSION;
        }
        if (intent.getComponent() != null) {
            throw new SecurityException("Sticky broadcasts can't target a specific component");
        }
        // as a separate set of sticky broadcasts.
        if (userId != UserHandle.USER_ALL) {
            // But first, if this is not a broadcast to all users, then
            // make sure it doesn't conflict with an existing broadcast to
            // all users.
            HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(UserHandle.USER_ALL);
            if (stickies != null) {
                ArrayList<Intent> list = stickies.get(intent.getAction());
                if (list != null) {
                    int N = list.size();
                    int i;
                    for (i = 0; i < N; i++) {
                        if (intent.filterEquals(list.get(i))) {
                            throw new IllegalArgumentException("Sticky broadcast " + intent + " for user " + userId + " conflicts with existing global broadcast");
                        }
                    }
                }
            }
        }
        HashMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId);
        if (stickies == null) {
            stickies = new HashMap<String, ArrayList<Intent>>();
            mStickyBroadcasts.put(userId, stickies);
        }
        ArrayList<Intent> list = stickies.get(intent.getAction());
        if (list == null) {
            list = new ArrayList<Intent>();
            stickies.put(intent.getAction(), list);
        }
        int N = list.size();
        int i;
        for (i = 0; i < N; i++) {
            if (intent.filterEquals(list.get(i))) {
                // This sticky already exists, replace it.
                list.set(i, new Intent(intent));
                break;
            }
        }
        if (i >= N) {
            list.add(new Intent(intent));
        }
    }
    int[] users;
    if (userId == UserHandle.USER_ALL) {
        // Caller wants broadcast to go to all started users.
        users = mStartedUserArray;
    } else {
        // Caller wants broadcast to go to one specific user.
        users = new int[] { userId };
    }
    // Figure out who all will receive this broadcast.
    List receivers = null;
    List<BroadcastFilter> registeredReceivers = null;
    // Need to resolve the intent to interested receivers...
    if ((intent.getFlags() & Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) {
        receivers = collectReceiverComponents(intent, resolvedType, users);
    }
    if (intent.getComponent() == null) {
        registeredReceivers = mReceiverResolver.queryIntent(intent, resolvedType, false, userId);
    }
    final boolean replacePending = (intent.getFlags() & Intent.FLAG_RECEIVER_REPLACE_PENDING) != 0;
    if (DEBUG_BROADCAST)
        Slog.v(TAG, "Enqueing broadcast: " + intent.getAction() + " replacePending=" + replacePending);
    int NR = registeredReceivers != null ? registeredReceivers.size() : 0;
    if (!ordered && NR > 0) {
        // If we are not serializing this broadcast, then send the
        // registered receivers separately so they don't wait for the
        // components to be launched.
        final BroadcastQueue queue = broadcastQueueForIntent(intent);
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, appOp, registeredReceivers, resultTo, resultCode, resultData, map, ordered, sticky, false, userId);
        if (DEBUG_BROADCAST)
            Slog.v(TAG, "Enqueueing parallel broadcast " + r);
        final boolean replaced = replacePending && queue.replaceParallelBroadcastLocked(r);
        if (!replaced) {
            queue.enqueueParallelBroadcastLocked(r);
            queue.scheduleBroadcastsLocked();
        }
        registeredReceivers = null;
        NR = 0;
    }
    // Merge into one list.
    int ir = 0;
    if (receivers != null) {
        // A special case for PACKAGE_ADDED: do not allow the package
        // being added to see this broadcast.  This prevents them from
        // using this as a back door to get run as soon as they are
        // installed.  Maybe in the future we want to have a special install
        // broadcast or such for apps, but we'd like to deliberately make
        // this decision.
        String[] skipPackages = null;
        if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction()) || Intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction()) || Intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
            Uri data = intent.getData();
            if (data != null) {
                String pkgName = data.getSchemeSpecificPart();
                if (pkgName != null) {
                    skipPackages = new String[] { pkgName };
                }
            }
        } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())) {
            skipPackages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
        }
        if (skipPackages != null && (skipPackages.length > 0)) {
            for (String skipPackage : skipPackages) {
                if (skipPackage != null) {
                    int NT = receivers.size();
                    for (int it = 0; it < NT; it++) {
                        ResolveInfo curt = (ResolveInfo) receivers.get(it);
                        if (curt.activityInfo.packageName.equals(skipPackage)) {
                            receivers.remove(it);
                            it--;
                            NT--;
                        }
                    }
                }
            }
        }
        int NT = receivers != null ? receivers.size() : 0;
        int it = 0;
        ResolveInfo curt = null;
        BroadcastFilter curr = null;
        while (it < NT && ir < NR) {
            if (curt == null) {
                curt = (ResolveInfo) receivers.get(it);
            }
            if (curr == null) {
                curr = registeredReceivers.get(ir);
            }
            if (curr.getPriority() >= curt.priority) {
                // Insert this broadcast record into the final list.
                receivers.add(it, curr);
                ir++;
                curr = null;
                it++;
                NT++;
            } else {
                // Skip to the next ResolveInfo in the final list.
                it++;
                curt = null;
            }
        }
    }
    while (ir < NR) {
        if (receivers == null) {
            receivers = new ArrayList();
        }
        receivers.add(registeredReceivers.get(ir));
        ir++;
    }
    if ((receivers != null && receivers.size() > 0) || resultTo != null) {
        BroadcastQueue queue = broadcastQueueForIntent(intent);
        BroadcastRecord r = new BroadcastRecord(queue, intent, callerApp, callerPackage, callingPid, callingUid, requiredPermission, appOp, receivers, resultTo, resultCode, resultData, map, ordered, sticky, false, userId);
        if (DEBUG_BROADCAST)
            Slog.v(TAG, "Enqueueing ordered broadcast " + r + ": prev had " + queue.mOrderedBroadcasts.size());
        if (DEBUG_BROADCAST) {
            int seq = r.intent.getIntExtra("seq", -1);
            Slog.i(TAG, "Enqueueing broadcast " + r.intent.getAction() + " seq=" + seq);
        }
        boolean replaced = replacePending && queue.replaceOrderedBroadcastLocked(r);
        if (!replaced) {
            queue.enqueueOrderedBroadcastLocked(r);
            queue.scheduleBroadcastsLocked();
        }
    }
    return ActivityManager.BROADCAST_SUCCESS;
}
Also used : ProxyProperties(android.net.ProxyProperties) Bundle(android.os.Bundle) ArrayList(java.util.ArrayList) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) BatteryStatsImpl(com.android.internal.os.BatteryStatsImpl) Uri(android.net.Uri) ResolveInfo(android.content.pm.ResolveInfo) ArrayList(java.util.ArrayList) RemoteCallbackList(android.os.RemoteCallbackList) List(java.util.List) RemoteException(android.os.RemoteException)

Example 37 with ResolveInfo

use of android.content.pm.ResolveInfo in project android_frameworks_base by ParanoidAndroid.

the class Vpn method establish.

/**
     * Establish a VPN network and return the file descriptor of the VPN
     * interface. This methods returns {@code null} if the application is
     * revoked or not prepared.
     *
     * @param config The parameters to configure the network.
     * @return The file descriptor of the VPN interface.
     */
public synchronized ParcelFileDescriptor establish(VpnConfig config) {
    // Check if the caller is already prepared.
    PackageManager pm = mContext.getPackageManager();
    ApplicationInfo app = null;
    try {
        app = pm.getApplicationInfo(mPackage, 0);
    } catch (Exception e) {
        return null;
    }
    if (Binder.getCallingUid() != app.uid) {
        return null;
    }
    // Check if the service is properly declared.
    Intent intent = new Intent(VpnConfig.SERVICE_INTERFACE);
    intent.setClassName(mPackage, config.user);
    ResolveInfo info = pm.resolveService(intent, 0);
    if (info == null) {
        throw new SecurityException("Cannot find " + config.user);
    }
    if (!BIND_VPN_SERVICE.equals(info.serviceInfo.permission)) {
        throw new SecurityException(config.user + " does not require " + BIND_VPN_SERVICE);
    }
    // Load the label.
    String label = app.loadLabel(pm).toString();
    // Load the icon and convert it into a bitmap.
    Drawable icon = app.loadIcon(pm);
    Bitmap bitmap = null;
    if (icon.getIntrinsicWidth() > 0 && icon.getIntrinsicHeight() > 0) {
        int width = mContext.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
        int height = mContext.getResources().getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
        icon.setBounds(0, 0, width, height);
        bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(bitmap);
        icon.draw(c);
        c.setBitmap(null);
    }
    // Configure the interface. Abort if any of these steps fails.
    ParcelFileDescriptor tun = ParcelFileDescriptor.adoptFd(jniCreate(config.mtu));
    try {
        updateState(DetailedState.CONNECTING, "establish");
        String interfaze = jniGetName(tun.getFd());
        if (jniSetAddresses(interfaze, config.addresses) < 1) {
            throw new IllegalArgumentException("At least one address must be specified");
        }
        if (config.routes != null) {
            jniSetRoutes(interfaze, config.routes);
        }
        Connection connection = new Connection();
        if (!mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE)) {
            throw new IllegalStateException("Cannot bind " + config.user);
        }
        if (mConnection != null) {
            mContext.unbindService(mConnection);
        }
        if (mInterface != null && !mInterface.equals(interfaze)) {
            jniReset(mInterface);
        }
        mConnection = connection;
        mInterface = interfaze;
    } catch (RuntimeException e) {
        updateState(DetailedState.FAILED, "establish");
        IoUtils.closeQuietly(tun);
        throw e;
    }
    Log.i(TAG, "Established by " + config.user + " on " + mInterface);
    // Fill more values.
    config.user = mPackage;
    config.interfaze = mInterface;
    // Override DNS servers and show the notification.
    final long token = Binder.clearCallingIdentity();
    try {
        mCallback.override(config.dnsServers, config.searchDomains);
        showNotification(config, label, bitmap);
    } finally {
        Binder.restoreCallingIdentity(token);
    }
    // TODO: ensure that contract class eventually marks as connected
    updateState(DetailedState.AUTHENTICATING, "establish");
    return tun;
}
Also used : Canvas(android.graphics.Canvas) ApplicationInfo(android.content.pm.ApplicationInfo) Drawable(android.graphics.drawable.Drawable) ServiceConnection(android.content.ServiceConnection) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) RemoteException(android.os.RemoteException) ResolveInfo(android.content.pm.ResolveInfo) Bitmap(android.graphics.Bitmap) PackageManager(android.content.pm.PackageManager) ParcelFileDescriptor(android.os.ParcelFileDescriptor)

Example 38 with ResolveInfo

use of android.content.pm.ResolveInfo in project android_frameworks_base by ParanoidAndroid.

the class ActivityStack method startActivityMayWait.

final int startActivityMayWait(IApplicationThread caller, int callingUid, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, String profileFile, ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config, Bundle options, int userId) {
    // Refuse possible leaked file descriptors
    if (intent != null && intent.hasFileDescriptors()) {
        throw new IllegalArgumentException("File descriptors passed in Intent");
    }
    boolean componentSpecified = intent.getComponent() != null;
    // Don't modify the client's object!
    intent = new Intent(intent);
    // Collect information about the target of the Intent.
    ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profileFile, profileFd, userId);
    synchronized (mService) {
        int callingPid;
        if (callingUid >= 0) {
            callingPid = -1;
        } else if (caller == null) {
            callingPid = Binder.getCallingPid();
            callingUid = Binder.getCallingUid();
        } else {
            callingPid = callingUid = -1;
        }
        mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
        if (DEBUG_CONFIGURATION)
            Slog.v(TAG, "Starting activity when config will change = " + mConfigWillChange);
        final long origId = Binder.clearCallingIdentity();
        if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
            // have another, different heavy-weight process running.
            if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
                if (mService.mHeavyWeightProcess != null && (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid || !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
                    int realCallingPid = callingPid;
                    int realCallingUid = callingUid;
                    if (caller != null) {
                        ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
                        if (callerApp != null) {
                            realCallingPid = callerApp.pid;
                            realCallingUid = callerApp.info.uid;
                        } else {
                            Slog.w(TAG, "Unable to find app for caller " + caller + " (pid=" + realCallingPid + ") when starting: " + intent.toString());
                            ActivityOptions.abort(options);
                            return ActivityManager.START_PERMISSION_DENIED;
                        }
                    }
                    IIntentSender target = mService.getIntentSenderLocked(ActivityManager.INTENT_SENDER_ACTIVITY, "android", realCallingUid, userId, null, null, 0, new Intent[] { intent }, new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT, null);
                    Intent newIntent = new Intent();
                    if (requestCode >= 0) {
                        // Caller is requesting a result.
                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
                    }
                    newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT, new IntentSender(target));
                    if (mService.mHeavyWeightProcess.activities.size() > 0) {
                        ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, hist.packageName);
                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, hist.task.taskId);
                    }
                    newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP, aInfo.packageName);
                    newIntent.setFlags(intent.getFlags());
                    newIntent.setClassName("android", HeavyWeightSwitcherActivity.class.getName());
                    intent = newIntent;
                    resolvedType = null;
                    caller = null;
                    callingUid = Binder.getCallingUid();
                    callingPid = Binder.getCallingPid();
                    componentSpecified = true;
                    try {
                        ResolveInfo rInfo = AppGlobals.getPackageManager().resolveIntent(intent, null, PackageManager.MATCH_DEFAULT_ONLY | ActivityManagerService.STOCK_PM_FLAGS, userId);
                        aInfo = rInfo != null ? rInfo.activityInfo : null;
                        aInfo = mService.getActivityInfoForUser(aInfo, userId);
                    } catch (RemoteException e) {
                        aInfo = null;
                    }
                }
            }
        }
        int res = startActivityLocked(caller, intent, resolvedType, aInfo, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, startFlags, options, componentSpecified, null);
        if (mConfigWillChange && mMainStack) {
            // If the caller also wants to switch to a new configuration,
            // do so now.  This allows a clean switch, as we are waiting
            // for the current activity to pause (so we will not destroy
            // it), and have not yet started the next activity.
            mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, "updateConfiguration()");
            mConfigWillChange = false;
            if (DEBUG_CONFIGURATION)
                Slog.v(TAG, "Updating to new configuration after starting activity.");
            mService.updateConfigurationLocked(config, null, false, false);
        }
        Binder.restoreCallingIdentity(origId);
        if (outResult != null) {
            outResult.result = res;
            if (res == ActivityManager.START_SUCCESS) {
                mWaitingActivityLaunched.add(outResult);
                do {
                    try {
                        mService.wait();
                    } catch (InterruptedException e) {
                    }
                } while (!outResult.timeout && outResult.who == null);
            } else if (res == ActivityManager.START_TASK_TO_FRONT) {
                ActivityRecord r = this.topRunningActivityLocked(null);
                if (r.nowVisible) {
                    outResult.timeout = false;
                    outResult.who = new ComponentName(r.info.packageName, r.info.name);
                    outResult.totalTime = 0;
                    outResult.thisTime = 0;
                } else {
                    outResult.thisTime = SystemClock.uptimeMillis();
                    mWaitingActivityVisible.add(outResult);
                    do {
                        try {
                            mService.wait();
                        } catch (InterruptedException e) {
                        }
                    } while (!outResult.timeout && outResult.who == null);
                }
            }
        }
        return res;
    }
}
Also used : ActivityInfo(android.content.pm.ActivityInfo) HeavyWeightSwitcherActivity(com.android.internal.app.HeavyWeightSwitcherActivity) PendingIntent(android.app.PendingIntent) Intent(android.content.Intent) IIntentSender(android.content.IIntentSender) ResolveInfo(android.content.pm.ResolveInfo) ComponentName(android.content.ComponentName) IIntentSender(android.content.IIntentSender) IntentSender(android.content.IntentSender) RemoteException(android.os.RemoteException)

Example 39 with ResolveInfo

use of android.content.pm.ResolveInfo in project android_frameworks_base by ParanoidAndroid.

the class BroadcastQueue method processNextBroadcast.

final void processNextBroadcast(boolean fromMsg) {
    synchronized (mService) {
        BroadcastRecord r;
        if (DEBUG_BROADCAST)
            Slog.v(TAG, "processNextBroadcast [" + mQueueName + "]: " + mParallelBroadcasts.size() + " broadcasts, " + mOrderedBroadcasts.size() + " ordered broadcasts");
        mService.updateCpuStats();
        if (fromMsg) {
            mBroadcastsScheduled = false;
        }
        // First, deliver any non-serialized broadcasts right away.
        while (mParallelBroadcasts.size() > 0) {
            r = mParallelBroadcasts.remove(0);
            r.dispatchTime = SystemClock.uptimeMillis();
            r.dispatchClockTime = System.currentTimeMillis();
            final int N = r.receivers.size();
            if (DEBUG_BROADCAST_LIGHT)
                Slog.v(TAG, "Processing parallel broadcast [" + mQueueName + "] " + r);
            for (int i = 0; i < N; i++) {
                Object target = r.receivers.get(i);
                if (DEBUG_BROADCAST)
                    Slog.v(TAG, "Delivering non-ordered on [" + mQueueName + "] to registered " + target + ": " + r);
                deliverToRegisteredReceiverLocked(r, (BroadcastFilter) target, false);
            }
            addBroadcastToHistoryLocked(r);
            if (DEBUG_BROADCAST_LIGHT)
                Slog.v(TAG, "Done with parallel broadcast [" + mQueueName + "] " + r);
        }
        // check that the process we're waiting for still exists.
        if (mPendingBroadcast != null) {
            if (DEBUG_BROADCAST_LIGHT) {
                Slog.v(TAG, "processNextBroadcast [" + mQueueName + "]: waiting for " + mPendingBroadcast.curApp);
            }
            boolean isDead;
            synchronized (mService.mPidsSelfLocked) {
                isDead = (mService.mPidsSelfLocked.get(mPendingBroadcast.curApp.pid) == null);
            }
            if (!isDead) {
                // It's still alive, so keep waiting
                return;
            } else {
                Slog.w(TAG, "pending app  [" + mQueueName + "]" + mPendingBroadcast.curApp + " died before responding to broadcast");
                mPendingBroadcast.state = BroadcastRecord.IDLE;
                mPendingBroadcast.nextReceiver = mPendingBroadcastRecvIndex;
                mPendingBroadcast = null;
            }
        }
        boolean looped = false;
        do {
            if (mOrderedBroadcasts.size() == 0) {
                // No more broadcasts pending, so all done!
                mService.scheduleAppGcsLocked();
                if (looped) {
                    // If we had finished the last ordered broadcast, then
                    // make sure all processes have correct oom and sched
                    // adjustments.
                    mService.updateOomAdjLocked();
                }
                return;
            }
            r = mOrderedBroadcasts.get(0);
            boolean forceReceive = false;
            // Ensure that even if something goes awry with the timeout
            // detection, we catch "hung" broadcasts here, discard them,
            // and continue to make progress.
            //
            // This is only done if the system is ready so that PRE_BOOT_COMPLETED
            // receivers don't get executed with timeouts. They're intended for
            // one time heavy lifting after system upgrades and can take
            // significant amounts of time.
            int numReceivers = (r.receivers != null) ? r.receivers.size() : 0;
            if (mService.mProcessesReady && r.dispatchTime > 0) {
                long now = SystemClock.uptimeMillis();
                if ((numReceivers > 0) && (now > r.dispatchTime + (2 * mTimeoutPeriod * numReceivers))) {
                    Slog.w(TAG, "Hung broadcast [" + mQueueName + "] discarded after timeout failure:" + " now=" + now + " dispatchTime=" + r.dispatchTime + " startTime=" + r.receiverTime + " intent=" + r.intent + " numReceivers=" + numReceivers + " nextReceiver=" + r.nextReceiver + " state=" + r.state);
                    // forcibly finish this broadcast
                    broadcastTimeoutLocked(false);
                    forceReceive = true;
                    r.state = BroadcastRecord.IDLE;
                }
            }
            if (r.state != BroadcastRecord.IDLE) {
                if (DEBUG_BROADCAST)
                    Slog.d(TAG, "processNextBroadcast(" + mQueueName + ") called when not idle (state=" + r.state + ")");
                return;
            }
            if (r.receivers == null || r.nextReceiver >= numReceivers || r.resultAbort || forceReceive) {
                // result if requested...
                if (r.resultTo != null) {
                    try {
                        if (DEBUG_BROADCAST) {
                            int seq = r.intent.getIntExtra("seq", -1);
                            Slog.i(TAG, "Finishing broadcast [" + mQueueName + "] " + r.intent.getAction() + " seq=" + seq + " app=" + r.callerApp);
                        }
                        performReceiveLocked(r.callerApp, r.resultTo, new Intent(r.intent), r.resultCode, r.resultData, r.resultExtras, false, false, r.userId);
                        // Set this to null so that the reference
                        // (local and remote) isnt kept in the mBroadcastHistory.
                        r.resultTo = null;
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Failure [" + mQueueName + "] sending broadcast result of " + r.intent, e);
                    }
                }
                if (DEBUG_BROADCAST)
                    Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG");
                cancelBroadcastTimeoutLocked();
                if (DEBUG_BROADCAST_LIGHT)
                    Slog.v(TAG, "Finished with ordered broadcast " + r);
                // ... and on to the next...
                addBroadcastToHistoryLocked(r);
                mOrderedBroadcasts.remove(0);
                r = null;
                looped = true;
                continue;
            }
        } while (r == null);
        // Get the next receiver...
        int recIdx = r.nextReceiver++;
        // Keep track of when this receiver started, and make sure there
        // is a timeout message pending to kill it if need be.
        r.receiverTime = SystemClock.uptimeMillis();
        if (recIdx == 0) {
            r.dispatchTime = r.receiverTime;
            r.dispatchClockTime = System.currentTimeMillis();
            if (DEBUG_BROADCAST_LIGHT)
                Slog.v(TAG, "Processing ordered broadcast [" + mQueueName + "] " + r);
        }
        if (!mPendingBroadcastTimeoutMessage) {
            long timeoutTime = r.receiverTime + mTimeoutPeriod;
            if (DEBUG_BROADCAST)
                Slog.v(TAG, "Submitting BROADCAST_TIMEOUT_MSG [" + mQueueName + "] for " + r + " at " + timeoutTime);
            setBroadcastTimeoutLocked(timeoutTime);
        }
        Object nextReceiver = r.receivers.get(recIdx);
        if (nextReceiver instanceof BroadcastFilter) {
            // Simple case: this is a registered receiver who gets
            // a direct call.
            BroadcastFilter filter = (BroadcastFilter) nextReceiver;
            if (DEBUG_BROADCAST)
                Slog.v(TAG, "Delivering ordered [" + mQueueName + "] to registered " + filter + ": " + r);
            deliverToRegisteredReceiverLocked(r, filter, r.ordered);
            if (r.receiver == null || !r.ordered) {
                // process the next one.
                if (DEBUG_BROADCAST)
                    Slog.v(TAG, "Quick finishing [" + mQueueName + "]: ordered=" + r.ordered + " receiver=" + r.receiver);
                r.state = BroadcastRecord.IDLE;
                scheduleBroadcastsLocked();
            }
            return;
        }
        // Hard case: need to instantiate the receiver, possibly
        // starting its application process to host it.
        ResolveInfo info = (ResolveInfo) nextReceiver;
        ComponentName component = new ComponentName(info.activityInfo.applicationInfo.packageName, info.activityInfo.name);
        boolean skip = false;
        int perm = mService.checkComponentPermission(info.activityInfo.permission, r.callingPid, r.callingUid, info.activityInfo.applicationInfo.uid, info.activityInfo.exported);
        if (perm != PackageManager.PERMISSION_GRANTED) {
            if (!info.activityInfo.exported) {
                Slog.w(TAG, "Permission Denial: broadcasting " + r.intent.toString() + " from " + r.callerPackage + " (pid=" + r.callingPid + ", uid=" + r.callingUid + ")" + " is not exported from uid " + info.activityInfo.applicationInfo.uid + " due to receiver " + component.flattenToShortString());
            } else {
                Slog.w(TAG, "Permission Denial: broadcasting " + r.intent.toString() + " from " + r.callerPackage + " (pid=" + r.callingPid + ", uid=" + r.callingUid + ")" + " requires " + info.activityInfo.permission + " due to receiver " + component.flattenToShortString());
            }
            skip = true;
        }
        if (info.activityInfo.applicationInfo.uid != Process.SYSTEM_UID && r.requiredPermission != null) {
            try {
                perm = AppGlobals.getPackageManager().checkPermission(r.requiredPermission, info.activityInfo.applicationInfo.packageName);
            } catch (RemoteException e) {
                perm = PackageManager.PERMISSION_DENIED;
            }
            if (perm != PackageManager.PERMISSION_GRANTED) {
                Slog.w(TAG, "Permission Denial: receiving " + r.intent + " to " + component.flattenToShortString() + " requires " + r.requiredPermission + " due to sender " + r.callerPackage + " (uid " + r.callingUid + ")");
                skip = true;
            }
        }
        if (r.appOp != AppOpsManager.OP_NONE) {
            int mode = mService.mAppOpsService.checkOperation(r.appOp, info.activityInfo.applicationInfo.uid, info.activityInfo.packageName);
            if (mode != AppOpsManager.MODE_ALLOWED) {
                if (DEBUG_BROADCAST)
                    Slog.v(TAG, "App op " + r.appOp + " not allowed for broadcast to uid " + info.activityInfo.applicationInfo.uid + " pkg " + info.activityInfo.packageName);
                skip = true;
            }
        }
        boolean isSingleton = false;
        try {
            isSingleton = mService.isSingleton(info.activityInfo.processName, info.activityInfo.applicationInfo, info.activityInfo.name, info.activityInfo.flags);
        } catch (SecurityException e) {
            Slog.w(TAG, e.getMessage());
            skip = true;
        }
        if ((info.activityInfo.flags & ActivityInfo.FLAG_SINGLE_USER) != 0) {
            if (ActivityManager.checkUidPermission(android.Manifest.permission.INTERACT_ACROSS_USERS, info.activityInfo.applicationInfo.uid) != PackageManager.PERMISSION_GRANTED) {
                Slog.w(TAG, "Permission Denial: Receiver " + component.flattenToShortString() + " requests FLAG_SINGLE_USER, but app does not hold " + android.Manifest.permission.INTERACT_ACROSS_USERS);
                skip = true;
            }
        }
        if (r.curApp != null && r.curApp.crashing) {
            // If the target process is crashing, just skip it.
            if (DEBUG_BROADCAST)
                Slog.v(TAG, "Skipping deliver ordered [" + mQueueName + "] " + r + " to " + r.curApp + ": process crashing");
            skip = true;
        }
        if (skip) {
            if (DEBUG_BROADCAST)
                Slog.v(TAG, "Skipping delivery of ordered [" + mQueueName + "] " + r + " for whatever reason");
            r.receiver = null;
            r.curFilter = null;
            r.state = BroadcastRecord.IDLE;
            scheduleBroadcastsLocked();
            return;
        }
        r.state = BroadcastRecord.APP_RECEIVE;
        String targetProcess = info.activityInfo.processName;
        r.curComponent = component;
        if (r.callingUid != Process.SYSTEM_UID && isSingleton) {
            info.activityInfo = mService.getActivityInfoForUser(info.activityInfo, 0);
        }
        r.curReceiver = info.activityInfo;
        if (DEBUG_MU && r.callingUid > UserHandle.PER_USER_RANGE) {
            Slog.v(TAG_MU, "Updated broadcast record activity info for secondary user, " + info.activityInfo + ", callingUid = " + r.callingUid + ", uid = " + info.activityInfo.applicationInfo.uid);
        }
        // Broadcast is being executed, its package can't be stopped.
        try {
            AppGlobals.getPackageManager().setPackageStoppedState(r.curComponent.getPackageName(), false, UserHandle.getUserId(r.callingUid));
        } catch (RemoteException e) {
        } catch (IllegalArgumentException e) {
            Slog.w(TAG, "Failed trying to unstop package " + r.curComponent.getPackageName() + ": " + e);
        }
        // Is this receiver's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(targetProcess, info.activityInfo.applicationInfo.uid);
        if (app != null && app.thread != null) {
            try {
                app.addPackage(info.activityInfo.packageName);
                processCurBroadcastLocked(r, app);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when sending broadcast to " + r.curComponent, e);
            } catch (RuntimeException e) {
                Log.wtf(TAG, "Failed sending broadcast to " + r.curComponent + " with " + r.intent, e);
                // If some unexpected exception happened, just skip
                // this broadcast.  At this point we are not in the call
                // from a client, so throwing an exception out from here
                // will crash the entire system instead of just whoever
                // sent the broadcast.
                logBroadcastReceiverDiscardLocked(r);
                finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true);
                scheduleBroadcastsLocked();
                // We need to reset the state if we failed to start the receiver.
                r.state = BroadcastRecord.IDLE;
                return;
            }
        // If a dead object exception was thrown -- fall through to
        // restart the application.
        }
        // Not running -- get it started, to be executed when the app comes up.
        if (DEBUG_BROADCAST)
            Slog.v(TAG, "Need to start app [" + mQueueName + "] " + targetProcess + " for broadcast " + r);
        if ((r.curApp = mService.startProcessLocked(targetProcess, info.activityInfo.applicationInfo, true, r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND, "broadcast", r.curComponent, (r.intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false)) == null) {
            // Ah, this recipient is unavailable.  Finish it if necessary,
            // and mark the broadcast record as ready for the next.
            Slog.w(TAG, "Unable to launch app " + info.activityInfo.applicationInfo.packageName + "/" + info.activityInfo.applicationInfo.uid + " for broadcast " + r.intent + ": process is bad");
            logBroadcastReceiverDiscardLocked(r);
            finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, true);
            scheduleBroadcastsLocked();
            r.state = BroadcastRecord.IDLE;
            return;
        }
        mPendingBroadcast = r;
        mPendingBroadcastRecvIndex = recIdx;
    }
}
Also used : Intent(android.content.Intent) ResolveInfo(android.content.pm.ResolveInfo) ComponentName(android.content.ComponentName) RemoteException(android.os.RemoteException)

Example 40 with ResolveInfo

use of android.content.pm.ResolveInfo in project android_frameworks_base by ParanoidAndroid.

the class BroadcastQueue method logBroadcastReceiverDiscardLocked.

final void logBroadcastReceiverDiscardLocked(BroadcastRecord r) {
    if (r.nextReceiver > 0) {
        Object curReceiver = r.receivers.get(r.nextReceiver - 1);
        if (curReceiver instanceof BroadcastFilter) {
            BroadcastFilter bf = (BroadcastFilter) curReceiver;
            EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_FILTER, bf.owningUserId, System.identityHashCode(r), r.intent.getAction(), r.nextReceiver - 1, System.identityHashCode(bf));
        } else {
            ResolveInfo ri = (ResolveInfo) curReceiver;
            EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP, UserHandle.getUserId(ri.activityInfo.applicationInfo.uid), System.identityHashCode(r), r.intent.getAction(), r.nextReceiver - 1, ri.toString());
        }
    } else {
        Slog.w(TAG, "Discarding broadcast before first receiver is invoked: " + r);
        EventLog.writeEvent(EventLogTags.AM_BROADCAST_DISCARD_APP, -1, System.identityHashCode(r), r.intent.getAction(), r.nextReceiver, "NONE");
    }
}
Also used : ResolveInfo(android.content.pm.ResolveInfo)

Aggregations

ResolveInfo (android.content.pm.ResolveInfo)2316 Intent (android.content.Intent)1476 PackageManager (android.content.pm.PackageManager)875 ComponentName (android.content.ComponentName)637 ArrayList (java.util.ArrayList)515 ActivityInfo (android.content.pm.ActivityInfo)360 Test (org.junit.Test)282 ServiceInfo (android.content.pm.ServiceInfo)203 PendingIntent (android.app.PendingIntent)183 ApplicationInfo (android.content.pm.ApplicationInfo)178 RemoteException (android.os.RemoteException)170 Context (android.content.Context)101 Bundle (android.os.Bundle)97 NameNotFoundException (android.content.pm.PackageManager.NameNotFoundException)81 IOException (java.io.IOException)78 PackageInfo (android.content.pm.PackageInfo)68 HashSet (java.util.HashSet)65 HashMap (java.util.HashMap)63 ActivityNotFoundException (android.content.ActivityNotFoundException)59 EphemeralResolveInfo (android.content.pm.EphemeralResolveInfo)58