diff options
Diffstat (limited to 'core')
17 files changed, 528 insertions, 156 deletions
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index ed7a2a3..7032c9a 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -4520,6 +4520,17 @@ public class PackageParser { return applicationInfo.isUpdatedSystemApp(); } + /** + * @hide + */ + public boolean canHaveOatDir() { + // The following app types CANNOT have oat directory + // - non-updated system apps + // - forward-locked apps or apps installed in ASEC containers + return (!isSystemApp() || isUpdatedSystemApp()) + && !isForwardLocked() && !applicationInfo.isExternalAsec(); + } + public String toString() { return "Package{" + Integer.toHexString(System.identityHashCode(this)) diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 7fef5e1..122df23 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -775,7 +775,7 @@ public class FingerprintManager { if (fingerId != reqFingerId) { Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId); } - if (fingerId != reqFingerId) { + if (groupId != reqGroupId) { Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId); } mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint); diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index bad94fc..8e86a53 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -463,13 +463,15 @@ public abstract class BatteryStats implements Parcelable { public abstract long getCpuPowerMaUs(int which); /** - * Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed. + * Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed for a + * given CPU cluster. + * @param cluster the index of the CPU cluster. * @param step the index of the CPU speed. This is not the actual speed of the CPU. * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT. - * @see BatteryStats#getCpuSpeedSteps() + * @see PowerProfile.getNumCpuClusters() + * @see PowerProfile.getNumSpeedStepsInCpuCluster(int) */ - @Deprecated - public abstract long getTimeAtCpuSpeed(int step, int which); + public abstract long getTimeAtCpuSpeed(int cluster, int step, int which); public static abstract class Sensor { /* @@ -2276,9 +2278,6 @@ public abstract class BatteryStats implements Parcelable { public abstract Map<String, ? extends Timer> getKernelWakelockStats(); - /** Returns the number of different speeds that the CPU can run at */ - public abstract int getCpuSpeedSteps(); - public abstract void writeToParcelWithoutUids(Parcel out, int flags); private final static void formatTimeRaw(StringBuilder out, long seconds) { diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java index e742f98..17bce30 100644 --- a/core/java/android/os/PowerManagerInternal.java +++ b/core/java/android/os/PowerManagerInternal.java @@ -53,6 +53,15 @@ public abstract class PowerManagerInternal { */ public static final int WAKEFULNESS_DOZING = 3; + + /** + * Power hint: The user is interacting with the device. The corresponding data field must be + * the expected duration of the fling, or 0 if unknown. + * + * This must be kept in sync with the values in hardware/libhardware/include/hardware/power.h + */ + public static final int POWER_HINT_INTERACTION = 2; + public static String wakefulnessToString(int wakefulness) { switch (wakefulness) { case WAKEFULNESS_ASLEEP: @@ -142,4 +151,6 @@ public abstract class PowerManagerInternal { public abstract void updateUidProcState(int uid, int procState); public abstract void uidGone(int uid); + + public abstract void powerHint(int hintId, int data); } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 2053dbe..1822067 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3283,7 +3283,6 @@ public final class Settings { DOCK_SOUNDS_ENABLED, // moved to global LOCKSCREEN_SOUNDS_ENABLED, SHOW_WEB_SUGGESTIONS, - NOTIFICATION_LIGHT_PULSE, SIP_CALL_OPTIONS, SIP_RECEIVE_CALLS, POINTER_SPEED, diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index d9faece..3219dcb 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -104,6 +104,7 @@ public class ChooserActivity extends ResolverActivity { sri.resultTargets); } unbindService(sri.connection); + sri.connection.destroy(); mServiceConnections.remove(sri.connection); if (mServiceConnections.isEmpty()) { mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT); @@ -208,6 +209,8 @@ public class ChooserActivity extends ResolverActivity { mRefinementResultReceiver.destroy(); mRefinementResultReceiver = null; } + unbindRemainingServices(); + mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_RESULT); } @Override @@ -265,6 +268,11 @@ public class ChooserActivity extends ResolverActivity { return true; } + @Override + boolean shouldAutoLaunchSingleChoice() { + return false; + } + private void modifyTargetIntent(Intent in) { final String action = in.getAction(); if (Intent.ACTION_SEND.equals(action) || @@ -371,7 +379,8 @@ public class ChooserActivity extends ResolverActivity { continue; } - final ChooserTargetServiceConnection conn = new ChooserTargetServiceConnection(dri); + final ChooserTargetServiceConnection conn = + new ChooserTargetServiceConnection(this, dri); if (bindServiceAsUser(serviceIntent, conn, BIND_AUTO_CREATE | BIND_NOT_FOREGROUND, UserHandle.CURRENT)) { if (DEBUG) { @@ -425,6 +434,7 @@ public class ChooserActivity extends ResolverActivity { final ChooserTargetServiceConnection conn = mServiceConnections.get(i); if (DEBUG) Log.d(TAG, "unbinding " + conn); unbindService(conn); + conn.destroy(); } mServiceConnections.clear(); mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT); @@ -637,7 +647,8 @@ public class ChooserActivity extends ResolverActivity { @Override public CharSequence getExtendedInfo() { - return mSourceInfo != null ? mSourceInfo.getExtendedInfo() : null; + // ChooserTargets have badge icons, so we won't show the extended info to disambiguate. + return null; } @Override @@ -730,9 +741,8 @@ public class ChooserActivity extends ResolverActivity { @Override public boolean showsExtendedInfo(TargetInfo info) { - // Reserve space to show extended info if any one of the items in the adapter has - // extended info. This keeps grid item sizes uniform. - return hasExtendedInfo(); + // We have badges so we don't need this text shown. + return false; } @Override @@ -1024,54 +1034,93 @@ public class ChooserActivity extends ResolverActivity { } } - class ChooserTargetServiceConnection implements ServiceConnection { + static class ChooserTargetServiceConnection implements ServiceConnection { private final DisplayResolveInfo mOriginalTarget; + private ComponentName mConnectedComponent; + private ChooserActivity mChooserActivity; + private final Object mLock = new Object(); private final IChooserTargetResult mChooserTargetResult = new IChooserTargetResult.Stub() { @Override public void sendResult(List<ChooserTarget> targets) throws RemoteException { - filterServiceTargets(mOriginalTarget.getResolveInfo().activityInfo.packageName, - targets); - final Message msg = Message.obtain(); - msg.what = CHOOSER_TARGET_SERVICE_RESULT; - msg.obj = new ServiceResultInfo(mOriginalTarget, targets, - ChooserTargetServiceConnection.this); - mChooserHandler.sendMessage(msg); + synchronized (mLock) { + if (mChooserActivity == null) { + Log.e(TAG, "destroyed ChooserTargetServiceConnection received result from " + + mConnectedComponent + "; ignoring..."); + return; + } + mChooserActivity.filterServiceTargets( + mOriginalTarget.getResolveInfo().activityInfo.packageName, targets); + final Message msg = Message.obtain(); + msg.what = CHOOSER_TARGET_SERVICE_RESULT; + msg.obj = new ServiceResultInfo(mOriginalTarget, targets, + ChooserTargetServiceConnection.this); + mChooserActivity.mChooserHandler.sendMessage(msg); + } } }; - public ChooserTargetServiceConnection(DisplayResolveInfo dri) { + public ChooserTargetServiceConnection(ChooserActivity chooserActivity, + DisplayResolveInfo dri) { + mChooserActivity = chooserActivity; mOriginalTarget = dri; } @Override public void onServiceConnected(ComponentName name, IBinder service) { if (DEBUG) Log.d(TAG, "onServiceConnected: " + name); - final IChooserTargetService icts = IChooserTargetService.Stub.asInterface(service); - try { - icts.getChooserTargets(mOriginalTarget.getResolvedComponentName(), - mOriginalTarget.getResolveInfo().filter, mChooserTargetResult); - } catch (RemoteException e) { - Log.e(TAG, "Querying ChooserTargetService " + name + " failed.", e); - unbindService(this); - mServiceConnections.remove(this); + synchronized (mLock) { + if (mChooserActivity == null) { + Log.e(TAG, "destroyed ChooserTargetServiceConnection got onServiceConnected"); + return; + } + + final IChooserTargetService icts = IChooserTargetService.Stub.asInterface(service); + try { + icts.getChooserTargets(mOriginalTarget.getResolvedComponentName(), + mOriginalTarget.getResolveInfo().filter, mChooserTargetResult); + } catch (RemoteException e) { + Log.e(TAG, "Querying ChooserTargetService " + name + " failed.", e); + mChooserActivity.unbindService(this); + destroy(); + mChooserActivity.mServiceConnections.remove(this); + } } } @Override public void onServiceDisconnected(ComponentName name) { if (DEBUG) Log.d(TAG, "onServiceDisconnected: " + name); - unbindService(this); - mServiceConnections.remove(this); - if (mServiceConnections.isEmpty()) { - mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT); - sendVoiceChoicesIfNeeded(); + synchronized (mLock) { + if (mChooserActivity == null) { + Log.e(TAG, + "destroyed ChooserTargetServiceConnection got onServiceDisconnected"); + return; + } + + mChooserActivity.unbindService(this); + destroy(); + mChooserActivity.mServiceConnections.remove(this); + if (mChooserActivity.mServiceConnections.isEmpty()) { + mChooserActivity.mChooserHandler.removeMessages( + CHOOSER_TARGET_SERVICE_WATCHDOG_TIMEOUT); + mChooserActivity.sendVoiceChoicesIfNeeded(); + } + mConnectedComponent = null; + } + } + + public void destroy() { + synchronized (mLock) { + mChooserActivity = null; } } @Override public String toString() { - return mOriginalTarget.getResolveInfo().activityInfo.toString(); + return "ChooserTargetServiceConnection{service=" + + mConnectedComponent + ", activity=" + + mOriginalTarget.getResolveInfo().activityInfo.toString() + "}"; } } diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 7dd3bed..ef9d1ce 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -234,7 +234,9 @@ public class ResolverActivity extends Activity { mResolverComparator = new ResolverComparator(this, getTargetIntent(), referrerPackage); - configureContentView(mIntents, initialIntents, rList, alwaysUseOption); + if (configureContentView(mIntents, initialIntents, rList, alwaysUseOption)) { + return; + } // Prevent the Resolver window from becoming the top fullscreen window and thus from taking // control of the system bars. @@ -794,6 +796,10 @@ public class ResolverActivity extends Activity { return false; } + boolean shouldAutoLaunchSingleChoice() { + return true; + } + void showAppDetails(ResolveInfo ri) { Intent in = new Intent().setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) .setData(Uri.fromParts("package", ri.activityInfo.packageName, null)) @@ -808,7 +814,10 @@ public class ResolverActivity extends Activity { launchedFromUid, filterLastUsed); } - void configureContentView(List<Intent> payloadIntents, Intent[] initialIntents, + /** + * Returns true if the activity is finishing and creation should halt + */ + boolean configureContentView(List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList, boolean alwaysUseOption) { // The last argument of createAdapter is whether to do special handling // of the last used choice to highlight it in the list. We need to always @@ -828,7 +837,9 @@ public class ResolverActivity extends Activity { mAlwaysUseOption = alwaysUseOption; int count = mAdapter.getUnfilteredCount(); - if (count > 1 || (count == 1 && mAdapter.getOtherProfile() != null)) { + if ((!shouldAutoLaunchSingleChoice() && count > 0) + || count > 1 + || (count == 1 && mAdapter.getOtherProfile() != null)) { setContentView(layoutId); mAdapterView = (AbsListView) findViewById(R.id.resolver_list); onPrepareAdapterView(mAdapterView, mAdapter, alwaysUseOption); @@ -837,7 +848,7 @@ public class ResolverActivity extends Activity { mPackageMonitor.unregister(); mRegistered = false; finish(); - return; + return true; } else { setContentView(R.layout.resolver_list); @@ -847,6 +858,7 @@ public class ResolverActivity extends Activity { mAdapterView = (AbsListView) findViewById(R.id.resolver_list); mAdapterView.setVisibility(View.GONE); } + return false; } void onPrepareAdapterView(AbsListView adapterView, ResolveListAdapter adapter, @@ -884,6 +896,7 @@ public class ResolverActivity extends Activity { private final ResolveInfo mResolveInfo; private final CharSequence mDisplayLabel; private Drawable mDisplayIcon; + private Drawable mBadge; private final CharSequence mExtendedInfo; private final Intent mResolvedIntent; private final List<Intent> mSourceIntents = new ArrayList<>(); @@ -928,7 +941,25 @@ public class ResolverActivity extends Activity { } public Drawable getBadgeIcon() { - return null; + // We only expose a badge if we have extended info. + // The badge is a higher-priority disambiguation signal + // but we don't need one if we wouldn't show extended info at all. + if (TextUtils.isEmpty(getExtendedInfo())) { + return null; + } + + if (mBadge == null && mResolveInfo != null && mResolveInfo.activityInfo != null + && mResolveInfo.activityInfo.applicationInfo != null) { + if (mResolveInfo.activityInfo.icon == 0 || mResolveInfo.activityInfo.icon + == mResolveInfo.activityInfo.applicationInfo.icon) { + // Badging an icon with exactly the same icon is silly. + // If the activityInfo icon resid is 0 it will fall back + // to the application's icon, making it a match. + return null; + } + mBadge = mResolveInfo.activityInfo.applicationInfo.loadIcon(mPm); + } + return mBadge; } @Override @@ -1366,8 +1397,8 @@ public class ResolverActivity extends Activity { } else { mHasExtendedInfo = true; boolean usePkg = false; - CharSequence startApp = ro.getResolveInfoAt(0).activityInfo.applicationInfo - .loadLabel(mPm); + final ApplicationInfo ai = ro.getResolveInfoAt(0).activityInfo.applicationInfo; + final CharSequence startApp = ai.loadLabel(mPm); if (startApp == null) { usePkg = true; } diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java index 4f4d3e0..f178c8c 100644 --- a/core/java/com/android/internal/os/BatteryStatsHelper.java +++ b/core/java/com/android/internal/os/BatteryStatsHelper.java @@ -338,7 +338,7 @@ public final class BatteryStatsHelper { } if (mCpuPowerCalculator == null) { - mCpuPowerCalculator = new CpuPowerCalculator(); + mCpuPowerCalculator = new CpuPowerCalculator(mPowerProfile); } mCpuPowerCalculator.reset(); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 4ff7869..6ccdd08 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -105,7 +105,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 130 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 131 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -118,8 +118,6 @@ public final class BatteryStatsImpl extends BatteryStats { // in to one common name. private static final int MAX_WAKELOCKS_PER_UID = 100; - private static int sNumSpeedSteps; - private final JournaledFile mFile; public final AtomicFile mCheckinFile; public final AtomicFile mDailyFile; @@ -133,7 +131,7 @@ public final class BatteryStatsImpl extends BatteryStats { private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats(); private final KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader(); - private final KernelCpuSpeedReader mKernelCpuSpeedReader = new KernelCpuSpeedReader(); + private KernelCpuSpeedReader[] mKernelCpuSpeedReaders; public interface BatteryCallback { public void batteryNeedsCpuUpdate(); @@ -4411,7 +4409,7 @@ public final class BatteryStatsImpl extends BatteryStats { LongSamplingCounter mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase); LongSamplingCounter mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase); LongSamplingCounter mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase); - LongSamplingCounter[] mSpeedBins; + LongSamplingCounter[][] mCpuClusterSpeed; /** * The statistics we have collected for this uid's wake locks. @@ -4470,7 +4468,6 @@ public final class BatteryStatsImpl extends BatteryStats { mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED, mWifiMulticastTimers, mOnBatteryTimeBase); mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE]; - mSpeedBins = new LongSamplingCounter[getCpuSpeedSteps()]; } @Override @@ -5008,10 +5005,18 @@ public final class BatteryStatsImpl extends BatteryStats { } @Override - public long getTimeAtCpuSpeed(int step, int which) { - if (step >= 0 && step < mSpeedBins.length) { - if (mSpeedBins[step] != null) { - return mSpeedBins[step].getCountLocked(which); + public long getTimeAtCpuSpeed(int cluster, int step, int which) { + if (mCpuClusterSpeed != null) { + if (cluster >= 0 && cluster < mCpuClusterSpeed.length) { + final LongSamplingCounter[] cpuSpeeds = mCpuClusterSpeed[cluster]; + if (cpuSpeeds != null) { + if (step >= 0 && step < cpuSpeeds.length) { + final LongSamplingCounter c = cpuSpeeds[step]; + if (c != null) { + return c.getCountLocked(which); + } + } + } } } return 0; @@ -5128,10 +5133,16 @@ public final class BatteryStatsImpl extends BatteryStats { mUserCpuTime.reset(false); mSystemCpuTime.reset(false); mCpuPower.reset(false); - for (int i = 0; i < mSpeedBins.length; i++) { - LongSamplingCounter c = mSpeedBins[i]; - if (c != null) { - c.reset(false); + + if (mCpuClusterSpeed != null) { + for (LongSamplingCounter[] speeds : mCpuClusterSpeed) { + if (speeds != null) { + for (LongSamplingCounter speed : speeds) { + if (speed != null) { + speed.reset(false); + } + } + } } } @@ -5280,10 +5291,16 @@ public final class BatteryStatsImpl extends BatteryStats { mUserCpuTime.detach(); mSystemCpuTime.detach(); mCpuPower.detach(); - for (int i = 0; i < mSpeedBins.length; i++) { - LongSamplingCounter c = mSpeedBins[i]; - if (c != null) { - c.detach(); + + if (mCpuClusterSpeed != null) { + for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) { + if (cpuSpeeds != null) { + for (LongSamplingCounter c : cpuSpeeds) { + if (c != null) { + c.detach(); + } + } + } } } } @@ -5461,15 +5478,27 @@ public final class BatteryStatsImpl extends BatteryStats { mSystemCpuTime.writeToParcel(out); mCpuPower.writeToParcel(out); - out.writeInt(mSpeedBins.length); - for (int i = 0; i < mSpeedBins.length; i++) { - LongSamplingCounter c = mSpeedBins[i]; - if (c != null) { - out.writeInt(1); - c.writeToParcel(out); - } else { - out.writeInt(0); + if (mCpuClusterSpeed != null) { + out.writeInt(1); + out.writeInt(mCpuClusterSpeed.length); + for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) { + if (cpuSpeeds != null) { + out.writeInt(1); + out.writeInt(cpuSpeeds.length); + for (LongSamplingCounter c : cpuSpeeds) { + if (c != null) { + out.writeInt(1); + c.writeToParcel(out); + } else { + out.writeInt(0); + } + } + } else { + out.writeInt(0); + } } + } else { + out.writeInt(0); } } @@ -5653,13 +5682,32 @@ public final class BatteryStatsImpl extends BatteryStats { mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in); mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase, in); - int bins = in.readInt(); - int steps = getCpuSpeedSteps(); - mSpeedBins = new LongSamplingCounter[bins >= steps ? bins : steps]; - for (int i = 0; i < bins; i++) { - if (in.readInt() != 0) { - mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase, in); + if (in.readInt() != 0) { + int numCpuClusters = in.readInt(); + if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numCpuClusters) { + throw new ParcelFormatException("Incompatible number of cpu clusters"); + } + + mCpuClusterSpeed = new LongSamplingCounter[numCpuClusters][]; + for (int cluster = 0; cluster < numCpuClusters; cluster++) { + if (in.readInt() != 0) { + int numSpeeds = in.readInt(); + if (mPowerProfile != null && + mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) { + throw new ParcelFormatException("Incompatible number of cpu speeds"); + } + + final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds]; + mCpuClusterSpeed[cluster] = cpuSpeeds; + for (int speed = 0; speed < numSpeeds; speed++) { + if (in.readInt() != 0) { + cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase, in); + } + } + } } + } else { + mCpuClusterSpeed = null; } } @@ -6874,6 +6922,19 @@ public final class BatteryStatsImpl extends BatteryStats { public void setPowerProfile(PowerProfile profile) { synchronized (this) { mPowerProfile = profile; + + // We need to initialize the KernelCpuSpeedReaders to read from + // the first cpu of each core. Once we have the PowerProfile, we have access to this + // information. + final int numClusters = mPowerProfile.getNumCpuClusters(); + mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters]; + int firstCpuOfCluster = 0; + for (int i = 0; i < numClusters; i++) { + final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i); + mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster, + numSpeedSteps); + firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i); + } } } @@ -6881,10 +6942,6 @@ public final class BatteryStatsImpl extends BatteryStats { mCallback = cb; } - public void setNumSpeedSteps(int steps) { - if (sNumSpeedSteps == 0) sNumSpeedSteps = steps; - } - public void setRadioScanningTimeout(long timeout) { if (mPhoneSignalScanningTimer != null) { mPhoneSignalScanningTimer.setTimeout(timeout); @@ -7997,9 +8054,11 @@ public final class BatteryStatsImpl extends BatteryStats { // If no app is holding a wakelock, then the distribution is normal. final int wakelockWeight = 50; - // Read the time spent at various cpu frequencies. - final int cpuSpeedSteps = getCpuSpeedSteps(); - final long[] cpuSpeeds = mKernelCpuSpeedReader.readDelta(); + // Read the time spent for each cluster at various cpu frequencies. + final long[][] clusterSpeeds = new long[mKernelCpuSpeedReaders.length][]; + for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) { + clusterSpeeds[cluster] = mKernelCpuSpeedReaders[cluster].readDelta(); + } int numWakelocks = 0; @@ -8072,11 +8131,23 @@ public final class BatteryStatsImpl extends BatteryStats { // Add the cpu speeds to this UID. These are used as a ratio // for computing the power this UID used. - for (int i = 0; i < cpuSpeedSteps; i++) { - if (u.mSpeedBins[i] == null) { - u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase); + if (u.mCpuClusterSpeed == null) { + u.mCpuClusterSpeed = new LongSamplingCounter[clusterSpeeds.length][]; + } + + for (int cluster = 0; cluster < clusterSpeeds.length; cluster++) { + if (u.mCpuClusterSpeed[cluster] == null) { + u.mCpuClusterSpeed[cluster] = + new LongSamplingCounter[clusterSpeeds[cluster].length]; + } + + final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeed[cluster]; + for (int speed = 0; speed < clusterSpeeds[cluster].length; speed++) { + if (cpuSpeeds[speed] == null) { + cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase); + } + cpuSpeeds[speed].addCountLocked(clusterSpeeds[cluster][speed]); } - u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]); } } }); @@ -8776,11 +8847,6 @@ public final class BatteryStatsImpl extends BatteryStats { } } - @Override - public int getCpuSpeedSteps() { - return sNumSpeedSteps; - } - /** * Retrieve the statistics object for a particular uid, creating if needed. */ @@ -9216,11 +9282,6 @@ public final class BatteryStatsImpl extends BatteryStats { } } - sNumSpeedSteps = in.readInt(); - if (sNumSpeedSteps < 0 || sNumSpeedSteps > 100) { - throw new ParcelFormatException("Bad speed steps in data: " + sNumSpeedSteps); - } - final int NU = in.readInt(); if (NU > 10000) { throw new ParcelFormatException("File corrupt: too many uids " + NU); @@ -9304,17 +9365,33 @@ public final class BatteryStatsImpl extends BatteryStats { u.mSystemCpuTime.readSummaryFromParcelLocked(in); u.mCpuPower.readSummaryFromParcelLocked(in); - int NSB = in.readInt(); - if (NSB > 100) { - throw new ParcelFormatException("File corrupt: too many speed bins " + NSB); - } + if (in.readInt() != 0) { + final int numClusters = in.readInt(); + if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) { + throw new ParcelFormatException("Incompatible cpu cluster arrangement"); + } - u.mSpeedBins = new LongSamplingCounter[NSB]; - for (int i=0; i<NSB; i++) { - if (in.readInt() != 0) { - u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase); - u.mSpeedBins[i].readSummaryFromParcelLocked(in); + u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][]; + for (int cluster = 0; cluster < numClusters; cluster++) { + int NSB = in.readInt(); + if (mPowerProfile != null && + mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) { + throw new ParcelFormatException("File corrupt: too many speed bins " + NSB); + } + + if (in.readInt() != 0) { + u.mCpuClusterSpeed[cluster] = new LongSamplingCounter[NSB]; + for (int speed = 0; speed < NSB; speed++) { + if (in.readInt() != 0) { + u.mCpuClusterSpeed[cluster][speed] = new LongSamplingCounter( + mOnBatteryTimeBase); + u.mCpuClusterSpeed[cluster][speed].readSummaryFromParcelLocked(in); + } + } + } } + } else { + u.mCpuClusterSpeed = null; } int NW = in.readInt(); @@ -9531,7 +9608,6 @@ public final class BatteryStatsImpl extends BatteryStats { } } - out.writeInt(sNumSpeedSteps); final int NU = mUidStats.size(); out.writeInt(NU); for (int iu = 0; iu < NU; iu++) { @@ -9640,15 +9716,27 @@ public final class BatteryStatsImpl extends BatteryStats { u.mSystemCpuTime.writeSummaryFromParcelLocked(out); u.mCpuPower.writeSummaryFromParcelLocked(out); - out.writeInt(u.mSpeedBins.length); - for (int i = 0; i < u.mSpeedBins.length; i++) { - LongSamplingCounter speedBin = u.mSpeedBins[i]; - if (speedBin != null) { - out.writeInt(1); - speedBin.writeSummaryFromParcelLocked(out); - } else { - out.writeInt(0); + if (u.mCpuClusterSpeed != null) { + out.writeInt(1); + out.writeInt(u.mCpuClusterSpeed.length); + for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeed) { + if (cpuSpeeds != null) { + out.writeInt(1); + out.writeInt(cpuSpeeds.length); + for (LongSamplingCounter c : cpuSpeeds) { + if (c != null) { + out.writeInt(1); + c.writeSummaryFromParcelLocked(out); + } else { + out.writeInt(0); + } + } + } else { + out.writeInt(0); + } } + } else { + out.writeInt(0); } final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap(); @@ -9897,8 +9985,6 @@ public final class BatteryStatsImpl extends BatteryStats { mFlashlightTurnedOnTimers.clear(); mCameraTurnedOnTimers.clear(); - sNumSpeedSteps = in.readInt(); - int numUids = in.readInt(); mUidStats.clear(); for (int i = 0; i < numUids; i++) { @@ -10037,8 +10123,6 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeInt(0); } - out.writeInt(sNumSpeedSteps); - if (inclUids) { int size = mUidStats.size(); out.writeInt(size); diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java index d62f7a6..8417856 100644 --- a/core/java/com/android/internal/os/CpuPowerCalculator.java +++ b/core/java/com/android/internal/os/CpuPowerCalculator.java @@ -22,12 +22,47 @@ import android.util.Log; public class CpuPowerCalculator extends PowerCalculator { private static final String TAG = "CpuPowerCalculator"; private static final boolean DEBUG = BatteryStatsHelper.DEBUG; + private final PowerProfile mProfile; + + public CpuPowerCalculator(PowerProfile profile) { + mProfile = profile; + } @Override public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs, long rawUptimeUs, int statsType) { + app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000; - app.cpuPowerMah = (double) u.getCpuPowerMaUs(statsType) / (60.0 * 60.0 * 1000.0 * 1000.0); + + // Aggregate total time spent on each cluster. + long totalTime = 0; + final int numClusters = mProfile.getNumCpuClusters(); + for (int cluster = 0; cluster < numClusters; cluster++) { + final int speedsForCluster = mProfile.getNumSpeedStepsInCpuCluster(cluster); + for (int speed = 0; speed < speedsForCluster; speed++) { + totalTime += u.getTimeAtCpuSpeed(cluster, speed, statsType); + } + } + totalTime = Math.max(totalTime, 1); + + double cpuPowerMaMs = 0; + for (int cluster = 0; cluster < numClusters; cluster++) { + final int speedsForCluster = mProfile.getNumSpeedStepsInCpuCluster(cluster); + for (int speed = 0; speed < speedsForCluster; speed++) { + final double ratio = (double) u.getTimeAtCpuSpeed(cluster, speed, statsType) / + totalTime; + final double cpuSpeedStepPower = ratio * app.cpuTimeMs * + mProfile.getAveragePowerForCpu(cluster, speed); + if (DEBUG && ratio != 0) { + Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #" + + speed + " ratio=" + BatteryStatsHelper.makemAh(ratio) + " power=" + + BatteryStatsHelper.makemAh(cpuSpeedStepPower / (60 * 60 * 1000))); + } + cpuPowerMaMs += cpuSpeedStepPower; + } + } + app.cpuPowerMah = cpuPowerMaMs / (60 * 60 * 1000); + if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) { Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + app.cpuTimeMs + " ms power=" + BatteryStatsHelper.makemAh(app.cpuPowerMah)); diff --git a/core/java/com/android/internal/os/KernelCpuSpeedReader.java b/core/java/com/android/internal/os/KernelCpuSpeedReader.java index c30df28..5b776ac 100644 --- a/core/java/com/android/internal/os/KernelCpuSpeedReader.java +++ b/core/java/com/android/internal/os/KernelCpuSpeedReader.java @@ -24,8 +24,8 @@ import java.io.IOException; import java.util.Arrays; /** - * Reads CPU time spent at various frequencies and provides a delta from the last call to - * {@link #readDelta}. Each line in the proc file has the format: + * Reads CPU time of a specific core spent at various frequencies and provides a delta from the + * last call to {@link #readDelta}. Each line in the proc file has the format: * * freq time * @@ -33,12 +33,20 @@ import java.util.Arrays; */ public class KernelCpuSpeedReader { private static final String TAG = "KernelCpuSpeedReader"; - private static final String sProcFile = - "/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state"; - private static final int MAX_SPEEDS = 60; - private long[] mLastSpeedTimes = new long[MAX_SPEEDS]; - private long[] mDeltaSpeedTimes = new long[MAX_SPEEDS]; + private final String mProcFile; + private final long[] mLastSpeedTimes; + private final long[] mDeltaSpeedTimes; + + /** + * @param cpuNumber The cpu (cpu0, cpu1, etc) whose state to read. + */ + public KernelCpuSpeedReader(int cpuNumber, int numSpeedSteps) { + mProcFile = String.format("/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state", + cpuNumber); + mLastSpeedTimes = new long[numSpeedSteps]; + mDeltaSpeedTimes = new long[numSpeedSteps]; + } /** * The returned array is modified in subsequent calls to {@link #readDelta}. @@ -46,22 +54,28 @@ public class KernelCpuSpeedReader { * {@link #readDelta}. */ public long[] readDelta() { - try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) { + try (BufferedReader reader = new BufferedReader(new FileReader(mProcFile))) { TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' '); String line; int speedIndex = 0; - while ((line = reader.readLine()) != null) { + while (speedIndex < mLastSpeedTimes.length && (line = reader.readLine()) != null) { splitter.setString(line); Long.parseLong(splitter.next()); // The proc file reports time in 1/100 sec, so convert to milliseconds. long time = Long.parseLong(splitter.next()) * 10; - mDeltaSpeedTimes[speedIndex] = time - mLastSpeedTimes[speedIndex]; + if (time < mLastSpeedTimes[speedIndex]) { + // The stats reset when the cpu hotplugged. That means that the time + // we read is offset from 0, so the time is the delta. + mDeltaSpeedTimes[speedIndex] = time; + } else { + mDeltaSpeedTimes[speedIndex] = time - mLastSpeedTimes[speedIndex]; + } mLastSpeedTimes[speedIndex] = time; speedIndex++; } } catch (IOException e) { - Slog.e(TAG, "Failed to read cpu-freq", e); + Slog.e(TAG, "Failed to read cpu-freq: " + e.getMessage()); Arrays.fill(mDeltaSpeedTimes, 0); } return mDeltaSpeedTimes; diff --git a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java index 0df78ed..5d3043c 100644 --- a/core/java/com/android/internal/os/KernelUidCpuTimeReader.java +++ b/core/java/com/android/internal/os/KernelUidCpuTimeReader.java @@ -137,7 +137,7 @@ public class KernelUidCpuTimeReader { mLastPowerMaUs.put(uid, powerMaUs); } } catch (IOException e) { - Slog.e(TAG, "Failed to read uid_cputime", e); + Slog.e(TAG, "Failed to read uid_cputime: " + e.getMessage()); } mLastTimeReadUs = nowUs; } diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java index 4ede8dd..aaa9f73 100644 --- a/core/java/com/android/internal/os/PowerProfile.java +++ b/core/java/com/android/internal/os/PowerProfile.java @@ -59,6 +59,7 @@ public class PowerProfile { /** * Power consumption when CPU is in power collapse mode. */ + @Deprecated public static final String POWER_CPU_ACTIVE = "cpu.active"; /** @@ -163,6 +164,7 @@ public class PowerProfile { */ public static final String POWER_CAMERA = "camera.avg"; + @Deprecated public static final String POWER_CPU_SPEEDS = "cpu.speeds"; /** @@ -191,6 +193,7 @@ public class PowerProfile { if (sPowerMap.size() == 0) { readPowerValuesFromXml(context); } + initCpuClusters(); } private void readPowerValuesFromXml(Context context) { @@ -249,7 +252,7 @@ public class PowerProfile { } // Now collect other config variables. - int[] configResIds = new int[] { + int[] configResIds = new int[]{ com.android.internal.R.integer.config_bluetooth_idle_cur_ma, com.android.internal.R.integer.config_bluetooth_rx_cur_ma, com.android.internal.R.integer.config_bluetooth_tx_cur_ma, @@ -260,7 +263,7 @@ public class PowerProfile { com.android.internal.R.integer.config_wifi_operating_voltage_mv, }; - String[] configResIdKeys = new String[] { + String[] configResIdKeys = new String[]{ POWER_BLUETOOTH_CONTROLLER_IDLE, POWER_BLUETOOTH_CONTROLLER_RX, POWER_BLUETOOTH_CONTROLLER_TX, @@ -279,6 +282,69 @@ public class PowerProfile { } } + private CpuClusterKey[] mCpuClusters; + + private static final String POWER_CPU_CLUSTER_CORE_COUNT = "cpu.clusters.cores"; + private static final String POWER_CPU_CLUSTER_SPEED_PREFIX = "cpu.speeds.cluster"; + private static final String POWER_CPU_CLUSTER_ACTIVE_PREFIX = "cpu.active.cluster"; + + @SuppressWarnings("deprecated") + private void initCpuClusters() { + // Figure out how many CPU clusters we're dealing with + final Object obj = sPowerMap.get(POWER_CPU_CLUSTER_CORE_COUNT); + if (obj == null || !(obj instanceof Double[])) { + // Default to single. + mCpuClusters = new CpuClusterKey[1]; + mCpuClusters[0] = new CpuClusterKey(POWER_CPU_SPEEDS, POWER_CPU_ACTIVE, 1); + + } else { + final Double[] array = (Double[]) obj; + mCpuClusters = new CpuClusterKey[array.length]; + for (int cluster = 0; cluster < array.length; cluster++) { + int numCpusInCluster = (int) Math.round(array[cluster]); + mCpuClusters[cluster] = new CpuClusterKey( + POWER_CPU_CLUSTER_SPEED_PREFIX + cluster, + POWER_CPU_CLUSTER_ACTIVE_PREFIX + cluster, + numCpusInCluster); + } + } + } + + public static class CpuClusterKey { + private final String timeKey; + private final String powerKey; + private final int numCpus; + + private CpuClusterKey(String timeKey, String powerKey, int numCpus) { + this.timeKey = timeKey; + this.powerKey = powerKey; + this.numCpus = numCpus; + } + } + + public int getNumCpuClusters() { + return mCpuClusters.length; + } + + public int getNumCoresInCpuCluster(int index) { + return mCpuClusters[index].numCpus; + } + + public int getNumSpeedStepsInCpuCluster(int index) { + Object value = sPowerMap.get(mCpuClusters[index].timeKey); + if (value != null && value instanceof Double[]) { + return ((Double[])value).length; + } + return 1; // Only one speed + } + + public double getAveragePowerForCpu(int cluster, int step) { + if (cluster >= 0 && cluster < mCpuClusters.length) { + return getAveragePower(mCpuClusters[cluster].powerKey, step); + } + return 0; + } + /** * Returns the average current in mA consumed by the subsystem, or the given * default value if the subsystem has no recorded value. @@ -344,16 +410,4 @@ public class PowerProfile { public double getBatteryCapacity() { return getAveragePower(POWER_BATTERY_CAPACITY); } - - /** - * Returns the number of speeds that the CPU can be run at. - * @return - */ - public int getNumSpeedSteps() { - Object value = sPowerMap.get(POWER_CPU_SPEEDS); - if (value != null && value instanceof Double[]) { - return ((Double[])value).length; - } - return 1; // Only one speed - } } diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index a873ef8..82ae2f3 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -1071,12 +1071,22 @@ public class LockPatternUtils { * enter a pattern. */ public long getLockoutAttemptDeadline(int userId) { - final long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L, userId); + long deadline = getLong(LOCKOUT_ATTEMPT_DEADLINE, 0L, userId); final long timeoutMs = getLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, 0L, userId); final long now = SystemClock.elapsedRealtime(); - if (deadline < now || deadline > (now + timeoutMs)) { + if (deadline < now) { + // timeout expired + setLong(LOCKOUT_ATTEMPT_DEADLINE, 0, userId); + setLong(LOCKOUT_ATTEMPT_TIMEOUT_MS, 0, userId); return 0L; } + + if (deadline > (now + timeoutMs)) { + // device was rebooted, set new deadline + deadline = now + timeoutMs; + setLong(LOCKOUT_ATTEMPT_DEADLINE, deadline, userId); + } + return deadline; } diff --git a/core/res/res/values-mcc240-mnc01/config.xml b/core/res/res/values-mcc240-mnc01/config.xml new file mode 100644 index 0000000..7fb5c46 --- /dev/null +++ b/core/res/res/values-mcc240-mnc01/config.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Do not set the system language as value of EF LI/EF PL --> + <bool name="config_use_sim_language_file">false</bool> + +</resources> diff --git a/core/res/res/values-mcc240-mnc05/config.xml b/core/res/res/values-mcc240-mnc05/config.xml new file mode 100644 index 0000000..7fb5c46 --- /dev/null +++ b/core/res/res/values-mcc240-mnc05/config.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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 my 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. +*/ +--> + +<!-- These resources are around just to allow their values to be customized + for different hardware and product builds. --> +<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> + + <!-- Do not set the system language as value of EF LI/EF PL --> + <bool name="config_use_sim_language_file">false</bool> + +</resources> diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml index 28d99d8..ddd0ca2 100644 --- a/core/res/res/xml/power_profile.xml +++ b/core/res/res/xml/power_profile.xml @@ -47,17 +47,38 @@ <value>0.2</value> <!-- ~2mA --> <value>0.1</value> <!-- ~1mA --> </array> - <!-- Different CPU speeds as reported in - /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state --> - <array name="cpu.speeds"> + + <!-- A list of heterogeneous CPU clusters, where the value for each cluster represents the + number of CPU cores for that cluster. + + Ex: + <array name="cpu.clusters.cores"> + <value>4</value> // cluster 0 has cpu0, cpu1, cpu2, cpu3 + <value>2</value> // cluster 1 has cpu4, cpu5 + </array> --> + <array name="cpu.clusters.cores"> + <value>1</value> <!-- cluster 0 has cpu0 --> + </array> + + <!-- Different CPU speeds for cluster 0 as reported in + /sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state. + + There must be one of these for each cluster, labeled: + cpu.speeds.cluster0, cpu.speeds.cluster1, etc... --> + <array name="cpu.speeds.cluster0"> <value>400000</value> <!-- 400 MHz CPU speed --> </array> - <!-- Current when CPU is idle --> - <item name="cpu.idle">0.1</item> - <!-- Current at each CPU speed, as per 'cpu.speeds' --> - <array name="cpu.active"> + + <!-- Current at each CPU speed for cluster 0, as per 'cpu.speeds.cluster0'. + Like cpu.speeds.cluster0, there must be one of these present for + each heterogeneous CPU cluster. --> + <array name="cpu.active.cluster0"> <value>0.1</value> <!-- ~100mA --> </array> + + <!-- Current when CPU is idle --> + <item name="cpu.idle">0.1</item> + <!-- This is the battery capacity in mAh (measured at nominal voltage) --> <item name="battery.capacity">1000</item> |