Merge "Regional: Customize date and time format and accessibility services"
diff --git a/cmds/idmap/scan.cpp b/cmds/idmap/scan.cpp
index 612a7eb..3f61b62 100644
--- a/cmds/idmap/scan.cpp
+++ b/cmds/idmap/scan.cpp
@@ -25,8 +25,7 @@
bool operator<(Overlay const& rhs) const
{
- // Note: order is reversed by design
- return rhs.priority < priority;
+ return rhs.priority > priority;
}
String8 apk_path;
@@ -165,6 +164,62 @@
delete dataMap;
return priority;
}
+
+ int idmap_scan(const char *overlay_dir, const char *target_package_name,
+ const char *target_apk_path, const char *idmap_dir,
+ SortedVector<Overlay>& overlayVector)
+ {
+ DIR *dir = opendir(overlay_dir);
+ if (dir == NULL) {
+ return EXIT_FAILURE;
+ }
+
+ struct dirent *dirent;
+ while ((dirent = readdir(dir)) != NULL) {
+ struct stat st;
+ char overlay_apk_path[PATH_MAX + 1];
+ snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
+ if (stat(overlay_apk_path, &st) < 0) {
+ continue;
+ }
+ if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode)) {
+ continue;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ String8 dir_name = String8(overlay_apk_path).getPathLeaf();
+ if (dir_name == "." || dir_name == "..") {
+ // Skip the "." and ".." dir.
+ continue;
+ }
+ idmap_scan(overlay_apk_path, target_package_name, target_apk_path, idmap_dir,
+ overlayVector);
+ } else {
+ int priority = parse_apk(overlay_apk_path, target_package_name);
+ if (priority < 0) {
+ continue;
+ }
+
+ String8 idmap_path(idmap_dir);
+ idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
+ idmap_path.append("@idmap");
+
+ if (idmap_create_path(target_apk_path, overlay_apk_path,
+ idmap_path.string()) != 0) {
+ ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
+ target_apk_path, overlay_apk_path, idmap_path.string());
+ continue;
+ }
+
+ Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
+ overlayVector.add(overlay);
+ }
+ }
+
+ closedir(dir);
+
+ return EXIT_SUCCESS;
+ }
}
int idmap_scan(const char *overlay_dir, const char *target_package_name,
@@ -176,48 +231,13 @@
return EXIT_FAILURE;
}
- DIR *dir = opendir(overlay_dir);
- if (dir == NULL) {
- return EXIT_FAILURE;
- }
-
SortedVector<Overlay> overlayVector;
- struct dirent *dirent;
- while ((dirent = readdir(dir)) != NULL) {
- struct stat st;
- char overlay_apk_path[PATH_MAX + 1];
- snprintf(overlay_apk_path, PATH_MAX, "%s/%s", overlay_dir, dirent->d_name);
- if (stat(overlay_apk_path, &st) < 0) {
- continue;
- }
- if (!S_ISREG(st.st_mode)) {
- continue;
- }
+ int res = idmap_scan(overlay_dir, target_package_name, target_apk_path, idmap_dir,
+ overlayVector);
- int priority = parse_apk(overlay_apk_path, target_package_name);
- if (priority < 0) {
- continue;
- }
-
- String8 idmap_path(idmap_dir);
- idmap_path.appendPath(flatten_path(overlay_apk_path + 1));
- idmap_path.append("@idmap");
-
- if (idmap_create_path(target_apk_path, overlay_apk_path, idmap_path.string()) != 0) {
- ALOGE("error: failed to create idmap for target=%s overlay=%s idmap=%s\n",
- target_apk_path, overlay_apk_path, idmap_path.string());
- continue;
- }
-
- Overlay overlay(String8(overlay_apk_path), idmap_path, priority);
- overlayVector.add(overlay);
- }
-
- closedir(dir);
-
- if (!writePackagesList(filename.string(), overlayVector)) {
+ if (res == EXIT_FAILURE || !writePackagesList(filename.string(), overlayVector)) {
return EXIT_FAILURE;
}
- return EXIT_SUCCESS;
+ return res;
}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 8d96f5c..17b662a 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -612,7 +612,9 @@
public final int addAssetPath(String path) {
synchronized (this) {
int res = addAssetPathNative(path);
- makeStringBlocks(mStringBlocks);
+ if (mStringBlocks != null) {
+ makeStringBlocks(mStringBlocks);
+ }
return res;
}
}
@@ -627,11 +629,12 @@
*
* {@hide}
*/
-
public final int addOverlayPath(String idmapPath) {
synchronized (this) {
int res = addOverlayPathNative(idmapPath);
- makeStringBlocks(mStringBlocks);
+ if (mStringBlocks != null) {
+ makeStringBlocks(mStringBlocks);
+ }
return res;
}
}
diff --git a/include/androidfw/AssetManager.h b/include/androidfw/AssetManager.h
index 0cfd2b1..0cfc270 100644
--- a/include/androidfw/AssetManager.h
+++ b/include/androidfw/AssetManager.h
@@ -280,7 +280,7 @@
const ResTable* getResTable(bool required = true) const;
void setLocaleLocked(const char* locale);
void updateResourceParamsLocked() const;
- bool appendPathToResTable(const asset_path& ap) const;
+ bool appendPathToResTable(const asset_path& ap, size_t* entryIdx) const;
Asset* openIdmapLocked(const struct asset_path& ap) const;
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 2dc1c96..4f62204 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -224,6 +224,11 @@
mAssetPaths.add(ap);
+ if (mResources != NULL) {
+ size_t index = mAssetPaths.size() - 1;
+ appendPathToResTable(ap, &index);
+ }
+
// new paths are always added at the end
if (cookie) {
*cookie = static_cast<int32_t>(mAssetPaths.size());
@@ -237,10 +242,6 @@
}
#endif
- if (mResources != NULL) {
- appendPathToResTable(ap);
- }
-
return true;
}
@@ -303,7 +304,8 @@
*cookie = static_cast<int32_t>(mAssetPaths.size());
if (mResources != NULL) {
- appendPathToResTable(oap);
+ size_t index = mAssetPaths.size() - 1;
+ appendPathToResTable(oap, &index);
}
return true;
@@ -610,7 +612,7 @@
return kFileTypeRegular;
}
-bool AssetManager::appendPathToResTable(const asset_path& ap) const {
+bool AssetManager::appendPathToResTable(const asset_path& ap, size_t* entryIdx) const {
// skip those ap's that correspond to system overlays
if (ap.isSystemOverlay) {
return true;
@@ -622,17 +624,16 @@
bool onlyEmptyResources = true;
MY_TRACE_BEGIN(ap.path.string());
Asset* idmap = openIdmapLocked(ap);
- size_t nextEntryIdx = mResources->getTableCount();
ALOGV("Looking for resource asset in '%s'\n", ap.path.string());
if (ap.type != kFileTypeDirectory) {
- if (nextEntryIdx == 0) {
+ if (*entryIdx == 0) {
// The first item is typically the framework resources,
// which we want to avoid parsing every time.
sharedRes = const_cast<AssetManager*>(this)->
mZipSet.getZipResourceTable(ap.path);
if (sharedRes != NULL) {
// skip ahead the number of system overlay packages preloaded
- nextEntryIdx = sharedRes->getTableCount();
+ *entryIdx += sharedRes->getTableCount() - 1;
}
}
if (sharedRes == NULL) {
@@ -650,20 +651,20 @@
}
}
- if (nextEntryIdx == 0 && ass != NULL) {
+ if (*entryIdx == 0 && ass != NULL) {
// If this is the first resource table in the asset
// manager, then we are going to cache it so that we
// can quickly copy it out for others.
ALOGV("Creating shared resources for %s", ap.path.string());
sharedRes = new ResTable();
- sharedRes->add(ass, idmap, nextEntryIdx + 1, false);
+ sharedRes->add(ass, idmap, *entryIdx + 1, false);
#ifdef HAVE_ANDROID_OS
const char* data = getenv("ANDROID_DATA");
LOG_ALWAYS_FATAL_IF(data == NULL, "ANDROID_DATA not set");
String8 overlaysListPath(data);
overlaysListPath.appendPath(kResourceCache);
overlaysListPath.appendPath("overlays.list");
- addSystemOverlays(overlaysListPath.string(), ap.path, sharedRes, nextEntryIdx);
+ addSystemOverlays(overlaysListPath.string(), ap.path, sharedRes, *entryIdx);
#endif
sharedRes = const_cast<AssetManager*>(this)->
mZipSet.setZipResourceTable(ap.path, sharedRes);
@@ -685,7 +686,7 @@
mResources->add(sharedRes);
} else {
ALOGV("Parsing resources for %s", ap.path.string());
- mResources->add(ass, idmap, nextEntryIdx + 1, !shared);
+ mResources->add(ass, idmap, *entryIdx + 1, !shared);
}
onlyEmptyResources = false;
@@ -694,7 +695,7 @@
}
} else {
ALOGV("Installing empty resources in to table %p\n", mResources);
- mResources->addEmpty(nextEntryIdx + 1);
+ mResources->addEmpty(*entryIdx + 1);
}
if (idmap != NULL) {
@@ -734,7 +735,7 @@
bool onlyEmptyResources = true;
const size_t N = mAssetPaths.size();
for (size_t i=0; i<N; i++) {
- bool empty = appendPathToResTable(mAssetPaths.itemAt(i));
+ bool empty = appendPathToResTable(mAssetPaths.itemAt(i), &i);
onlyEmptyResources = onlyEmptyResources && empty;
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index f6d787c..9207f0a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -135,6 +135,8 @@
if (newProfileState == BluetoothProfile.STATE_CONNECTED) {
if (profile instanceof MapProfile) {
profile.setPreferred(mDevice, true);
+ mRemovedProfiles.remove(profile);
+ mProfiles.add(profile);
} else if (!mProfiles.contains(profile)) {
mRemovedProfiles.remove(profile);
mProfiles.add(profile);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
old mode 100755
new mode 100644
index 6a7890f..3876468
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothProfileManager.java
@@ -24,6 +24,7 @@
import android.bluetooth.BluetoothInputDevice;
import android.bluetooth.BluetoothPan;
import android.bluetooth.BluetoothDun;
+import android.bluetooth.BluetoothPbap;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothUuid;
import android.content.Context;
@@ -126,15 +127,17 @@
addProfile(mMapProfile, MapProfile.NAME,
BluetoothMap.ACTION_CONNECTION_STATE_CHANGED);
- // enable DUN only if the property is set
+ // enable DUN only if the property is set
if (SystemProperties.getBoolean("ro.bluetooth.dun", false) == true) {
mDunProfile = new DunServerProfile(context);
addProfile(mDunProfile, DunServerProfile.NAME,
BluetoothDun.ACTION_CONNECTION_STATE_CHANGED);
}
- //Create PBAP server profile, but do not add it to list of profiles
- // as we do not need to monitor the profile as part of profile list
+
+ //Create PBAP server profile
mPbapProfile = new PbapServerProfile(context);
+ addProfile(mPbapProfile, PbapServerProfile.NAME,
+ BluetoothPbap.PBAP_STATE_CHANGED_ACTION);
if (DEBUG) Log.d(TAG, "LocalBluetoothProfileManager construction complete");
}
@@ -411,6 +414,13 @@
removedProfiles.remove(mMapProfile);
mMapProfile.setPreferred(device, true);
}
+
+ if ((mPbapProfile != null) &&
+ (mPbapProfile.getConnectionStatus(device) == BluetoothProfile.STATE_CONNECTED)) {
+ profiles.add(mPbapProfile);
+ removedProfiles.remove(mPbapProfile);
+ mPbapProfile.setPreferred(device, true);
+ }
}
}
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index be8a03e..c0a1e5c 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -213,6 +213,19 @@
<!-- Default for Settings.Secure.NFC_PAYMENT_COMPONENT -->
<string name="def_nfc_payment_component"></string>
+ <!--
+ Default Input Method, its value is from inputmethod's package name and main class name
+ such as "com.android.inputmethod.pinyin/.PinyinIME"
+ -->
+ <string name="def_input_method" translatable="false"></string>
+
+ <!--
+ Default Enable InputMethods, its value is from inputmethod's package name and main class
+ name such as "com.android.inputmethod.pinyin/.PinyinIME" ;This is a string
+ containing the IDs of all enabled input methods, each ID separated by ':'.
+ -->
+ <string name="def_enable_input_methods" translatable="false"></string>
+
<!-- custom system sound or not -->
<bool name="def_custom_sys_volume">false</bool>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index f10695f..5d2229f 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2144,6 +2144,25 @@
SettingsState.SYSTEM_PACKAGE_NAME);
}
+ // Allow openmarket OEMs to set default customized
+ defaultComponent
+ = getContext().getResources().getString(R.string.def_input_method);
+ if (!TextUtils.isEmpty(defaultComponent)) {
+ secureSettings.insertSettingLocked(
+ Settings.Secure.DEFAULT_INPUT_METHOD,
+ defaultComponent,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+
+ defaultComponent = getContext().getResources()
+ .getString(R.string.def_enable_input_methods);
+ if (!TextUtils.isEmpty(defaultComponent)) {
+ secureSettings.insertSettingLocked(
+ Settings.Secure.ENABLED_INPUT_METHODS,
+ defaultComponent,
+ SettingsState.SYSTEM_PACKAGE_NAME);
+ }
+
// Allow OEMs to set volumes in resources.
if (getContext().getResources().getBoolean(R.bool.def_custom_sys_volume)) {
final SettingsState systemSettings = getSystemSettingsLocked(userId);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index b87e109..e037bad 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -121,6 +121,10 @@
// at the same time.
final int mMaxStartingBackground;
+ // Flag to reschedule the services during app launch. Disable by default.
+ private static final boolean SERVICE_RESCHEDULE
+ = SystemProperties.getBoolean("ro.am.reschedule_service", false);
+
final SparseArray<ServiceMap> mServiceMap = new SparseArray<>();
/**
@@ -1229,6 +1233,14 @@
r.pendingStarts.add(0, si);
long dur = SystemClock.uptimeMillis() - si.deliveredTime;
dur *= 2;
+ if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) {
+ Slog.w(TAG,"Can add more delay !!!"
+ +" si.deliveredTime "+si.deliveredTime
+ +" dur "+dur
+ +" si.deliveryCount "+si.deliveryCount
+ +" si.doneExecutingCount "+si.doneExecutingCount
+ +" allowCancel "+allowCancel);
+ }
if (minDuration < dur) minDuration = dur;
if (resetTime < dur) resetTime = dur;
} else {
@@ -1241,6 +1253,13 @@
}
r.totalRestartCount++;
+ if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) {
+ Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration
+ +" resetTime "+resetTime+" now "+now
+ +" r.restartDelay "+r.restartDelay
+ +" r.restartTime+resetTime "+(r.restartTime+resetTime)
+ +" allowCancel "+allowCancel);
+ }
if (r.restartDelay == 0) {
r.restartCount++;
r.restartDelay = minDuration;
@@ -1262,6 +1281,14 @@
}
r.nextRestartTime = now + r.restartDelay;
+ if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) {
+ Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration
+ +" resetTime "+resetTime+" now "+now
+ +" r.restartDelay "+r.restartDelay
+ +" r.restartTime+resetTime "+(r.restartTime+resetTime)
+ +" r.nextRestartTime "+r.nextRestartTime
+ +" allowCancel "+allowCancel);
+ }
// Make sure that we don't end up restarting a bunch of services
// all at the same time.
@@ -1304,6 +1331,15 @@
r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay;
Slog.w(TAG, "Scheduling restart of crashed service "
+ r.shortName + " in " + r.restartDelay + "ms");
+
+ if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) {
+ for (int i=mRestartingServices.size()-1; i>=0; i--) {
+ ServiceRecord r2 = mRestartingServices.get(i);
+ Slog.w(TAG,"Restarting list - i "+i+" r2.nextRestartTime "
+ +r2.nextRestartTime+" r2.name "+r2.name);
+ }
+ }
+
EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART,
r.userId, r.shortName, r.restartDelay);
@@ -1315,7 +1351,31 @@
return;
}
try {
- bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true);
+ if(SERVICE_RESCHEDULE == true) {
+ boolean shouldDelay = false;
+ ActivityRecord top_rc = null;
+ ActivityStack stack = mAm.getFocusedStack();
+ if(stack != null) {
+ top_rc = stack.topRunningActivityLocked(null);
+ }
+ if(top_rc != null) {
+ if(!top_rc.nowVisible && !r.shortName.contains(top_rc.packageName)) {
+ shouldDelay = true;
+ }
+ }
+ if(!shouldDelay) {
+ bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true);
+ } else {
+ if (DEBUG_DELAYED_SERVICE) {
+ Slog.v(TAG, "Reschedule service restart due to app launch"
+ +" r.shortName "+r.shortName+" r.app = "+r.app);
+ }
+ r.resetRestartCounter();
+ scheduleServiceRestartLocked(r, true);
+ }
+ } else {
+ bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true);
+ }
} catch (TransactionTooLargeException e) {
// Ignore, it's been logged and nothing upstack cares.
}
@@ -1538,6 +1598,11 @@
if (newService) {
app.services.remove(r);
r.app = null;
+ if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) {
+ Slog.w(TAG, " Failed to create Service !!!! ."
+ +"This will introduce huge delay... "
+ +r.shortName + " in " + r.restartDelay + "ms");
+ }
}
// Retry.
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 3b59c94..9f94016 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -3772,6 +3772,7 @@
mConnectedBTDevicesList.add(device);
if (mConnectedBTDevicesList.size() > 1) {
Log.d(TAG, "Second device connected, add new device ");
+ return delay;
}
} else if ((state == BluetoothA2dp.STATE_DISCONNECTED) ||
(state == BluetoothA2dp.STATE_DISCONNECTING)) {
@@ -3781,9 +3782,7 @@
mConnectedBTDevicesList.remove(device);
}
if (mConnectedBTDevicesList.size() > 0) {
- Log.d(TAG, "device removed " + device.getAddress() );
- mConnectedDevices.remove(makeDeviceListKey(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP,
- device.getAddress()));
+ Log.d(TAG, "Not all are disconnected ");
return delay;
}
}
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index d5ef5a1..139ea07 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -241,6 +241,8 @@
/** EMERGENCY call failed with permanent fail cause */
public static final int EMERGENCY_PERM_FAILURE = 97;
+ public static final int NON_SELECTED_USER_CLEARING = 98;
+
//*********************************************************************************************
// When adding a disconnect type:
@@ -250,14 +252,14 @@
// 4) Update toString() with the newly added disconnect type.
// 5) Update android.telecom.DisconnectCauseUtil with any mappings to a telecom.DisconnectCause.
//
- // NextId: 98
+ // NextId: 99
//*********************************************************************************************
/** Smallest valid value for call disconnect codes. */
public static final int MINIMUM_VALID_VALUE = NOT_DISCONNECTED;
/** Largest valid value for call disconnect codes. */
- public static final int MAXIMUM_VALID_VALUE = EMERGENCY_PERM_FAILURE;
+ public static final int MAXIMUM_VALID_VALUE = NON_SELECTED_USER_CLEARING;
/** Private constructor to avoid class instantiation. */
private DisconnectCause() {
@@ -365,6 +367,8 @@
return "IMS_MERGED_SUCCESSFULLY";
case CDMA_ALREADY_ACTIVATED:
return "CDMA_ALREADY_ACTIVATED";
+ case NON_SELECTED_USER_CLEARING:
+ return "NON_SELECTED_USER_CLEARING";
case HO_NOT_FEASIBLE:
return "HO_NOT_FEASIBLE";
case NO_CIRCUIT_AVAIL: