Search in sources :

Example 36 with ServiceState

use of com.android.internal.app.procstats.ServiceState in project platform_frameworks_base by android.

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 37 with ServiceState

use of com.android.internal.app.procstats.ServiceState in project android_frameworks_base by DirtyUnicorns.

the class ActiveServices method bumpServiceExecutingLocked.

private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) {
    if (DEBUG_SERVICE)
        Slog.v(TAG_SERVICE, ">>> EXECUTING " + why + " of " + r + " in app " + r.app);
    else if (DEBUG_SERVICE_EXECUTING)
        Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING " + why + " of " + r.shortName);
    long now = SystemClock.uptimeMillis();
    if (r.executeNesting == 0) {
        r.executeFg = fg;
        ServiceState stracker = r.getTracker();
        if (stracker != null) {
            stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
        }
        if (r.app != null) {
            r.app.executingServices.add(r);
            r.app.execServicesFg |= fg;
            if (r.app.executingServices.size() == 1) {
                scheduleServiceTimeoutLocked(r.app);
            }
        }
    } else if (r.app != null && fg && !r.app.execServicesFg) {
        r.app.execServicesFg = true;
        scheduleServiceTimeoutLocked(r.app);
    }
    r.executeFg |= fg;
    r.executeNesting++;
    r.executingStart = now;
}
Also used : ServiceState(com.android.internal.app.procstats.ServiceState)

Example 38 with ServiceState

use of com.android.internal.app.procstats.ServiceState in project android_frameworks_base by DirtyUnicorns.

the class ActiveServices method startServiceInnerLocked.

ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r, boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
    ServiceState stracker = r.getTracker();
    if (stracker != null) {
        stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
    }
    r.callStart = false;
    synchronized (r.stats.getBatteryStats()) {
        r.stats.startRunningLocked();
    }
    String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
    if (error != null) {
        return new ComponentName("!!", error);
    }
    if (r.startRequested && addToStarting) {
        boolean first = smap.mStartingBackground.size() == 0;
        smap.mStartingBackground.add(r);
        r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;
        if (DEBUG_DELAYED_SERVICE) {
            RuntimeException here = new RuntimeException("here");
            here.fillInStackTrace();
            Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);
        } else if (DEBUG_DELAYED_STARTS) {
            Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);
        }
        if (first) {
            smap.rescheduleDelayedStarts();
        }
    } else if (callerFg) {
        smap.ensureNotStartingBackground(r);
    }
    return r.name;
}
Also used : ServiceState(com.android.internal.app.procstats.ServiceState) ComponentName(android.content.ComponentName)

Example 39 with ServiceState

use of com.android.internal.app.procstats.ServiceState in project android_frameworks_base by DirtyUnicorns.

the class ProcessStatsService method setMemFactorLocked.

public boolean setMemFactorLocked(int memFactor, boolean screenOn, long now) {
    mMemFactorLowered = memFactor < mLastMemOnlyState;
    mLastMemOnlyState = memFactor;
    if (screenOn) {
        memFactor += ProcessStats.ADJ_SCREEN_ON;
    }
    if (memFactor != mProcessStats.mMemFactor) {
        if (mProcessStats.mMemFactor != ProcessStats.STATE_NOTHING) {
            mProcessStats.mMemFactorDurations[mProcessStats.mMemFactor] += now - mProcessStats.mStartTime;
        }
        mProcessStats.mMemFactor = memFactor;
        mProcessStats.mStartTime = now;
        final ArrayMap<String, SparseArray<SparseArray<ProcessStats.PackageState>>> pmap = mProcessStats.mPackages.getMap();
        for (int ipkg = pmap.size() - 1; ipkg >= 0; ipkg--) {
            final SparseArray<SparseArray<ProcessStats.PackageState>> uids = pmap.valueAt(ipkg);
            for (int iuid = uids.size() - 1; iuid >= 0; iuid--) {
                final SparseArray<ProcessStats.PackageState> vers = uids.valueAt(iuid);
                for (int iver = vers.size() - 1; iver >= 0; iver--) {
                    final ProcessStats.PackageState pkg = vers.valueAt(iver);
                    final ArrayMap<String, ServiceState> services = pkg.mServices;
                    for (int isvc = services.size() - 1; isvc >= 0; isvc--) {
                        final ServiceState service = services.valueAt(isvc);
                        service.setMemFactor(memFactor, now);
                    }
                }
            }
        }
        return true;
    }
    return false;
}
Also used : SparseArray(android.util.SparseArray) IProcessStats(com.android.internal.app.procstats.IProcessStats) ProcessStats(com.android.internal.app.procstats.ProcessStats) ServiceState(com.android.internal.app.procstats.ServiceState)

Example 40 with ServiceState

use of com.android.internal.app.procstats.ServiceState in project android_frameworks_base by DirtyUnicorns.

the class ProcessStats method resetSafely.

public void resetSafely() {
    if (DEBUG)
        Slog.d(TAG, "Safely resetting state of " + mTimePeriodStartClockStr);
    resetCommon();
    // First initialize use count of all common processes.
    final long now = SystemClock.uptimeMillis();
    final ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
    for (int ip = procMap.size() - 1; ip >= 0; ip--) {
        final SparseArray<ProcessState> uids = procMap.valueAt(ip);
        for (int iu = uids.size() - 1; iu >= 0; iu--) {
            uids.valueAt(iu).tmpNumInUse = 0;
        }
    }
    // Next reset or prune all per-package processes, and for the ones that are reset
    // track this back to the common processes.
    final ArrayMap<String, SparseArray<SparseArray<PackageState>>> pkgMap = mPackages.getMap();
    for (int ip = pkgMap.size() - 1; ip >= 0; ip--) {
        final SparseArray<SparseArray<PackageState>> uids = pkgMap.valueAt(ip);
        for (int iu = uids.size() - 1; iu >= 0; iu--) {
            final SparseArray<PackageState> vpkgs = uids.valueAt(iu);
            for (int iv = vpkgs.size() - 1; iv >= 0; iv--) {
                final PackageState pkgState = vpkgs.valueAt(iv);
                for (int iproc = pkgState.mProcesses.size() - 1; iproc >= 0; iproc--) {
                    final ProcessState ps = pkgState.mProcesses.valueAt(iproc);
                    if (ps.isInUse()) {
                        ps.resetSafely(now);
                        ps.getCommonProcess().tmpNumInUse++;
                        ps.getCommonProcess().tmpFoundSubProc = ps;
                    } else {
                        pkgState.mProcesses.valueAt(iproc).makeDead();
                        pkgState.mProcesses.removeAt(iproc);
                    }
                }
                for (int isvc = pkgState.mServices.size() - 1; isvc >= 0; isvc--) {
                    final ServiceState ss = pkgState.mServices.valueAt(isvc);
                    if (ss.isInUse()) {
                        ss.resetSafely(now);
                    } else {
                        pkgState.mServices.removeAt(isvc);
                    }
                }
                if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0) {
                    vpkgs.removeAt(iv);
                }
            }
            if (vpkgs.size() <= 0) {
                uids.removeAt(iu);
            }
        }
        if (uids.size() <= 0) {
            pkgMap.removeAt(ip);
        }
    }
    // Finally prune out any common processes that are no longer in use.
    for (int ip = procMap.size() - 1; ip >= 0; ip--) {
        final SparseArray<ProcessState> uids = procMap.valueAt(ip);
        for (int iu = uids.size() - 1; iu >= 0; iu--) {
            ProcessState ps = uids.valueAt(iu);
            if (ps.isInUse() || ps.tmpNumInUse > 0) {
                // using it).
                if (!ps.isActive() && ps.isMultiPackage() && ps.tmpNumInUse == 1) {
                    // Here we go...
                    ps = ps.tmpFoundSubProc;
                    ps.makeStandalone();
                    uids.setValueAt(iu, ps);
                } else {
                    ps.resetSafely(now);
                }
            } else {
                ps.makeDead();
                uids.removeAt(iu);
            }
        }
        if (uids.size() <= 0) {
            procMap.removeAt(ip);
        }
    }
    mStartTime = now;
    if (DEBUG)
        Slog.d(TAG, "State reset; now " + mTimePeriodStartClockStr);
}
Also used : ProcessState(com.android.internal.app.procstats.ProcessState) SparseArray(android.util.SparseArray) ServiceState(com.android.internal.app.procstats.ServiceState)

Aggregations

ServiceState (com.android.internal.app.procstats.ServiceState)61 ProcessState (com.android.internal.app.procstats.ProcessState)41 SparseArray (android.util.SparseArray)31 IProcessStats (com.android.internal.app.procstats.IProcessStats)6 ProcessStats (com.android.internal.app.procstats.ProcessStats)6 ArrayList (java.util.ArrayList)6 PendingIntent (android.app.PendingIntent)5 ComponentName (android.content.ComponentName)5 Intent (android.content.Intent)5 Bundle (android.os.Bundle)5 DeadObjectException (android.os.DeadObjectException)5 IBinder (android.os.IBinder)5 RemoteCallback (android.os.RemoteCallback)5 RemoteException (android.os.RemoteException)5 TransactionTooLargeException (android.os.TransactionTooLargeException)5 UserHandle (android.os.UserHandle)5 IOException (java.io.IOException)5 ProcessMap (com.android.internal.app.ProcessMap)1