From 991357fe25b3addabf85b871df3f4098fc4b833b Mon Sep 17 00:00:00 2001 From: Adam Lesinski Date: Tue, 10 May 2016 14:00:03 -0700 Subject: [PATCH] BluetoothManager: Make requestControllerActivityInfo one call Instead of making multiple calls into the Bluetooth service, make one call that can timeout. This helps prevent cases when the Bluetooth process hangs and the system_server is calling into it and causes a WATCHDOG restart. Bug:28658141 Change-Id: I37778b7b6e508be420a21bdf23593ae89b38f5b8 --- .../android/bluetooth/BluetoothAdapter.java | 40 ++--- core/java/android/bluetooth/IBluetooth.aidl | 1 - .../android/content/res/ResourcesImpl.java | 167 +++++++++--------- .../server/am/BatteryStatsService.java | 4 +- 4 files changed, 100 insertions(+), 112 deletions(-) diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java index e74847711bdcc..d036d96257ef9 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -472,12 +472,6 @@ public final class BluetoothAdapter { private static final int ADDRESS_LENGTH = 17; - private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 30; - /** @hide */ - public static final int ACTIVITY_ENERGY_INFO_CACHED = 0; - /** @hide */ - public static final int ACTIVITY_ENERGY_INFO_REFRESHED = 1; - /** * Lazily initialized singleton. Guaranteed final after first object * constructed. @@ -1374,13 +1368,13 @@ public final class BluetoothAdapter { * @return a record with {@link BluetoothActivityEnergyInfo} or null if * report is unavailable or unsupported * @deprecated use the asynchronous - * {@link #requestControllerActivityEnergyInfo(int, ResultReceiver)} instead. + * {@link #requestControllerActivityEnergyInfo(ResultReceiver)} instead. * @hide */ @Deprecated public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) { SynchronousResultReceiver receiver = new SynchronousResultReceiver(); - requestControllerActivityEnergyInfo(updateType, receiver); + requestControllerActivityEnergyInfo(receiver); try { SynchronousResultReceiver.Result result = receiver.awaitResult(1000); if (result.bundle != null) { @@ -1400,34 +1394,24 @@ public final class BluetoothAdapter { * A null value for the activity info object may be sent if the bluetooth service is * unreachable or the device does not support reporting such information. * - * @param updateType Type of info, cached vs refreshed. * @param result The callback to which to send the activity info. * @hide */ - public void requestControllerActivityEnergyInfo(int updateType, ResultReceiver result) { - if (getState() != STATE_ON) { - result.send(0, null); - return; - } - + public void requestControllerActivityEnergyInfo(ResultReceiver result) { try { - if (!mService.isActivityAndEnergyReportingSupported()) { - result.send(0, null); - return; - } - synchronized(this) { - if (updateType == ACTIVITY_ENERGY_INFO_REFRESHED) { - mService.getActivityEnergyInfoFromController(); - wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS); + synchronized(mManagerCallback) { + if (mService != null) { + mService.requestActivityInfo(result); + result = null; } - mService.requestActivityInfo(result); } - } catch (InterruptedException e) { - Log.e(TAG, "getControllerActivityEnergyInfoCallback wait interrupted: " + e); - result.send(0, null); } catch (RemoteException e) { Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e); - result.send(0, null); + } finally { + if (result != null) { + // Only send an immediate result if we failed. + result.send(0, null); + } } } diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl index 45d864150d745..a420539636780 100644 --- a/core/java/android/bluetooth/IBluetooth.aidl +++ b/core/java/android/bluetooth/IBluetooth.aidl @@ -102,7 +102,6 @@ interface IBluetooth boolean isOffloadedFilteringSupported(); boolean isOffloadedScanBatchingSupported(); boolean isActivityAndEnergyReportingSupported(); - void getActivityEnergyInfoFromController(); BluetoothActivityEnergyInfo reportActivityInfo(); /** diff --git a/core/java/android/content/res/ResourcesImpl.java b/core/java/android/content/res/ResourcesImpl.java index a36401098e274..110df5d76aaca 100644 --- a/core/java/android/content/res/ResourcesImpl.java +++ b/core/java/android/content/res/ResourcesImpl.java @@ -309,90 +309,97 @@ public class ResourcesImpl { public void updateConfiguration(Configuration config, DisplayMetrics metrics, CompatibilityInfo compat) { - synchronized (mAccessLock) { - if (false) { - Slog.i(TAG, "**** Updating config of " + this + ": old config is " - + mConfiguration + " old compat is " + mCompatibilityInfo); - Slog.i(TAG, "**** Updating config of " + this + ": new config is " - + config + " new compat is " + compat); - } - if (compat != null) { - mCompatibilityInfo = compat; - } - if (metrics != null) { - mMetrics.setTo(metrics); - } - // NOTE: We should re-arrange this code to create a Display - // with the CompatibilityInfo that is used everywhere we deal - // with the display in relation to this app, rather than - // doing the conversion here. This impl should be okay because - // we make sure to return a compatible display in the places - // where there are public APIs to retrieve the display... but - // it would be cleaner and more maintainble to just be - // consistently dealing with a compatible display everywhere in - // the framework. - mCompatibilityInfo.applyToDisplayMetrics(mMetrics); + Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesImpl#updateConfiguration"); + try { + synchronized (mAccessLock) { + if (false) { + Slog.i(TAG, "**** Updating config of " + this + ": old config is " + + mConfiguration + " old compat is " + mCompatibilityInfo); + Slog.i(TAG, "**** Updating config of " + this + ": new config is " + + config + " new compat is " + compat); + } + if (compat != null) { + mCompatibilityInfo = compat; + } + if (metrics != null) { + mMetrics.setTo(metrics); + } + // NOTE: We should re-arrange this code to create a Display + // with the CompatibilityInfo that is used everywhere we deal + // with the display in relation to this app, rather than + // doing the conversion here. This impl should be okay because + // we make sure to return a compatible display in the places + // where there are public APIs to retrieve the display... but + // it would be cleaner and more maintainble to just be + // consistently dealing with a compatible display everywhere in + // the framework. + mCompatibilityInfo.applyToDisplayMetrics(mMetrics); - final @Config int configChanges = calcConfigChanges(config); + final @Config int configChanges = calcConfigChanges(config); - LocaleList locales = mConfiguration.getLocales(); - if (locales.isEmpty()) { - locales = LocaleList.getAdjustedDefault(); - mConfiguration.setLocales(locales); + LocaleList locales = mConfiguration.getLocales(); + if (locales.isEmpty()) { + locales = LocaleList.getAdjustedDefault(); + mConfiguration.setLocales(locales); + } + if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) { + mMetrics.densityDpi = mConfiguration.densityDpi; + mMetrics.density = + mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; + } + mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale; + + final int width, height; + if (mMetrics.widthPixels >= mMetrics.heightPixels) { + width = mMetrics.widthPixels; + height = mMetrics.heightPixels; + } else { + //noinspection SuspiciousNameCombination + width = mMetrics.heightPixels; + //noinspection SuspiciousNameCombination + height = mMetrics.widthPixels; + } + + final int keyboardHidden; + if (mConfiguration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO + && mConfiguration.hardKeyboardHidden + == Configuration.HARDKEYBOARDHIDDEN_YES) { + keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT; + } else { + keyboardHidden = mConfiguration.keyboardHidden; + } + + mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc, + adjustLanguageTag(locales.get(0).toLanguageTag()), + mConfiguration.orientation, + mConfiguration.touchscreen, + mConfiguration.densityDpi, mConfiguration.keyboard, + keyboardHidden, mConfiguration.navigation, width, height, + mConfiguration.smallestScreenWidthDp, + mConfiguration.screenWidthDp, mConfiguration.screenHeightDp, + mConfiguration.screenLayout, mConfiguration.uiMode, + Build.VERSION.RESOURCES_SDK_INT); + + if (DEBUG_CONFIG) { + Slog.i(TAG, "**** Updating config of " + this + ": final config is " + + mConfiguration + " final compat is " + mCompatibilityInfo); + } + + mDrawableCache.onConfigurationChange(configChanges); + mColorDrawableCache.onConfigurationChange(configChanges); + mComplexColorCache.onConfigurationChange(configChanges); + mAnimatorCache.onConfigurationChange(configChanges); + mStateListAnimatorCache.onConfigurationChange(configChanges); + + flushLayoutCache(); } - if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) { - mMetrics.densityDpi = mConfiguration.densityDpi; - mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; - } - mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale; - - final int width, height; - if (mMetrics.widthPixels >= mMetrics.heightPixels) { - width = mMetrics.widthPixels; - height = mMetrics.heightPixels; - } else { - //noinspection SuspiciousNameCombination - width = mMetrics.heightPixels; - //noinspection SuspiciousNameCombination - height = mMetrics.widthPixels; - } - - final int keyboardHidden; - if (mConfiguration.keyboardHidden == Configuration.KEYBOARDHIDDEN_NO - && mConfiguration.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) { - keyboardHidden = Configuration.KEYBOARDHIDDEN_SOFT; - } else { - keyboardHidden = mConfiguration.keyboardHidden; - } - - mAssets.setConfiguration(mConfiguration.mcc, mConfiguration.mnc, - adjustLanguageTag(locales.get(0).toLanguageTag()), - mConfiguration.orientation, - mConfiguration.touchscreen, - mConfiguration.densityDpi, mConfiguration.keyboard, - keyboardHidden, mConfiguration.navigation, width, height, - mConfiguration.smallestScreenWidthDp, - mConfiguration.screenWidthDp, mConfiguration.screenHeightDp, - mConfiguration.screenLayout, mConfiguration.uiMode, - Build.VERSION.RESOURCES_SDK_INT); - - if (DEBUG_CONFIG) { - Slog.i(TAG, "**** Updating config of " + this + ": final config is " - + mConfiguration + " final compat is " + mCompatibilityInfo); - } - - mDrawableCache.onConfigurationChange(configChanges); - mColorDrawableCache.onConfigurationChange(configChanges); - mComplexColorCache.onConfigurationChange(configChanges); - mAnimatorCache.onConfigurationChange(configChanges); - mStateListAnimatorCache.onConfigurationChange(configChanges); - - flushLayoutCache(); - } - synchronized (sSync) { - if (mPluralRule != null) { - mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0)); + synchronized (sSync) { + if (mPluralRule != null) { + mPluralRule = PluralRules.forLocale(mConfiguration.getLocales().get(0)); + } } + } finally { + Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); } } diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index d34ec868dc1c0..3eacf7aa96734 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -1448,9 +1448,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter != null) { bluetoothReceiver = new SynchronousResultReceiver(); - adapter.requestControllerActivityEnergyInfo( - BluetoothAdapter.ACTIVITY_ENERGY_INFO_REFRESHED, - bluetoothReceiver); + adapter.requestControllerActivityEnergyInfo(bluetoothReceiver); } }