Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fee756ff authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Implement issue #16330060: Inform ActivityManager about WebView...

...state changes.

Add a new API to tell the activity manager about a new dependency
one process has on another package.  Start using it already for
when apps is Context.createPackageContext() to load code from another
app.

Also do some work on getting the monitoring of proc/uid states
in shape so it can be used by unundled code, along with an
AppImportanceMonitor class for doing so.

Some small fixes and additions to VoiceInteractionService.

Improve handling of unaccounted/overcounted battery use so that
they aren't shown to the user unless they are significant.

Change-Id: I22dd79a73f4e70103d3f8964494aebc8a31f971c
parent 2883ba69
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -996,6 +996,7 @@ package android {
    field public static final int ratingBarStyleIndicator = 16843280; // 0x1010210
    field public static final int ratingBarStyleSmall = 16842877; // 0x101007d
    field public static final int readPermission = 16842759; // 0x1010007
    field public static final int recognitionService = 16843935; // 0x101049f
    field public static final int relinquishTaskIdentity = 16843896; // 0x1010478
    field public static final int repeatCount = 16843199; // 0x10101bf
    field public static final int repeatMode = 16843200; // 0x10101c0
@@ -3613,6 +3614,7 @@ package android.app {
    field public static final int IMPORTANCE_BACKGROUND = 400; // 0x190
    field public static final int IMPORTANCE_EMPTY = 500; // 0x1f4
    field public static final int IMPORTANCE_FOREGROUND = 100; // 0x64
    field public static final int IMPORTANCE_GONE = 1000; // 0x3e8
    field public static final int IMPORTANCE_PERCEPTIBLE = 130; // 0x82
    field public static final int IMPORTANCE_SERVICE = 300; // 0x12c
    field public static final int IMPORTANCE_VISIBLE = 200; // 0xc8
@@ -26990,7 +26992,9 @@ package android.service.voice {
  public class VoiceInteractionService extends android.app.Service {
    ctor public VoiceInteractionService();
    method public final android.service.voice.AlwaysOnHotwordDetector getAlwaysOnHotwordDetector(java.lang.String, java.lang.String, android.service.voice.AlwaysOnHotwordDetector.Callback);
    method public static boolean isActiveService(android.content.Context, android.content.ComponentName);
    method public android.os.IBinder onBind(android.content.Intent);
    method public void onReady();
    method public void startSession(android.os.Bundle);
    field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
    field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction";
+23 −1
Original line number Diff line number Diff line
@@ -1820,6 +1820,28 @@ public class ActivityManager {
         */
        public static final int IMPORTANCE_EMPTY = 500;

        /**
         * Constant for {@link #importance}: this process does not exist.
         */
        public static final int IMPORTANCE_GONE = 1000;

        /** @hide */
        public static int procStateToImportance(int procState) {
            if (procState >= ActivityManager.PROCESS_STATE_HOME) {
                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
            } else if (procState >= ActivityManager.PROCESS_STATE_SERVICE) {
                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
            } else if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
            } else if (procState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {
                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
            } else if (procState >= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {
                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
            } else {
                return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
            }
        }

        /**
         * The relative importance level that the system places on this
         * process.  May be one of {@link #IMPORTANCE_FOREGROUND},
+22 −3
Original line number Diff line number Diff line
@@ -1466,6 +1466,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            return true;
        }

        case ADD_PACKAGE_DEPENDENCY_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            String packageName = data.readString();
            addPackageDependency(packageName);
            reply.writeNoException();
            return true;
        }

        case KILL_APPLICATION_WITH_APPID_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            String pkg = data.readString();
@@ -4051,6 +4059,17 @@ class ActivityManagerProxy implements IActivityManager
        data.recycle();
    }

    public void addPackageDependency(String packageName) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeString(packageName);
        mRemote.transact(ADD_PACKAGE_DEPENDENCY_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }

    public void killApplicationWithAppId(String pkg, int appid, String reason)
            throws RemoteException {
        Parcel data = Parcel.obtain();
+8 −5
Original line number Diff line number Diff line
@@ -1684,6 +1684,7 @@ public final class ActivityThread {
                && ai.uid != Process.SYSTEM_UID && (mBoundApplication != null
                        ? !UserHandle.isSameApp(ai.uid, mBoundApplication.appInfo.uid)
                        : true);
        boolean registerPackage = includeCode && (flags&Context.CONTEXT_REGISTER_PACKAGE) != 0;
        if ((flags&(Context.CONTEXT_INCLUDE_CODE
                |Context.CONTEXT_IGNORE_SECURITY))
                == Context.CONTEXT_INCLUDE_CODE) {
@@ -1698,12 +1699,13 @@ public final class ActivityThread {
                throw new SecurityException(msg);
            }
        }
        return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode);
        return getPackageInfo(ai, compatInfo, null, securityViolation, includeCode,
                registerPackage);
    }

    public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
            CompatibilityInfo compatInfo) {
        return getPackageInfo(ai, compatInfo, null, false, true);
        return getPackageInfo(ai, compatInfo, null, false, true, false);
    }

    public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
@@ -1719,7 +1721,8 @@ public final class ActivityThread {
    }

    private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
            ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
            ClassLoader baseLoader, boolean securityViolation, boolean includeCode,
            boolean registerPackage) {
        synchronized (mResourcesManager) {
            WeakReference<LoadedApk> ref;
            if (includeCode) {
@@ -1738,7 +1741,7 @@ public final class ActivityThread {
                packageInfo =
                    new LoadedApk(this, aInfo, compatInfo, baseLoader,
                            securityViolation, includeCode &&
                            (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
                            (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
                if (includeCode) {
                    mPackages.put(aInfo.packageName,
                            new WeakReference<LoadedApk>(packageInfo));
@@ -4394,7 +4397,7 @@ public final class ActivityThread {
            instrApp.dataDir = ii.dataDir;
            instrApp.nativeLibraryDir = ii.nativeLibraryDir;
            LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true);
                    appContext.getClassLoader(), false, true, false);
            ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

            try {
+150 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.app;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.util.SparseArray;
import android.util.SparseIntArray;

import java.util.List;

/**
 * Helper for monitoring the current importance of applications.
 * @hide
 */
public class AppImportanceMonitor {
    final Context mContext;

    final SparseArray<AppEntry> mApps = new SparseArray<>();

    static class AppEntry {
        final int uid;
        final SparseArray<Integer> procs = new SparseArray<>(1);
        int importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;

        AppEntry(int _uid) {
            uid = _uid;
        }
    }

    final IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
        @Override
        public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
        }

        @Override
        public void onProcessStateChanged(int pid, int uid, int procState) {
            synchronized (mApps) {
                updateImportanceLocked(pid, uid,
                        ActivityManager.RunningAppProcessInfo.procStateToImportance(procState),
                        true);
            }
        }

        @Override
        public void onProcessDied(int pid, int uid) {
            synchronized (mApps) {
                updateImportanceLocked(pid, uid,
                        ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE, true);
            }
        }
    };

    static final int MSG_UPDATE = 1;

    final Handler mHandler;

    public AppImportanceMonitor(Context context, Looper looper) {
        mContext = context;
        mHandler = new Handler(looper) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_UPDATE:
                        onImportanceChanged(msg.arg1, msg.arg2&0xffff, msg.arg2>>16);
                        break;
                    default:
                        super.handleMessage(msg);
                }
            }
        };
        ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        try {
            ActivityManagerNative.getDefault().registerProcessObserver(mProcessObserver);
        } catch (RemoteException e) {
        }
        List<ActivityManager.RunningAppProcessInfo> apps = am.getRunningAppProcesses();
        if (apps != null) {
            for (int i=0; i<apps.size(); i++) {
                ActivityManager.RunningAppProcessInfo app = apps.get(i);
                updateImportanceLocked(app.uid, app.pid, app.importance, false);
            }
        }
    }

    public int getImportance(int uid) {
        AppEntry ent = mApps.get(uid);
        if (ent == null) {
            return ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
        }
        return ent.importance;
    }

    /**
     * Report when an app's importance changed. Called on looper given to constructor.
     */
    public void onImportanceChanged(int uid, int importance, int oldImportance) {
    }

    void updateImportanceLocked(int uid, int pid, int importance, boolean repChange) {
        AppEntry ent = mApps.get(uid);
        if (ent == null) {
            ent = new AppEntry(uid);
            mApps.put(uid, ent);
        }
        if (importance >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) {
            ent.procs.remove(pid);
        } else {
            ent.procs.put(pid, importance);
        }
        updateImportanceLocked(ent, repChange);
    }

    void updateImportanceLocked(AppEntry ent, boolean repChange) {
        int appImp = ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
        for (int i=0; i<ent.procs.size(); i++) {
            int procImp = ent.procs.valueAt(i);
            if (procImp < appImp) {
                appImp = procImp;
            }
        }
        if (appImp != ent.importance) {
            int impCode = appImp | (ent.importance<<16);
            ent.importance = appImp;
            if (appImp >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) {
                mApps.remove(ent.uid);
            }
            if (repChange) {
                mHandler.obtainMessage(MSG_UPDATE, ent.uid, impCode).sendToTarget();
            }
        }
    }
}
Loading