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: