summaryrefslogtreecommitdiffstats
path: root/core/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/com')
-rw-r--r--core/java/com/android/internal/app/IntentForwarderActivity.java4
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java3
-rw-r--r--core/java/com/android/internal/backup/IBackupTransport.aidl2
-rw-r--r--core/java/com/android/internal/backup/LocalTransport.java5
-rw-r--r--core/java/com/android/internal/backup/LocalTransportService.java2
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java234
6 files changed, 202 insertions, 48 deletions
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 47ef65a..01e5d40 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -35,8 +35,8 @@ import java.util.Set;
/*
- * This is used in conjunction with DevicePolicyManager.setForwardingIntents to enable intents to be
- * passed in and out of a managed profile.
+ * This is used in conjunction with the {@link setCrossProfileIntentFilter} method of
+ * {@link DevicePolicyManager} to enable intents to be passed in and out of a managed profile.
*/
public class IntentForwarderActivity extends Activity {
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 591267e..183dd05 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -484,8 +484,7 @@ public class ResolverActivity extends AlertActivity implements AdapterView.OnIte
mList.clear();
if (mBaseResolveList != null) {
- currentResolveList = mBaseResolveList;
- mOrigResolveList = null;
+ currentResolveList = mOrigResolveList = mBaseResolveList;
} else {
currentResolveList = mOrigResolveList = mPm.queryIntentActivities(
mIntent, PackageManager.MATCH_DEFAULT_ONLY
diff --git a/core/java/com/android/internal/backup/IBackupTransport.aidl b/core/java/com/android/internal/backup/IBackupTransport.aidl
index 1e37fd9..d10451b 100644
--- a/core/java/com/android/internal/backup/IBackupTransport.aidl
+++ b/core/java/com/android/internal/backup/IBackupTransport.aidl
@@ -178,7 +178,7 @@ interface IBackupTransport {
/**
* Get the data for the application returned by {@link #nextRestorePackage}.
* @param data An open, writable file into which the backup data should be stored.
- * @return the same error codes as {@link #nextRestorePackage}.
+ * @return the same error codes as {@link #startRestore}.
*/
int getRestoreData(in ParcelFileDescriptor outFd);
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 446ef55..f2b29ef 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -18,6 +18,7 @@ package com.android.internal.backup;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
+import android.app.backup.BackupTransport;
import android.app.backup.RestoreSet;
import android.content.ComponentName;
import android.content.Context;
@@ -47,7 +48,7 @@ import static android.system.OsConstants.*;
* later restoring from there. For testing only.
*/
-public class LocalTransport extends IBackupTransport.Stub {
+public class LocalTransport extends BackupTransport {
private static final String TAG = "LocalTransport";
private static final boolean DEBUG = true;
@@ -217,7 +218,7 @@ public class LocalTransport extends IBackupTransport.Stub {
// Restore handling
static final long[] POSSIBLE_SETS = { 2, 3, 4, 5, 6, 7, 8, 9 };
- public RestoreSet[] getAvailableRestoreSets() throws android.os.RemoteException {
+ public RestoreSet[] getAvailableRestoreSets() {
long[] existing = new long[POSSIBLE_SETS.length + 1];
int num = 0;
diff --git a/core/java/com/android/internal/backup/LocalTransportService.java b/core/java/com/android/internal/backup/LocalTransportService.java
index d05699a..77ac313 100644
--- a/core/java/com/android/internal/backup/LocalTransportService.java
+++ b/core/java/com/android/internal/backup/LocalTransportService.java
@@ -32,6 +32,6 @@ public class LocalTransportService extends Service {
@Override
public IBinder onBind(Intent intent) {
- return sTransport;
+ return sTransport.getBinder();
}
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
index 495d5c6..df96488 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -19,6 +19,7 @@ package com.android.internal.inputmethod;
import android.content.Context;
import android.content.pm.PackageManager;
import android.text.TextUtils;
+import android.util.Log;
import android.util.Slog;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
@@ -211,54 +212,196 @@ public class InputMethodSubtypeSwitchingController {
}
}
- private final InputMethodSettings mSettings;
- private InputMethodAndSubtypeList mSubtypeList;
+ private static int calculateSubtypeId(InputMethodInfo imi, InputMethodSubtype subtype) {
+ return subtype != null ? InputMethodUtils.getSubtypeIdFromHashCode(imi,
+ subtype.hashCode()) : NOT_A_SUBTYPE_ID;
+ }
- @VisibleForTesting
- public static ImeSubtypeListItem getNextInputMethodLockedImpl(List<ImeSubtypeListItem> imList,
- boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) {
- if (imi == null) {
- return null;
+ private static class StaticRotationList {
+ private final List<ImeSubtypeListItem> mImeSubtypeList;
+ public StaticRotationList(final List<ImeSubtypeListItem> imeSubtypeList) {
+ mImeSubtypeList = imeSubtypeList;
}
- if (imList.size() <= 1) {
- return null;
+
+ /**
+ * Returns the index of the specified input method and subtype in the given list.
+ * @param imi The {@link InputMethodInfo} to be searched.
+ * @param subtype The {@link InputMethodSubtype} to be searched. null if the input method
+ * does not have a subtype.
+ * @return The index in the given list. -1 if not found.
+ */
+ private int getIndex(InputMethodInfo imi, InputMethodSubtype subtype) {
+ final int currentSubtypeId = calculateSubtypeId(imi, subtype);
+ final int N = mImeSubtypeList.size();
+ for (int i = 0; i < N; ++i) {
+ final ImeSubtypeListItem isli = mImeSubtypeList.get(i);
+ // Skip until the current IME/subtype is found.
+ if (imi.equals(isli.mImi) && isli.mSubtypeId == currentSubtypeId) {
+ return i;
+ }
+ }
+ return -1;
}
- // Here we have two rotation groups, depending on the returned boolean value of
- // {@link InputMethodInfo#supportsSwitchingToNextInputMethod()}.
- final boolean expectedValueOfSupportsSwitchingToNextInputMethod =
- imi.supportsSwitchingToNextInputMethod();
- final int N = imList.size();
- final int currentSubtypeId =
- subtype != null ? InputMethodUtils.getSubtypeIdFromHashCode(imi,
- subtype.hashCode()) : NOT_A_SUBTYPE_ID;
- for (int i = 0; i < N; ++i) {
- final ImeSubtypeListItem isli = imList.get(i);
- // Skip until the current IME/subtype is found.
- if (!isli.mImi.equals(imi) || isli.mSubtypeId != currentSubtypeId) {
- continue;
+
+ public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme,
+ InputMethodInfo imi, InputMethodSubtype subtype) {
+ if (imi == null) {
+ return null;
}
- // Found the current IME/subtype. Start searching the next IME/subtype from here.
- for (int j = 0; j < N - 1; ++j) {
- final ImeSubtypeListItem candidate = imList.get((i + j + 1) % N);
- // Skip if the candidate doesn't belong to the expected rotation group.
- if (expectedValueOfSupportsSwitchingToNextInputMethod !=
- candidate.mImi.supportsSwitchingToNextInputMethod()) {
- continue;
- }
+ if (mImeSubtypeList.size() <= 1) {
+ return null;
+ }
+ final int currentIndex = getIndex(imi, subtype);
+ if (currentIndex < 0) {
+ return null;
+ }
+ final int N = mImeSubtypeList.size();
+ for (int offset = 1; offset < N; ++offset) {
+ // Start searching the next IME/subtype from the next of the current index.
+ final int candidateIndex = (currentIndex + offset) % N;
+ final ImeSubtypeListItem candidate = mImeSubtypeList.get(candidateIndex);
// Skip if searching inside the current IME only, but the candidate is not
// the current IME.
- if (onlyCurrentIme && !candidate.mImi.equals(imi)) {
+ if (onlyCurrentIme && !imi.equals(candidate.mImi)) {
continue;
}
return candidate;
}
- // No appropriate IME/subtype is found in the list. Give up.
return null;
}
- // The current IME/subtype is not found in the list. Give up.
- return null;
}
+ private static class DynamicRotationList {
+ private static final String TAG = DynamicRotationList.class.getSimpleName();
+ private final List<ImeSubtypeListItem> mImeSubtypeList;
+ private final int[] mUsageHistoryOfSubtypeListItemIndex;
+
+ public DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) {
+ mImeSubtypeList = imeSubtypeListItems;
+ mUsageHistoryOfSubtypeListItemIndex = new int[mImeSubtypeList.size()];
+ final int N = mImeSubtypeList.size();
+ for (int i = 0; i < N; i++) {
+ mUsageHistoryOfSubtypeListItemIndex[i] = i;
+ }
+ }
+
+ /**
+ * Returns the index of the specified object in
+ * {@link #mUsageHistoryOfSubtypeListItemIndex}.
+ * <p>We call the index of {@link #mUsageHistoryOfSubtypeListItemIndex} as "Usage Rank"
+ * so as not to be confused with the index in {@link #mImeSubtypeList}.
+ * @return -1 when the specified item doesn't belong to {@link #mImeSubtypeList} actually.
+ */
+ private int getUsageRank(final InputMethodInfo imi, InputMethodSubtype subtype) {
+ final int currentSubtypeId = calculateSubtypeId(imi, subtype);
+ final int N = mUsageHistoryOfSubtypeListItemIndex.length;
+ for (int usageRank = 0; usageRank < N; usageRank++) {
+ final int subtypeListItemIndex = mUsageHistoryOfSubtypeListItemIndex[usageRank];
+ final ImeSubtypeListItem subtypeListItem =
+ mImeSubtypeList.get(subtypeListItemIndex);
+ if (subtypeListItem.mImi.equals(imi) &&
+ subtypeListItem.mSubtypeId == currentSubtypeId) {
+ return usageRank;
+ }
+ }
+ // Not found in the known IME/Subtype list.
+ return -1;
+ }
+
+ public void onUserAction(InputMethodInfo imi, InputMethodSubtype subtype) {
+ final int currentUsageRank = getUsageRank(imi, subtype);
+ // Do nothing if currentUsageRank == -1 (not found), or currentUsageRank == 0
+ if (currentUsageRank <= 0) {
+ return;
+ }
+ final int currentItemIndex = mUsageHistoryOfSubtypeListItemIndex[currentUsageRank];
+ System.arraycopy(mUsageHistoryOfSubtypeListItemIndex, 0,
+ mUsageHistoryOfSubtypeListItemIndex, 1, currentUsageRank);
+ mUsageHistoryOfSubtypeListItemIndex[0] = currentItemIndex;
+ }
+
+ public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme,
+ InputMethodInfo imi, InputMethodSubtype subtype) {
+ int currentUsageRank = getUsageRank(imi, subtype);
+ if (currentUsageRank < 0) {
+ if (DEBUG) {
+ Slog.d(TAG, "IME/subtype is not found: " + imi.getId() + ", " + subtype);
+ }
+ return null;
+ }
+ final int N = mUsageHistoryOfSubtypeListItemIndex.length;
+ for (int i = 1; i < N; i++) {
+ final int subtypeListItemRank = (currentUsageRank + i) % N;
+ final int subtypeListItemIndex =
+ mUsageHistoryOfSubtypeListItemIndex[subtypeListItemRank];
+ final ImeSubtypeListItem subtypeListItem =
+ mImeSubtypeList.get(subtypeListItemIndex);
+ if (onlyCurrentIme && !imi.equals(subtypeListItem.mImi)) {
+ continue;
+ }
+ return subtypeListItem;
+ }
+ return null;
+ }
+ }
+
+ @VisibleForTesting
+ public static class ControllerImpl {
+ // TODO: Switch to DynamicRotationList for smarter rotation.
+ private final StaticRotationList mSwitchingAwareSubtypeList;
+ private final StaticRotationList mSwitchingUnawareSubtypeList;
+
+ public ControllerImpl(final List<ImeSubtypeListItem> sortedItems) {
+ mSwitchingAwareSubtypeList = new StaticRotationList(filterImeSubtypeList(sortedItems,
+ true /* supportsSwitchingToNextInputMethod */));
+ mSwitchingUnawareSubtypeList = new StaticRotationList(filterImeSubtypeList(sortedItems,
+ false /* supportsSwitchingToNextInputMethod */));
+ }
+
+ public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, InputMethodInfo imi,
+ InputMethodSubtype subtype) {
+ if (imi == null) {
+ return null;
+ }
+ if (imi.supportsSwitchingToNextInputMethod()) {
+ return mSwitchingAwareSubtypeList.getNextInputMethodLocked(onlyCurrentIme, imi,
+ subtype);
+ } else {
+ return mSwitchingUnawareSubtypeList.getNextInputMethodLocked(onlyCurrentIme, imi,
+ subtype);
+ }
+ }
+
+ public void onUserActionLocked(InputMethodInfo imi, InputMethodSubtype subtype) {
+ if (imi == null) {
+ return;
+ }
+ // TODO: Enable the following code when DynamicRotationList is enabled.
+ // if (imi.supportsSwitchingToNextInputMethod()) {
+ // mSwitchingAwareSubtypeList.onUserAction(imi, subtype);
+ // }
+ }
+
+ private static List<ImeSubtypeListItem> filterImeSubtypeList(
+ final List<ImeSubtypeListItem> items,
+ final boolean supportsSwitchingToNextInputMethod) {
+ final ArrayList<ImeSubtypeListItem> result = new ArrayList<>();
+ final int ALL_ITEMS_COUNT = items.size();
+ for (int i = 0; i < ALL_ITEMS_COUNT; i++) {
+ final ImeSubtypeListItem item = items.get(i);
+ if (item.mImi.supportsSwitchingToNextInputMethod() ==
+ supportsSwitchingToNextInputMethod) {
+ result.add(item);
+ }
+ }
+ return result;
+ }
+ }
+
+ private final InputMethodSettings mSettings;
+ private InputMethodAndSubtypeList mSubtypeList;
+ private ControllerImpl mController;
+
private InputMethodSubtypeSwitchingController(InputMethodSettings settings, Context context) {
mSettings = settings;
resetCircularListLocked(context);
@@ -269,19 +412,30 @@ public class InputMethodSubtypeSwitchingController {
return new InputMethodSubtypeSwitchingController(settings, context);
}
- // TODO: write unit tests for this method and the logic that determines the next subtype
public void onCommitTextLocked(InputMethodInfo imi, InputMethodSubtype subtype) {
- // TODO: Implement this.
+ if (mController == null) {
+ if (DEBUG) {
+ Log.e(TAG, "mController shouldn't be null.");
+ }
+ return;
+ }
+ mController.onUserActionLocked(imi, subtype);
}
public void resetCircularListLocked(Context context) {
mSubtypeList = new InputMethodAndSubtypeList(context, mSettings);
+ mController = new ControllerImpl(mSubtypeList.getSortedInputMethodAndSubtypeList());
}
- public ImeSubtypeListItem getNextInputMethodLocked(
- boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) {
- return getNextInputMethodLockedImpl(mSubtypeList.getSortedInputMethodAndSubtypeList(),
- onlyCurrentIme, imi, subtype);
+ public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi,
+ InputMethodSubtype subtype) {
+ if (mController == null) {
+ if (DEBUG) {
+ Log.e(TAG, "mController shouldn't be null.");
+ }
+ return null;
+ }
+ return mController.getNextInputMethod(onlyCurrentIme, imi, subtype);
}
public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeListLocked(boolean showSubtypes,