Loading core/res/res/values/config.xml +4 −4 Original line number Diff line number Diff line Loading @@ -577,11 +577,11 @@ <!-- True if WallpaperService is enabled --> <bool name="config_enableWallpaperService">true</bool> <!-- Component name of the service providing network location support. --> <string name="config_networkLocationProvider" translatable="false">@null</string> <!-- Package name providing network location support. --> <string name="config_networkLocationProviderPackageName" translatable="false">@null</string> <!-- Component name of the service providing geocoder API support. --> <string name="config_geocodeProvider" translatable="false">@null</string> <!-- Package name providing geocoder API support. --> <string name="config_geocodeProviderPackageName" translatable="false">@null</string> <!-- Boolean indicating if current platform supports bluetooth SCO for off call use cases --> Loading core/res/res/values/public.xml +2 −2 Original line number Diff line number Diff line Loading @@ -1460,8 +1460,8 @@ <java-symbol type="string" name="car_mode_disable_notification_title" /> <java-symbol type="string" name="chooser_wallpaper" /> <java-symbol type="string" name="config_datause_iface" /> <java-symbol type="string" name="config_geocodeProvider" /> <java-symbol type="string" name="config_networkLocationProvider" /> <java-symbol type="string" name="config_geocodeProviderPackageName" /> <java-symbol type="string" name="config_networkLocationProviderPackageName" /> <java-symbol type="string" name="config_wimaxManagerClassname" /> <java-symbol type="string" name="config_wimaxNativeLibLocation" /> <java-symbol type="string" name="config_wimaxServiceClassname" /> Loading services/java/com/android/server/LocationManagerService.java +108 −25 Original line number Diff line number Diff line Loading @@ -26,7 +26,11 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.content.res.Resources; import android.database.Cursor; import android.location.Address; Loading Loading @@ -123,8 +127,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run private static boolean sProvidersLoaded = false; private final Context mContext; private final String mNetworkLocationProviderPackageName; private final String mGeocodeProviderPackageName; private PackageManager mPackageManager; // final after initialize() private String mNetworkLocationProviderPackageName; // only used on handler thread private String mGeocodeProviderPackageName; // only used on handler thread private GeocoderProxy mGeocodeProvider; private IGpsStatusProvider mGpsStatusProvider; private INetInitiatedListener mNetInitiatedListener; Loading Loading @@ -490,25 +495,78 @@ public class LocationManagerService extends ILocationManager.Stub implements Run addProvider(passiveProvider); mEnabledProviders.add(passiveProvider.getName()); // initialize external network location and geocoder services PackageManager pm = mContext.getPackageManager(); if (mNetworkLocationProviderPackageName != null && pm.resolveService(new Intent(mNetworkLocationProviderPackageName), 0) != null) { mNetworkLocationProvider = new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER, mNetworkLocationProviderPackageName, mLocationHandler); // initialize external network location and geocoder services. // The initial value of mNetworkLocationProviderPackageName and // mGeocodeProviderPackageName is just used to determine what // signatures future mNetworkLocationProviderPackageName and // mGeocodeProviderPackageName packages must have. So alternate // providers can be installed under a different package name // so long as they have the same signature as the original // provider packages. if (mNetworkLocationProviderPackageName != null) { String packageName = findBestPackage(LocationProviderProxy.SERVICE_ACTION, mNetworkLocationProviderPackageName); if (packageName != null) { mNetworkLocationProvider = new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER, packageName, mLocationHandler); mNetworkLocationProviderPackageName = packageName; addProvider(mNetworkLocationProvider); } if (mGeocodeProviderPackageName != null && pm.resolveService(new Intent(mGeocodeProviderPackageName), 0) != null) { mGeocodeProvider = new GeocoderProxy(mContext, mGeocodeProviderPackageName); } if (mGeocodeProviderPackageName != null) { String packageName = findBestPackage(GeocoderProxy.SERVICE_ACTION, mGeocodeProviderPackageName); if (packageName != null) { mGeocodeProvider = new GeocoderProxy(mContext, packageName); mGeocodeProviderPackageName = packageName; } } updateProvidersLocked(); } /** * Pick the best (network location provider or geocode provider) package. * The best package: * - implements serviceIntentName * - has signatures that match that of sigPackageName * - has the highest version value in a meta-data field in the service component */ String findBestPackage(String serviceIntentName, String sigPackageName) { Intent intent = new Intent(serviceIntentName); List<ResolveInfo> infos = mPackageManager.queryIntentServices(intent, PackageManager.GET_META_DATA); if (infos == null) return null; int bestVersion = Integer.MIN_VALUE; String bestPackage = null; for (ResolveInfo info : infos) { String packageName = info.serviceInfo.packageName; // check signature if (mPackageManager.checkSignatures(packageName, sigPackageName) != PackageManager.SIGNATURE_MATCH) { Slog.w(TAG, packageName + " implements " + serviceIntentName + " but its signatures don't match those in " + sigPackageName + ", ignoring"); continue; } // read version int version = 0; if (info.serviceInfo.metaData != null) { version = info.serviceInfo.metaData.getInt("version", 0); } if (LOCAL_LOGV) Slog.v(TAG, packageName + " implements " + serviceIntentName + " with version " + version); if (version > bestVersion) { bestVersion = version; bestPackage = packageName; } } return bestPackage; } /** * @param context the context that the LocationManagerService runs in */ Loading @@ -516,10 +574,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run super(); mContext = context; Resources resources = context.getResources(); mNetworkLocationProviderPackageName = resources.getString( com.android.internal.R.string.config_networkLocationProvider); com.android.internal.R.string.config_networkLocationProviderPackageName); mGeocodeProviderPackageName = resources.getString( com.android.internal.R.string.config_geocodeProvider); com.android.internal.R.string.config_geocodeProviderPackageName); mPackageMonitor.register(context, null, true); if (LOCAL_LOGV) { Loading @@ -537,6 +597,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // Create a wake lock, needs to be done before calling loadProviders() below PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); mPackageManager = mContext.getPackageManager(); // Load providers loadProviders(); Loading Loading @@ -1886,16 +1947,33 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } else if (msg.what == MESSAGE_PACKAGE_UPDATED) { String packageName = (String) msg.obj; String packageDot = packageName + "."; // reconnect to external providers after their packages have been updated if (mNetworkLocationProvider != null && mNetworkLocationProviderPackageName.startsWith(packageDot)) { mNetworkLocationProvider.reconnect(); // reconnect to external providers if there is a better package if (mNetworkLocationProviderPackageName != null && mPackageManager.resolveService( new Intent(LocationProviderProxy.SERVICE_ACTION) .setPackage(packageName), 0) != null) { // package implements service, perform full check String bestPackage = findBestPackage( LocationProviderProxy.SERVICE_ACTION, mNetworkLocationProviderPackageName); if (packageName.equals(bestPackage)) { mNetworkLocationProvider.reconnect(bestPackage); mNetworkLocationProviderPackageName = packageName; } } if (mGeocodeProviderPackageName != null && mPackageManager.resolveService( new Intent(GeocoderProxy.SERVICE_ACTION) .setPackage(packageName), 0) != null) { // package implements service, perform full check String bestPackage = findBestPackage( GeocoderProxy.SERVICE_ACTION, mGeocodeProviderPackageName); if (packageName.equals(bestPackage)) { mGeocodeProvider.reconnect(bestPackage); mGeocodeProviderPackageName = packageName; } if (mGeocodeProvider != null && mGeocodeProviderPackageName.startsWith(packageDot)) { mGeocodeProvider.reconnect(); } } } catch (Exception e) { Loading Loading @@ -2004,6 +2082,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // Called by main thread; divert work to LocationWorker. Message.obtain(mLocationHandler, MESSAGE_PACKAGE_UPDATED, packageName).sendToTarget(); } @Override public void onPackageAdded(String packageName, int uid) { // Called by main thread; divert work to LocationWorker. Message.obtain(mLocationHandler, MESSAGE_PACKAGE_UPDATED, packageName).sendToTarget(); } }; // Wake locks Loading services/java/com/android/server/location/GeocoderProxy.java +13 −12 Original line number Diff line number Diff line Loading @@ -39,27 +39,28 @@ public class GeocoderProxy { private static final String TAG = "GeocoderProxy"; public static final String SERVICE_ACTION = "com.android.location.service.GeocodeProvider"; private final Context mContext; private final Intent mIntent; private final Object mMutex = new Object(); // synchronizes access to mServiceConnection private Connection mServiceConnection = new Connection(); // never null private Connection mServiceConnection; // never null after ctor public GeocoderProxy(Context context, String serviceName) { public GeocoderProxy(Context context, String packageName) { mContext = context; mIntent = new Intent(serviceName); mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT); mIntent = new Intent(SERVICE_ACTION); reconnect(packageName); } /** * When unbundled NetworkLocationService package is updated, we * need to unbind from the old version and re-bind to the new one. */ public void reconnect() { /** Bind to service. Will reconnect if already connected */ public void reconnect(String packageName) { synchronized (mMutex) { if (mServiceConnection != null) { mContext.unbindService(mServiceConnection); } mServiceConnection = new Connection(); mIntent.setPackage(packageName); mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT); Loading services/java/com/android/server/location/LocationProviderProxy.java +15 −14 Original line number Diff line number Diff line Loading @@ -42,12 +42,15 @@ public class LocationProviderProxy implements LocationProviderInterface { private static final String TAG = "LocationProviderProxy"; public static final String SERVICE_ACTION = "com.android.location.service.NetworkLocationProvider"; private final Context mContext; private final String mName; private final Intent mIntent; private final Handler mHandler; private final Object mMutex = new Object(); // synchronizes access to non-final members private Connection mServiceConnection = new Connection(); // never null private Connection mServiceConnection; // never null after ctor // cached values set by the location manager private boolean mLocationTracking = false; Loading @@ -58,28 +61,26 @@ public class LocationProviderProxy implements LocationProviderInterface { private NetworkInfo mNetworkInfo; // constructor for proxying location providers implemented in a separate service public LocationProviderProxy(Context context, String name, String serviceName, public LocationProviderProxy(Context context, String name, String packageName, Handler handler) { mContext = context; mName = name; mIntent = new Intent(serviceName); mIntent = new Intent(SERVICE_ACTION); mHandler = handler; mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT); reconnect(packageName); } /** * When unbundled NetworkLocationService package is updated, we * need to unbind from the old version and re-bind to the new one. */ public void reconnect() { /** Bind to service. Will reconnect if already connected */ public void reconnect(String packageName) { synchronized (mMutex) { if (mServiceConnection != null) { mContext.unbindService(mServiceConnection); } mServiceConnection = new Connection(); mIntent.setPackage(packageName); mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT); Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT); } } Loading Loading
core/res/res/values/config.xml +4 −4 Original line number Diff line number Diff line Loading @@ -577,11 +577,11 @@ <!-- True if WallpaperService is enabled --> <bool name="config_enableWallpaperService">true</bool> <!-- Component name of the service providing network location support. --> <string name="config_networkLocationProvider" translatable="false">@null</string> <!-- Package name providing network location support. --> <string name="config_networkLocationProviderPackageName" translatable="false">@null</string> <!-- Component name of the service providing geocoder API support. --> <string name="config_geocodeProvider" translatable="false">@null</string> <!-- Package name providing geocoder API support. --> <string name="config_geocodeProviderPackageName" translatable="false">@null</string> <!-- Boolean indicating if current platform supports bluetooth SCO for off call use cases --> Loading
core/res/res/values/public.xml +2 −2 Original line number Diff line number Diff line Loading @@ -1460,8 +1460,8 @@ <java-symbol type="string" name="car_mode_disable_notification_title" /> <java-symbol type="string" name="chooser_wallpaper" /> <java-symbol type="string" name="config_datause_iface" /> <java-symbol type="string" name="config_geocodeProvider" /> <java-symbol type="string" name="config_networkLocationProvider" /> <java-symbol type="string" name="config_geocodeProviderPackageName" /> <java-symbol type="string" name="config_networkLocationProviderPackageName" /> <java-symbol type="string" name="config_wimaxManagerClassname" /> <java-symbol type="string" name="config_wimaxNativeLibLocation" /> <java-symbol type="string" name="config_wimaxServiceClassname" /> Loading
services/java/com/android/server/LocationManagerService.java +108 −25 Original line number Diff line number Diff line Loading @@ -26,7 +26,11 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.Signature; import android.content.res.Resources; import android.database.Cursor; import android.location.Address; Loading Loading @@ -123,8 +127,9 @@ public class LocationManagerService extends ILocationManager.Stub implements Run private static boolean sProvidersLoaded = false; private final Context mContext; private final String mNetworkLocationProviderPackageName; private final String mGeocodeProviderPackageName; private PackageManager mPackageManager; // final after initialize() private String mNetworkLocationProviderPackageName; // only used on handler thread private String mGeocodeProviderPackageName; // only used on handler thread private GeocoderProxy mGeocodeProvider; private IGpsStatusProvider mGpsStatusProvider; private INetInitiatedListener mNetInitiatedListener; Loading Loading @@ -490,25 +495,78 @@ public class LocationManagerService extends ILocationManager.Stub implements Run addProvider(passiveProvider); mEnabledProviders.add(passiveProvider.getName()); // initialize external network location and geocoder services PackageManager pm = mContext.getPackageManager(); if (mNetworkLocationProviderPackageName != null && pm.resolveService(new Intent(mNetworkLocationProviderPackageName), 0) != null) { mNetworkLocationProvider = new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER, mNetworkLocationProviderPackageName, mLocationHandler); // initialize external network location and geocoder services. // The initial value of mNetworkLocationProviderPackageName and // mGeocodeProviderPackageName is just used to determine what // signatures future mNetworkLocationProviderPackageName and // mGeocodeProviderPackageName packages must have. So alternate // providers can be installed under a different package name // so long as they have the same signature as the original // provider packages. if (mNetworkLocationProviderPackageName != null) { String packageName = findBestPackage(LocationProviderProxy.SERVICE_ACTION, mNetworkLocationProviderPackageName); if (packageName != null) { mNetworkLocationProvider = new LocationProviderProxy(mContext, LocationManager.NETWORK_PROVIDER, packageName, mLocationHandler); mNetworkLocationProviderPackageName = packageName; addProvider(mNetworkLocationProvider); } if (mGeocodeProviderPackageName != null && pm.resolveService(new Intent(mGeocodeProviderPackageName), 0) != null) { mGeocodeProvider = new GeocoderProxy(mContext, mGeocodeProviderPackageName); } if (mGeocodeProviderPackageName != null) { String packageName = findBestPackage(GeocoderProxy.SERVICE_ACTION, mGeocodeProviderPackageName); if (packageName != null) { mGeocodeProvider = new GeocoderProxy(mContext, packageName); mGeocodeProviderPackageName = packageName; } } updateProvidersLocked(); } /** * Pick the best (network location provider or geocode provider) package. * The best package: * - implements serviceIntentName * - has signatures that match that of sigPackageName * - has the highest version value in a meta-data field in the service component */ String findBestPackage(String serviceIntentName, String sigPackageName) { Intent intent = new Intent(serviceIntentName); List<ResolveInfo> infos = mPackageManager.queryIntentServices(intent, PackageManager.GET_META_DATA); if (infos == null) return null; int bestVersion = Integer.MIN_VALUE; String bestPackage = null; for (ResolveInfo info : infos) { String packageName = info.serviceInfo.packageName; // check signature if (mPackageManager.checkSignatures(packageName, sigPackageName) != PackageManager.SIGNATURE_MATCH) { Slog.w(TAG, packageName + " implements " + serviceIntentName + " but its signatures don't match those in " + sigPackageName + ", ignoring"); continue; } // read version int version = 0; if (info.serviceInfo.metaData != null) { version = info.serviceInfo.metaData.getInt("version", 0); } if (LOCAL_LOGV) Slog.v(TAG, packageName + " implements " + serviceIntentName + " with version " + version); if (version > bestVersion) { bestVersion = version; bestPackage = packageName; } } return bestPackage; } /** * @param context the context that the LocationManagerService runs in */ Loading @@ -516,10 +574,12 @@ public class LocationManagerService extends ILocationManager.Stub implements Run super(); mContext = context; Resources resources = context.getResources(); mNetworkLocationProviderPackageName = resources.getString( com.android.internal.R.string.config_networkLocationProvider); com.android.internal.R.string.config_networkLocationProviderPackageName); mGeocodeProviderPackageName = resources.getString( com.android.internal.R.string.config_geocodeProvider); com.android.internal.R.string.config_geocodeProviderPackageName); mPackageMonitor.register(context, null, true); if (LOCAL_LOGV) { Loading @@ -537,6 +597,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // Create a wake lock, needs to be done before calling loadProviders() below PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY); mPackageManager = mContext.getPackageManager(); // Load providers loadProviders(); Loading Loading @@ -1886,16 +1947,33 @@ public class LocationManagerService extends ILocationManager.Stub implements Run } } else if (msg.what == MESSAGE_PACKAGE_UPDATED) { String packageName = (String) msg.obj; String packageDot = packageName + "."; // reconnect to external providers after their packages have been updated if (mNetworkLocationProvider != null && mNetworkLocationProviderPackageName.startsWith(packageDot)) { mNetworkLocationProvider.reconnect(); // reconnect to external providers if there is a better package if (mNetworkLocationProviderPackageName != null && mPackageManager.resolveService( new Intent(LocationProviderProxy.SERVICE_ACTION) .setPackage(packageName), 0) != null) { // package implements service, perform full check String bestPackage = findBestPackage( LocationProviderProxy.SERVICE_ACTION, mNetworkLocationProviderPackageName); if (packageName.equals(bestPackage)) { mNetworkLocationProvider.reconnect(bestPackage); mNetworkLocationProviderPackageName = packageName; } } if (mGeocodeProviderPackageName != null && mPackageManager.resolveService( new Intent(GeocoderProxy.SERVICE_ACTION) .setPackage(packageName), 0) != null) { // package implements service, perform full check String bestPackage = findBestPackage( GeocoderProxy.SERVICE_ACTION, mGeocodeProviderPackageName); if (packageName.equals(bestPackage)) { mGeocodeProvider.reconnect(bestPackage); mGeocodeProviderPackageName = packageName; } if (mGeocodeProvider != null && mGeocodeProviderPackageName.startsWith(packageDot)) { mGeocodeProvider.reconnect(); } } } catch (Exception e) { Loading Loading @@ -2004,6 +2082,11 @@ public class LocationManagerService extends ILocationManager.Stub implements Run // Called by main thread; divert work to LocationWorker. Message.obtain(mLocationHandler, MESSAGE_PACKAGE_UPDATED, packageName).sendToTarget(); } @Override public void onPackageAdded(String packageName, int uid) { // Called by main thread; divert work to LocationWorker. Message.obtain(mLocationHandler, MESSAGE_PACKAGE_UPDATED, packageName).sendToTarget(); } }; // Wake locks Loading
services/java/com/android/server/location/GeocoderProxy.java +13 −12 Original line number Diff line number Diff line Loading @@ -39,27 +39,28 @@ public class GeocoderProxy { private static final String TAG = "GeocoderProxy"; public static final String SERVICE_ACTION = "com.android.location.service.GeocodeProvider"; private final Context mContext; private final Intent mIntent; private final Object mMutex = new Object(); // synchronizes access to mServiceConnection private Connection mServiceConnection = new Connection(); // never null private Connection mServiceConnection; // never null after ctor public GeocoderProxy(Context context, String serviceName) { public GeocoderProxy(Context context, String packageName) { mContext = context; mIntent = new Intent(serviceName); mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT); mIntent = new Intent(SERVICE_ACTION); reconnect(packageName); } /** * When unbundled NetworkLocationService package is updated, we * need to unbind from the old version and re-bind to the new one. */ public void reconnect() { /** Bind to service. Will reconnect if already connected */ public void reconnect(String packageName) { synchronized (mMutex) { if (mServiceConnection != null) { mContext.unbindService(mServiceConnection); } mServiceConnection = new Connection(); mIntent.setPackage(packageName); mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT); Loading
services/java/com/android/server/location/LocationProviderProxy.java +15 −14 Original line number Diff line number Diff line Loading @@ -42,12 +42,15 @@ public class LocationProviderProxy implements LocationProviderInterface { private static final String TAG = "LocationProviderProxy"; public static final String SERVICE_ACTION = "com.android.location.service.NetworkLocationProvider"; private final Context mContext; private final String mName; private final Intent mIntent; private final Handler mHandler; private final Object mMutex = new Object(); // synchronizes access to non-final members private Connection mServiceConnection = new Connection(); // never null private Connection mServiceConnection; // never null after ctor // cached values set by the location manager private boolean mLocationTracking = false; Loading @@ -58,28 +61,26 @@ public class LocationProviderProxy implements LocationProviderInterface { private NetworkInfo mNetworkInfo; // constructor for proxying location providers implemented in a separate service public LocationProviderProxy(Context context, String name, String serviceName, public LocationProviderProxy(Context context, String name, String packageName, Handler handler) { mContext = context; mName = name; mIntent = new Intent(serviceName); mIntent = new Intent(SERVICE_ACTION); mHandler = handler; mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT); reconnect(packageName); } /** * When unbundled NetworkLocationService package is updated, we * need to unbind from the old version and re-bind to the new one. */ public void reconnect() { /** Bind to service. Will reconnect if already connected */ public void reconnect(String packageName) { synchronized (mMutex) { if (mServiceConnection != null) { mContext.unbindService(mServiceConnection); } mServiceConnection = new Connection(); mIntent.setPackage(packageName); mContext.bindService(mIntent, mServiceConnection, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT); Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_ALLOW_OOM_MANAGEMENT); } } Loading