diff --git a/api/current.txt b/api/current.txt index 5a88cd43fb158..b25ae9aeead6b 100644 --- a/api/current.txt +++ b/api/current.txt @@ -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 @@ -26994,7 +26996,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"; diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index c8cab6f11b039..d2540f19c2a9b 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -1819,7 +1819,29 @@ public class ActivityManager { * actively running code. */ 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}, diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index e2b5a841c532c..fb70098d69597 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1465,7 +1465,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); 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(); @@ -1475,7 +1483,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); return true; } - + case CLOSE_SYSTEM_DIALOGS_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); String reason = data.readString(); @@ -4050,7 +4058,18 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); 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(); diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 7c8c83aa15a1c..15f3a759e26c7 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -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 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(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 { diff --git a/core/java/android/app/AppImportanceMonitor.java b/core/java/android/app/AppImportanceMonitor.java new file mode 100644 index 0000000000000..c760e1e34c53b --- /dev/null +++ b/core/java/android/app/AppImportanceMonitor.java @@ -0,0 +1,150 @@ +/* + * 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 mApps = new SparseArray<>(); + + static class AppEntry { + final int uid; + final SparseArray 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 apps = am.getRunningAppProcesses(); + if (apps != null) { + for (int i=0; i= 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= ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE) { + mApps.remove(ent.uid); + } + if (repChange) { + mHandler.obtainMessage(MSG_UPDATE, ent.uid, impCode).sendToTarget(); + } + } + } +} diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index d7c384aef6ace..cbfde14fa3616 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2097,7 +2097,7 @@ class ContextImpl extends Context { } LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), - flags, user.getIdentifier()); + flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier()); if (pi != null) { ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken, user, restricted, mDisplay, mOverrideConfiguration); diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index c6921a209e2c3..ac2916124ef3a 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -294,7 +294,9 @@ public interface IActivityManager extends IInterface { public void stopAppSwitches() throws RemoteException; public void resumeAppSwitches() throws RemoteException; - + + public void addPackageDependency(String packageName) throws RemoteException; + public void killApplicationWithAppId(String pkg, int appid, String reason) throws RemoteException; @@ -640,7 +642,7 @@ public interface IActivityManager extends IInterface { int UNBIND_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+91; int GET_UID_FOR_INTENT_SENDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+92; int HANDLE_INCOMING_USER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+93; - int ___AVAILABLE_2___ = IBinder.FIRST_CALL_TRANSACTION+94; + int ADD_PACKAGE_DEPENDENCY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+94; int KILL_APPLICATION_WITH_APPID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+95; int CLOSE_SYSTEM_DIALOGS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+96; int GET_PROCESS_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+97; diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 38614a06cfab4..24c283590188b 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -93,6 +93,7 @@ public final class LoadedApk { private final ClassLoader mBaseClassLoader; private final boolean mSecurityViolation; private final boolean mIncludeCode; + private final boolean mRegisterPackage; private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments(); Resources mResources; private ClassLoader mClassLoader; @@ -121,7 +122,7 @@ public final class LoadedApk { */ public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo, CompatibilityInfo compatInfo, ClassLoader baseLoader, - boolean securityViolation, boolean includeCode) { + boolean securityViolation, boolean includeCode, boolean registerPackage) { final int myUid = Process.myUid(); aInfo = adjustNativeLibraryPaths(aInfo); @@ -144,6 +145,7 @@ public final class LoadedApk { mBaseClassLoader = baseLoader; mSecurityViolation = securityViolation; mIncludeCode = includeCode; + mRegisterPackage = registerPackage; mDisplayAdjustments.setCompatibilityInfo(compatInfo); } @@ -189,6 +191,7 @@ public final class LoadedApk { mBaseClassLoader = null; mSecurityViolation = false; mIncludeCode = true; + mRegisterPackage = false; mClassLoader = ClassLoader.getSystemClassLoader(); mResources = Resources.getSystem(); } @@ -272,6 +275,13 @@ public final class LoadedApk { final ArrayList zipPaths = new ArrayList<>(); final ArrayList libPaths = new ArrayList<>(); + if (mRegisterPackage) { + try { + ActivityManagerNative.getDefault().addPackageDependency(mPackageName); + } catch (RemoteException e) { + } + } + zipPaths.add(mAppDir); if (mSplitAppDirs != null) { Collections.addAll(zipPaths, mSplitAppDirs); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 7d152332205c0..1dd018f3d1df2 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2475,11 +2475,11 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a {@link - * android.net.ethernet.EthernetManager} for handling management of + * android.net.EthernetManager} for handling management of * Ethernet access. * * @see #getSystemService - * @see android.net.ethernet.EthernetManager + * @see android.net.EthernetManager * * @hide */ @@ -3250,6 +3250,12 @@ public abstract class Context { */ public static final int CONTEXT_RESTRICTED = 0x00000004; + /** + * @hide Used to indicate we should tell the activity manager about the process + * loading this code. + */ + public static final int CONTEXT_REGISTER_PACKAGE = 0x40000000; + /** * Return a new Context object for the given application name. This * Context is the same as what the named application gets when it is diff --git a/core/java/android/service/voice/IVoiceInteractionService.aidl b/core/java/android/service/voice/IVoiceInteractionService.aidl index e9e2f4c81aa7c..c9915a27634d0 100644 --- a/core/java/android/service/voice/IVoiceInteractionService.aidl +++ b/core/java/android/service/voice/IVoiceInteractionService.aidl @@ -20,4 +20,5 @@ package android.service.voice; * @hide */ oneway interface IVoiceInteractionService { + void ready(); } diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java index a9b19599bb460..1f5d3276d1819 100644 --- a/core/java/android/service/voice/VoiceInteractionService.java +++ b/core/java/android/service/voice/VoiceInteractionService.java @@ -18,15 +18,19 @@ package android.service.voice; import android.annotation.SdkConstant; import android.app.Service; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.hardware.soundtrigger.KeyphraseEnrollmentInfo; import android.hardware.soundtrigger.SoundTriggerHelper; import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; +import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; +import android.provider.Settings; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IVoiceInteractionManagerService; @@ -64,14 +68,58 @@ public class VoiceInteractionService extends Service { public static final String SERVICE_META_DATA = "android.voice_interaction"; IVoiceInteractionService mInterface = new IVoiceInteractionService.Stub() { + @Override public void ready() { + mHandler.sendEmptyMessage(MSG_READY); + } }; + MyHandler mHandler; + IVoiceInteractionManagerService mSystemService; private KeyphraseEnrollmentInfo mKeyphraseEnrollmentInfo; private SoundTriggerHelper mSoundTriggerHelper; + static final int MSG_READY = 1; + + class MyHandler extends Handler { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_READY: + onReady(); + break; + default: + super.handleMessage(msg); + } + } + } + + /** + * Check whether the given service component is the currently active + * VoiceInteractionService. + */ + public static boolean isActiveService(Context context, ComponentName service) { + String cur = Settings.Secure.getString(context.getContentResolver(), + Settings.Secure.VOICE_INTERACTION_SERVICE); + if (cur == null || cur.isEmpty()) { + return false; + } + ComponentName curComp = ComponentName.unflattenFromString(cur); + if (curComp == null) { + return false; + } + return curComp.equals(cur); + } + + /** + * Initiate the execution of a new {@link android.service.voice.VoiceInteractionSession}. + * @param args Arbitrary arguments that will be propagated to the session. + */ public void startSession(Bundle args) { + if (mSystemService == null) { + throw new IllegalStateException("Not available until onReady() is called"); + } try { mSystemService.startSession(mInterface, args); } catch (RemoteException e) { @@ -81,10 +129,7 @@ public class VoiceInteractionService extends Service { @Override public void onCreate() { super.onCreate(); - mSystemService = IVoiceInteractionManagerService.Stub.asInterface( - ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE)); - mKeyphraseEnrollmentInfo = new KeyphraseEnrollmentInfo(getPackageManager()); - mSoundTriggerHelper = new SoundTriggerHelper(); + mHandler = new MyHandler(); } @Override @@ -95,6 +140,19 @@ public class VoiceInteractionService extends Service { return null; } + /** + * Called during service initialization to tell you when the system is ready + * to receive interaction from it. You should generally do initialization here + * rather than in {@link #onCreate()}. Methods such as {@link #startSession} + * and {@link #getAlwaysOnHotwordDetector} will not be operational until this point. + */ + public void onReady() { + mSystemService = IVoiceInteractionManagerService.Stub.asInterface( + ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE)); + mKeyphraseEnrollmentInfo = new KeyphraseEnrollmentInfo(getPackageManager()); + mSoundTriggerHelper = new SoundTriggerHelper(); + } + /** * @param keyphrase The keyphrase that's being used, for example "Hello Android". * @param locale The locale for which the enrollment needs to be performed. @@ -104,6 +162,11 @@ public class VoiceInteractionService extends Service { */ public final AlwaysOnHotwordDetector getAlwaysOnHotwordDetector( String keyphrase, String locale, AlwaysOnHotwordDetector.Callback callback) { + if (mSystemService == null) { + throw new IllegalStateException("Not available until onReady() is called"); + } + // TODO: Cache instances and return the same one instead of creating a new interactor + // for the same keyphrase/locale combination. return new AlwaysOnHotwordDetector(keyphrase, locale, callback, mKeyphraseEnrollmentInfo, mSoundTriggerHelper, mInterface, mSystemService); } diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java index a909ead8e95cd..d27e2cd91061f 100644 --- a/core/java/android/service/voice/VoiceInteractionServiceInfo.java +++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java @@ -40,6 +40,7 @@ public class VoiceInteractionServiceInfo { private ServiceInfo mServiceInfo; private String mSessionService; + private String mRecognitionService; private String mSettingsActivity; public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp) @@ -82,6 +83,8 @@ public class VoiceInteractionServiceInfo { com.android.internal.R.styleable.VoiceInteractionService); mSessionService = array.getString( com.android.internal.R.styleable.VoiceInteractionService_sessionService); + mRecognitionService = array.getString( + com.android.internal.R.styleable.VoiceInteractionService_recognitionService); mSettingsActivity = array.getString( com.android.internal.R.styleable.VoiceInteractionService_settingsActivity); array.recycle(); @@ -119,6 +122,10 @@ public class VoiceInteractionServiceInfo { return mSessionService; } + public String getRecognitionService() { + return mRecognitionService; + } + public String getSettingsActivity() { return mSettingsActivity; } diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java index 247c8feab80d9..cfeca086b2b43 100644 --- a/core/java/com/android/internal/os/BatterySipper.java +++ b/core/java/com/android/internal/os/BatterySipper.java @@ -80,6 +80,15 @@ public class BatterySipper implements Comparable { @Override public int compareTo(BatterySipper other) { + // Over-counted always goes to the bottom. + if (drainType != other.drainType) { + if (drainType == DrainType.OVERCOUNTED) { + // This is "larger" + return 1; + } else if (other.drainType == DrainType.OVERCOUNTED) { + return -1; + } + } // Return the flipped value because we want the items in descending order return Double.compare(other.value, value); } diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index 023ba032b1e8a..6c9b4b838152c 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -48,7 +48,6 @@ import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; -import java.util.Arrays; /** * A helper class for retrieving the power usage information for all applications and services. @@ -95,6 +94,7 @@ public class BatteryStatsHelper { private long mStatsPeriod = 0; private double mMaxPower = 1; + private double mMaxRealPower = 1; private double mComputedPower; private double mTotalPower; private double mWifiPower; @@ -208,6 +208,7 @@ public class BatteryStatsHelper { getStats(); mMaxPower = 0; + mMaxRealPower = 0; mComputedPower = 0; mTotalPower = 0; mWifiPower = 0; @@ -542,6 +543,7 @@ public class BatteryStatsHelper { } else { mUsageList.add(app); if (power > mMaxPower) mMaxPower = power; + if (power > mMaxRealPower) mMaxRealPower = power; mComputedPower += power; } if (u.getUid() == 0) { @@ -567,6 +569,7 @@ public class BatteryStatsHelper { osApp.value += power; osApp.values[0] += power; if (osApp.value > mMaxPower) mMaxPower = osApp.value; + if (osApp.value > mMaxRealPower) mMaxRealPower = osApp.value; mComputedPower += power; } } @@ -806,6 +809,7 @@ public class BatteryStatsHelper { private BatterySipper addEntry(DrainType drainType, long time, double power) { mComputedPower += power; + if (power > mMaxRealPower) mMaxRealPower = power; return addEntryNoTotal(drainType, time, power); } @@ -831,6 +835,8 @@ public class BatteryStatsHelper { public double getMaxPower() { return mMaxPower; } + public double getMaxRealPower() { return mMaxRealPower; } + public double getTotalPower() { return mTotalPower; } public double getComputedPower() { return mComputedPower; } diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 5b55a24de02c6..ab19ad4c5f385 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -6772,7 +6772,10 @@ its {@link android.service.voice.VoiceInteractionService#SERVICE_META_DATA} meta-data entry. Described here are the attributes that can be included in that tag. --> + + + diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 1b6ea951fd397..e4484ada04ebd 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2250,6 +2250,7 @@ + diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 0f55b0f981bcb..8b7e0d6b55de7 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4715,6 +4715,28 @@ public final class ActivityManagerService extends ActivityManagerNative } } + @Override + public void addPackageDependency(String packageName) { + synchronized (this) { + int callingPid = Binder.getCallingPid(); + if (callingPid == Process.myPid()) { + // Yeah, um, no. + Slog.w(TAG, "Can't addPackageDependency on system process"); + return; + } + ProcessRecord proc; + synchronized (mPidsSelfLocked) { + proc = mPidsSelfLocked.get(Binder.getCallingPid()); + } + if (proc != null) { + if (proc.pkgDeps == null) { + proc.pkgDeps = new ArraySet(1); + } + proc.pkgDeps.add(packageName); + } + } + } + /* * The pkg name and app id have to be specified. */ @@ -4911,7 +4933,6 @@ public final class ActivityManagerService extends ActivityManagerNative // Remove all processes this package may have touched: all with the // same UID (except for the system or root user), and all whose name // matches the package name. - final String procNamePrefix = packageName != null ? (packageName + ":") : null; final int NP = mProcessNames.getMap().size(); for (int ip=0; ip apps = mProcessNames.getMap().valueAt(ip); @@ -4947,13 +4968,15 @@ public final class ActivityManagerService extends ActivityManagerNative // that match it. We need to qualify this by the processes // that are running under the specified app and user ID. } else { - if (UserHandle.getAppId(app.uid) != appId) { + final boolean isDep = app.pkgDeps != null + && app.pkgDeps.contains(packageName); + if (!isDep && UserHandle.getAppId(app.uid) != appId) { continue; } if (userId != UserHandle.USER_ALL && app.userId != userId) { continue; } - if (!app.pkgList.containsKey(packageName)) { + if (!app.pkgList.containsKey(packageName) && !isDep) { continue; } } @@ -11030,30 +11053,15 @@ public final class ActivityManagerService extends ActivityManagerNative return errList; } - static int oomAdjToImportance(int adj, ActivityManager.RunningAppProcessInfo currApp) { - if (adj >= ProcessList.CACHED_APP_MIN_ADJ) { - if (currApp != null) { - currApp.lru = adj - ProcessList.CACHED_APP_MIN_ADJ + 1; - } - return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND; - } else if (adj >= ProcessList.SERVICE_B_ADJ) { - return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE; - } else if (adj >= ProcessList.HOME_APP_ADJ) { - if (currApp != null) { - currApp.lru = 0; - } - return ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND; - } else if (adj >= ProcessList.SERVICE_ADJ) { - return ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE; - } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) { - return ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE; - } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) { - return ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE; - } else if (adj >= ProcessList.VISIBLE_APP_ADJ) { - return ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE; + static int procStateToImportance(int procState, int memAdj, + ActivityManager.RunningAppProcessInfo currApp) { + int imp = ActivityManager.RunningAppProcessInfo.procStateToImportance(procState); + if (imp == ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND) { + currApp.lru = memAdj; } else { - return ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; + currApp.lru = 0; } + return imp; } private void fillInProcMemInfo(ProcessRecord app, @@ -11071,7 +11079,8 @@ public final class ActivityManagerService extends ActivityManagerNative } outInfo.lastTrimLevel = app.trimMemoryLevel; int adj = app.curAdj; - outInfo.importance = oomAdjToImportance(adj, outInfo); + int procState = app.curProcState; + outInfo.importance = procStateToImportance(procState, adj, outInfo); outInfo.importanceReasonCode = app.adjTypeCode; outInfo.processState = app.curProcState; } @@ -11098,8 +11107,9 @@ public final class ActivityManagerService extends ActivityManagerNative fillInProcMemInfo(app, currApp); if (app.adjSource instanceof ProcessRecord) { currApp.importanceReasonPid = ((ProcessRecord)app.adjSource).pid; - currApp.importanceReasonImportance = oomAdjToImportance( - app.adjSourceOom, null); + currApp.importanceReasonImportance = + ActivityManager.RunningAppProcessInfo.procStateToImportance( + app.adjSourceProcState); } else if (app.adjSource instanceof ActivityRecord) { ActivityRecord r = (ActivityRecord)app.adjSource; if (r.app != null) currApp.importanceReasonPid = r.app.pid; @@ -15615,7 +15625,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.adjTypeCode = ActivityManager.RunningAppProcessInfo .REASON_SERVICE_IN_USE; app.adjSource = cr.binding.client; - app.adjSourceOom = clientAdj; + app.adjSourceProcState = clientProcState; app.adjTarget = s.name; } } @@ -15636,7 +15646,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.adjTypeCode = ActivityManager.RunningAppProcessInfo .REASON_SERVICE_IN_USE; app.adjSource = a; - app.adjSourceOom = adj; + app.adjSourceProcState = procState; app.adjTarget = s.name; } } @@ -15681,7 +15691,7 @@ public final class ActivityManagerService extends ActivityManagerNative app.adjTypeCode = ActivityManager.RunningAppProcessInfo .REASON_PROVIDER_IN_USE; app.adjSource = client; - app.adjSourceOom = clientAdj; + app.adjSourceProcState = clientProcState; app.adjTarget = cpr.name; } if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) { diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index a20be73f2722d..b33f7b70f9ac8 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -55,6 +55,7 @@ final class ProcessRecord { // List of packages running in the process final ArrayMap pkgList = new ArrayMap(); + ArraySet pkgDeps; // additional packages we have a dependency on IApplicationThread thread; // the actual proc... may be null only if // 'persistent' is true (in which case we // are in the process of launching the app) @@ -124,7 +125,7 @@ final class ProcessRecord { String adjType; // Debugging: primary thing impacting oom_adj. int adjTypeCode; // Debugging: adj code to report to app. Object adjSource; // Debugging: option dependent object. - int adjSourceOom; // Debugging: oom_adj of adjSource's process. + int adjSourceProcState; // Debugging: proc state of adjSource's process. Object adjTarget; // Debugging: target component impacting oom_adj. // contains HistoryRecord objects @@ -195,6 +196,14 @@ final class ProcessRecord { pw.print(pkgList.keyAt(i)); } pw.println("}"); + if (pkgDeps != null) { + pw.print(prefix); pw.print("packageDependencies={"); + for (int i=0; i 0) pw.print(", "); + pw.print(pkgDeps.valueAt(i)); + } + pw.println("}"); + } pw.print(prefix); pw.print("compat="); pw.println(compat); if (instrumentationClass != null || instrumentationProfileFile != null || instrumentationArguments != null) { diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index 1f40c262687a4..54af5d462edf1 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -87,6 +87,10 @@ class VoiceInteractionManagerServiceImpl { public void onServiceConnected(ComponentName name, IBinder service) { synchronized (mLock) { mService = IVoiceInteractionService.Stub.asInterface(service); + try { + mService.ready(); + } catch (RemoteException e) { + } } } diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java index db43be3696eaf..ab2e8ac6ded4a 100644 --- a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java +++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java @@ -27,8 +27,8 @@ public class MainInteractionService extends VoiceInteractionService { static final String TAG = "MainInteractionService"; @Override - public void onCreate() { - super.onCreate(); + public void onReady() { + super.onReady(); Log.i(TAG, "Creating " + this); Log.i(TAG, "Keyphrase enrollment error? " + getKeyphraseEnrollmentInfo().getParseError()); Log.i(TAG, "Keyphrase enrollment meta-data: "