diff options
| -rw-r--r-- | api/current.xml | 24 | ||||
| -rw-r--r-- | cmds/keystore/commands.c | 2 | ||||
| -rw-r--r-- | cmds/keystore/keystore.c | 45 | ||||
| -rw-r--r-- | core/java/android/app/SearchManager.java | 10 | ||||
| -rw-r--r-- | core/java/android/app/SuggestionsAdapter.java | 71 | ||||
| -rw-r--r-- | core/java/android/server/search/SearchableInfo.java | 16 | ||||
| -rwxr-xr-x | core/java/android/speech/tts/TextToSpeech.java (renamed from core/java/android/speech/tts/Tts.java) | 141 | ||||
| -rw-r--r-- | core/java/android/widget/AutoCompleteTextView.java | 9 | ||||
| -rw-r--r-- | core/jni/android_location_GpsLocationProvider.cpp | 7 | ||||
| -rw-r--r-- | core/res/res/values/attrs.xml | 8 | ||||
| -rw-r--r-- | core/res/res/values/public.xml | 1 | ||||
| -rw-r--r-- | docs/html/search.jd | 2 | ||||
| -rw-r--r-- | keystore/java/android/security/Keystore.java | 103 | ||||
| -rw-r--r-- | keystore/java/android/security/ServiceCommand.java | 178 | ||||
| -rw-r--r-- | location/java/com/android/internal/location/GpsLocationProvider.java | 7 |
15 files changed, 472 insertions, 152 deletions
diff --git a/api/current.xml b/api/current.xml index cb348e1..f30c505 100644 --- a/api/current.xml +++ b/api/current.xml @@ -3518,17 +3518,6 @@ visibility="public" > </field> -<field name="donut_resource_pad30" - type="int" - transient="false" - volatile="false" - value="16843394" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> <field name="donut_resource_pad4" type="int" transient="false" @@ -6840,6 +6829,17 @@ visibility="public" > </field> +<field name="queryAfterZeroResults" + type="int" + transient="false" + volatile="false" + value="16843394" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="radioButtonStyle" type="int" transient="false" @@ -62837,7 +62837,7 @@ type="float" transient="false" volatile="false" - value="0.0010f" + value="0.001f" static="true" final="true" deprecated="not deprecated" diff --git a/cmds/keystore/commands.c b/cmds/keystore/commands.c index 7474d81..e53cece 100644 --- a/cmds/keystore/commands.c +++ b/cmds/keystore/commands.c @@ -40,7 +40,7 @@ static int list_files(const char *dir, char reply[REPLY_MAX]) { reply[0]=0; while ((de = readdir(d))) { if (de->d_type != DT_REG) continue; - strlcat(reply, " ", REPLY_MAX); + if (reply[0] != 0) strlcat(reply, " ", REPLY_MAX); if (strlcat(reply, de->d_name, REPLY_MAX) >= REPLY_MAX) { LOGE("reply is too long(too many files under '%s'\n", dir); return -1; diff --git a/cmds/keystore/keystore.c b/cmds/keystore/keystore.c index dbb62b3..5193b3d 100644 --- a/cmds/keystore/keystore.c +++ b/cmds/keystore/keystore.c @@ -113,7 +113,7 @@ static int execute(int s, char cmd[BUFFER_MAX]) unsigned i; unsigned n = 0; unsigned short count; - int ret = -1; + short ret = -1; /* default reply is "" */ reply[0] = 0; @@ -139,7 +139,7 @@ static int execute(int s, char cmd[BUFFER_MAX]) LOGE("%s requires %d arguments (%d given)\n", cmds[i].name, cmds[i].numargs, n); } else { - ret = cmds[i].func(arg + 1, reply); + ret = (short) cmds[i].func(arg + 1, reply); } goto done; } @@ -148,24 +148,26 @@ static int execute(int s, char cmd[BUFFER_MAX]) done: if (reply[0]) { - n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply); + strlcpy(cmd, reply, BUFFER_MAX); + count = strlen(cmd); } else { - n = snprintf(cmd, BUFFER_MAX, "%d", ret); + count = 0; + } + if (writex(s, &ret, sizeof(ret))) return -1; + if (ret == 0) { + if (writex(s, &count, sizeof(count))) return -1; + if (writex(s, cmd, count)) return -1; } - if (n > BUFFER_MAX) n = BUFFER_MAX; - count = n; - - if (writex(s, &count, sizeof(count))) return -1; - if (writex(s, cmd, count)) return -1; return 0; } int shell_command(const int argc, const char **argv) { - int fd, i, r; + int fd, i; + short ret; unsigned short count; - char cmd[BUFFER_MAX]=""; + char buf[BUFFER_MAX]=""; fd = socket_local_client(SOCKET_PATH, ANDROID_SOCKET_NAMESPACE_RESERVED, @@ -175,19 +177,24 @@ int shell_command(const int argc, const char **argv) exit(1); } for(i = 0; i < argc; i++) { - if (i > 0) strlcat(cmd, " ", BUFFER_MAX); - if(strlcat(cmd, argv[i], BUFFER_MAX) >= BUFFER_MAX) { + if (i > 0) strlcat(buf, " ", BUFFER_MAX); + if(strlcat(buf, argv[i], BUFFER_MAX) >= BUFFER_MAX) { fprintf(stderr, "Arguments are too long\n"); exit(1); } } - count = strlen(cmd); + count = strlen(buf); if (writex(fd, &count, sizeof(count))) return -1; - if (writex(fd, cmd, strlen(cmd))) return -1; - if (readx(fd, &count, sizeof(count))) return -1; - if (readx(fd, cmd, count)) return -1; - cmd[count]=0; - fprintf(stdout, "%s\n", cmd); + if (writex(fd, buf, strlen(buf))) return -1; + if (readx(fd, &ret, sizeof(ret))) return -1; + if (ret == 0) { + if (readx(fd, &count, sizeof(count))) return -1; + if (readx(fd, buf, count)) return -1; + buf[count]=0; + fprintf(stdout, "%s\n", buf); + } else { + fprintf(stderr, "Failed, please check log!\n"); + } return 0; } diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java index 3f0aa95..820f192 100644 --- a/core/java/android/app/SearchManager.java +++ b/core/java/android/app/SearchManager.java @@ -1402,6 +1402,16 @@ public class SearchManager * @hide For internal use, not part of the public API. */ public final static String SUGGEST_COLUMN_BACKGROUND_COLOR = "suggest_background_color"; + + /** + * Column name for suggestions cursor. <i>Optional.</i> This column is used to specify + * that a spinner should be shown in lieu of an icon2 while the shortcut of this suggestion + * is being refreshed. + * + * @hide Pending API council approval. + */ + public final static String SUGGEST_COLUMN_SPINNER_WHILE_REFRESHING = + "suggest_spinner_while_refreshing"; /** * Column value for suggestion column {@link #SUGGEST_COLUMN_SHORTCUT_ID} when a suggestion diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java index 6e8bd78..8c5cee3 100644 --- a/core/java/android/app/SuggestionsAdapter.java +++ b/core/java/android/app/SuggestionsAdapter.java @@ -20,16 +20,19 @@ import android.content.ContentResolver; import android.content.Context; import android.content.res.Resources.NotFoundException; import android.database.Cursor; +import android.graphics.Canvas; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.server.search.SearchableInfo; import android.text.Html; import android.text.TextUtils; +import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.ViewGroup; +import android.widget.AbsListView; import android.widget.ImageView; import android.widget.ResourceCursorAdapter; import android.widget.TextView; @@ -255,7 +258,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter { */ @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { - View v = super.newView(context, cursor, parent); + View v = new SuggestionItemView(context, cursor); v.setTag(new ChildViewCache(v)); return v; } @@ -303,7 +306,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter { if (backgroundColor == 0) { backgroundColor = mDefaultBackgroundColor; } - view.setBackgroundColor(backgroundColor); + ((SuggestionItemView)view).setColor(backgroundColor); final boolean isHtml = mFormatCol > 0 && "html".equals(cursor.getString(mFormatCol)); setViewText(cursor, views.mText1, mText1Col, isHtml); @@ -506,4 +509,68 @@ class SuggestionsAdapter extends ResourceCursorAdapter { return cursor.getString(col); } + /** + * A parent viewgroup class which holds the actual suggestion item as a child. + * + * The sole purpose of this class is to draw the given background color when the item is in + * normal state and not draw the background color when it is pressed, so that when pressed the + * list view's selection highlight will be displayed properly (if we draw our background it + * draws on top of the list view selection highlight). + */ + private class SuggestionItemView extends ViewGroup { + private int mBackgroundColor; // the background color to draw in normal state. + private View mView; // the suggestion item's view. + + protected SuggestionItemView(Context context, Cursor cursor) { + // Initialize ourselves + super(context); + + // For our layout use the default list item height from the current theme. + TypedValue lineHeight = new TypedValue(); + context.getTheme().resolveAttribute( + com.android.internal.R.attr.searchResultListItemHeight, lineHeight, true); + DisplayMetrics metrics = new DisplayMetrics(); + metrics.setToDefaults(); + AbsListView.LayoutParams layout = new AbsListView.LayoutParams( + AbsListView.LayoutParams.FILL_PARENT, + (int)lineHeight.getDimension(metrics)); + + setLayoutParams(layout); + + // Initialize the child view + mView = SuggestionsAdapter.super.newView(context, cursor, this); + if (mView != null) { + addView(mView, layout.width, layout.height); + mView.setVisibility(View.VISIBLE); + } + } + + public void setColor(int backgroundColor) { + mBackgroundColor = backgroundColor; + } + + @Override + public void dispatchDraw(Canvas canvas) { + if (!isPressed()) { + canvas.drawColor(mBackgroundColor); + } + super.dispatchDraw(canvas); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (mView != null) { + mView.measure(widthMeasureSpec, heightMeasureSpec); + } + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (mView != null) { + mView.layout(0, 0, mView.getMeasuredWidth(), mView.getMeasuredHeight()); + } + } + } + } diff --git a/core/java/android/server/search/SearchableInfo.java b/core/java/android/server/search/SearchableInfo.java index c083142..4df7368 100644 --- a/core/java/android/server/search/SearchableInfo.java +++ b/core/java/android/server/search/SearchableInfo.java @@ -66,6 +66,7 @@ public final class SearchableInfo implements Parcelable { private final int mSearchInputType; private final int mSearchImeOptions; private final boolean mIncludeInGlobalSearch; + private final boolean mQueryAfterZeroResults; private final String mSuggestAuthority; private final String mSuggestPath; private final String mSuggestSelection; @@ -276,6 +277,8 @@ public final class SearchableInfo implements Parcelable { EditorInfo.IME_ACTION_SEARCH); mIncludeInGlobalSearch = a.getBoolean( com.android.internal.R.styleable.Searchable_includeInGlobalSearch, false); + mQueryAfterZeroResults = a.getBoolean( + com.android.internal.R.styleable.Searchable_queryAfterZeroResults, false); mSuggestAuthority = a.getString( com.android.internal.R.styleable.Searchable_searchSuggestAuthority); @@ -637,6 +640,17 @@ public final class SearchableInfo implements Parcelable { } /** + * Checks whether this searchable activity should be invoked after a query returned zero + * results. + * + * @return The value of the <code>queryAfterZeroResults</code> attribute, + * or <code>false</code> if the attribute is not set. + */ + public boolean queryAfterZeroResults() { + return mQueryAfterZeroResults; + } + + /** * Support for parcelable and aidl operations. */ public static final Parcelable.Creator<SearchableInfo> CREATOR @@ -667,6 +681,7 @@ public final class SearchableInfo implements Parcelable { mSearchInputType = in.readInt(); mSearchImeOptions = in.readInt(); mIncludeInGlobalSearch = in.readInt() != 0; + mQueryAfterZeroResults = in.readInt() != 0; mSuggestAuthority = in.readString(); mSuggestPath = in.readString(); @@ -702,6 +717,7 @@ public final class SearchableInfo implements Parcelable { dest.writeInt(mSearchInputType); dest.writeInt(mSearchImeOptions); dest.writeInt(mIncludeInGlobalSearch ? 1 : 0); + dest.writeInt(mQueryAfterZeroResults ? 1 : 0); dest.writeString(mSuggestAuthority); dest.writeString(mSuggestPath); diff --git a/core/java/android/speech/tts/Tts.java b/core/java/android/speech/tts/TextToSpeech.java index 085b030..11be75d 100755 --- a/core/java/android/speech/tts/Tts.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -28,21 +28,16 @@ import android.os.IBinder; import android.os.RemoteException; import android.util.Log; +import java.util.HashMap; + /** * - * Synthesizes speech from text. This abstracts away the complexities of using - * the TTS service such as setting up the IBinder connection and handling - * RemoteExceptions, etc. - * - * The TTS should always be safe the use; if the user does not have the - * necessary TTS apk installed, the behavior is that all calls to the TTS act as - * no-ops. + * Synthesizes speech from text. * * {@hide} */ -//FIXME #TTS# review + complete javadoc -//FIXME RENAME TO TextToSpeech.java -public class Tts { +//TODO #TTS# review + complete javadoc +public class TextToSpeech { /** @@ -82,31 +77,6 @@ public class Tts { private OnSpeechCompletedListener speechCompletedCallback = null; - /** - * The constructor for the TTS. - * - * @param context - * The context - * @param callback - * The InitListener that should be called when the TTS has - * initialized successfully. - * @param displayInstallMessage - * Boolean indicating whether or not an installation prompt - * should be displayed to users who do not have the TTS library. - * If this is true, a generic alert asking the user to install - * the TTS will be used. If you wish to specify the exact message - * of that prompt, please use TTS(Context context, InitListener - * callback, TTSVersionAlert alert) as the constructor instead. - */ - public Tts(Context context, OnInitListener callback, - boolean displayInstallMessage) { - showInstaller = displayInstallMessage; - ctx = context; - cb = callback; - if (dataFilesCheck()) { - initTts(); - } - } /** * The constructor for the TTS. @@ -117,15 +87,13 @@ public class Tts { * The InitListener that should be called when the TTS has * initialized successfully. */ - public Tts(Context context, OnInitListener callback) { - // FIXME #TTS# support TtsVersionAlert + public TextToSpeech(Context context, OnInitListener callback) { + // TODO #TTS# support TtsVersionAlert // showInstaller = true; // versionAlert = alert; ctx = context; cb = callback; - if (dataFilesCheck()) { - initTts(); - } + initTts(); } @@ -136,9 +104,9 @@ public class Tts { private boolean dataFilesCheck() { - // FIXME #TTS# config manager will be in settings + // TODO #TTS# config manager will be in settings Log.i("TTS_FIXME", "FIXME in Tts: config manager will be in settings"); - // FIXME #TTS# implement checking of the correct installation of + // TODO #TTS# implement checking of the correct installation of // the data files. return true; @@ -193,15 +161,9 @@ public class Tts { Intent intent = new Intent("android.intent.action.USE_TTS"); intent.addCategory("android.intent.category.TTS"); - // Binding will fail only if the TTS doesn't exist; - // the TTSVersionAlert will give users a chance to install - // the needed TTS. - if (!ctx.bindService(intent, serviceConnection, - Context.BIND_AUTO_CREATE)) { - if (showInstaller) { - // FIXME #TTS# show version alert - } - } + ctx.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); + // TODO handle case where the binding works (should always work) but + // the plugin fails } @@ -316,21 +278,18 @@ public class Tts { * The queuing strategy to use. Use 0 for no queuing, and 1 for * queuing. * @param params - * The array of speech parameters to be used. Currently, only - * params[0] is defined - it is for setting the type of voice if - * the engine allows it. Possible values are "VOICE_MALE", - * "VOICE_FEMALE", and "VOICE_ROBOT". Note that right now only - * the pre-recorded voice has this support - this setting has no - * effect on eSpeak. + * The hashmap of speech parameters to be used. */ - public void speak(String text, int queueMode, String[] params) { + public void speak(String text, int queueMode, HashMap<String,String> params) + { synchronized (startLock) { Log.i("TTS received: ", text); if (!started) { return; } try { - itts.speak(text, queueMode, params); + // TODO support extra parameters, passing null for the moment + itts.speak(text, queueMode, null); } catch (RemoteException e) { // TTS died; restart it. started = false; @@ -357,15 +316,17 @@ public class Tts { * 0 for no queue (interrupts all previous utterances), 1 for * queued * @param params - * An ArrayList of parameters. + * The hashmap of parameters to be used. */ - public void playEarcon(String earcon, int queueMode, String[] params) { + public void playEarcon(String earcon, int queueMode, + HashMap<String,String> params) { synchronized (startLock) { if (!started) { return; } try { - itts.playEarcon(earcon, queueMode, params); + // TODO support extra parameters, passing null for the moment + itts.playEarcon(earcon, queueMode, null); } catch (RemoteException e) { // TTS died; restart it. started = false; @@ -381,6 +342,11 @@ public class Tts { } } } + + + public void playSilence(long durationInMs, int queueMode) { + // TODO implement, already present in TTS service + } /** @@ -440,17 +406,6 @@ public class Tts { } - /** - * Returns the version number of the TTS library that the user has - * installed. - * - * @return The version number of the TTS library that the user has - * installed. - */ - public int getVersion() { - return version; - } - /** * Sets the speech rate for the TTS engine. @@ -519,21 +474,21 @@ public class Tts { * @param text * The String of text that should be synthesized * @param params - * An ArrayList of parameters. The first element of this array - * controls the type of voice to use. + * A hashmap of parameters. * @param filename * The string that gives the full output filename; it should be * something like "/sdcard/myappsounds/mysound.wav". * @return A boolean that indicates if the synthesis succeeded */ - public boolean synthesizeToFile(String text, String[] params, + public boolean synthesizeToFile(String text, HashMap<String,String> params, String filename) { synchronized (startLock) { if (!started) { return false; } try { - return itts.synthesizeToFile(text, params, filename); + // TODO support extra parameters, passing null for the moment + return itts.synthesizeToFile(text, null, filename); } catch (RemoteException e) { // TTS died; restart it. started = false; @@ -552,36 +507,4 @@ public class Tts { } - /** - * Displays an alert that prompts users to install the TTS engine. - * This is useful if the application expects a newer version - * of the TTS than what the user has. - */ - public void showVersionAlert() { - if (!started) { - return; - } - // FIXME #TTS# implement show version alert - } - - - /** - * Checks if the TTS service is installed or not - * - * @return A boolean that indicates whether the TTS service is installed - */ - // TODO: TTS Service itself will always be installed. Factor this out - // (may need to add another method to see if there are any working - // TTS engines on the device). - public static boolean isInstalled(Context ctx) { - PackageManager pm = ctx.getPackageManager(); - Intent intent = new Intent("android.intent.action.USE_TTS"); - intent.addCategory("android.intent.category.TTS"); - ResolveInfo info = pm.resolveService(intent, 0); - if (info == null) { - return false; - } - return true; - } - } diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java index f376ce5..585ce3d 100644 --- a/core/java/android/widget/AutoCompleteTextView.java +++ b/core/java/android/widget/AutoCompleteTextView.java @@ -123,10 +123,6 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe private AutoCompleteTextView.ListSelectorHider mHideSelector; - // Indicates whether this AutoCompleteTextView is attached to a window or not - // The widget is attached to a window when mAttachCount > 0 - private int mAttachCount; - private AutoCompleteTextView.PassThroughClickListener mPassThroughClickListener; public AutoCompleteTextView(Context context) { @@ -960,7 +956,8 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe /** {@inheritDoc} */ public void onFilterComplete(int count) { - if (mAttachCount <= 0) return; + // Not attached to window, don't update drop-down + if (getWindowVisibility() == View.GONE) return; /* * This checks enoughToFilter() again because filtering requests @@ -999,13 +996,11 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - mAttachCount++; } @Override protected void onDetachedFromWindow() { dismissDropDown(); - mAttachCount--; super.onDetachedFromWindow(); } diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp index 0858741..5c4fb22 100644 --- a/core/jni/android_location_GpsLocationProvider.cpp +++ b/core/jni/android_location_GpsLocationProvider.cpp @@ -270,6 +270,12 @@ static void android_location_GpsLocationProvider_inject_time(JNIEnv* env, jobjec sGpsInterface->inject_time(time, timeReference, uncertainty); } +static void android_location_GpsLocationProvider_inject_location(JNIEnv* env, jobject obj, + jdouble latitude, jdouble longitude, jfloat accuracy) +{ + sGpsInterface->inject_location(latitude, longitude, accuracy); +} + static jboolean android_location_GpsLocationProvider_supports_xtra(JNIEnv* env, jobject obj) { if (!sGpsXtraInterface) { @@ -353,6 +359,7 @@ static JNINativeMethod sMethods[] = { {"native_wait_for_event", "()V", (void*)android_location_GpsLocationProvider_wait_for_event}, {"native_read_sv_status", "([I[F[F[F[I)I", (void*)android_location_GpsLocationProvider_read_sv_status}, {"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time}, + {"native_inject_location", "(DDF)V", (void*)android_location_GpsLocationProvider_inject_location}, {"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra}, {"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data}, {"native_agps_data_conn_open", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_agps_data_conn_open}, diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index c13bf77..99fe9c8 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2849,6 +2849,14 @@ The default value is <code>false</code>. <i>Optional attribute.</i>. --> <attr name="includeInGlobalSearch" format="boolean" /> + <!-- If provided and <code>true</code>, this searchable activity will be invoked for all + queries in a particular session. If set to <code>false</code> and the activity + returned zero results for a query, it will not be invoked again in that session for + supersets of that zero-results query. For example, if the activity returned zero + results for "bo", it would not be queried again for "bob". + The default value is <code>false</code>. <i>Optional attribute.</i>. --> + <attr name="queryAfterZeroResults" format="boolean" /> + </declare-styleable> <!-- In order to process special action keys during search, you must define them using diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index a50f3f9..e5a58b1 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1115,6 +1115,7 @@ <public type="attr" name="backupAgent" /> <public type="attr" name="allowBackup" /> <public type="attr" name="glEsVersion" /> + <public type="attr" name="queryAfterZeroResults" /> <public-padding type="attr" name="donut_resource_pad" end="0x0101029f" /> diff --git a/docs/html/search.jd b/docs/html/search.jd index 0a802a6..defba30 100644 --- a/docs/html/search.jd +++ b/docs/html/search.jd @@ -2,7 +2,7 @@ page.title=Search Results @jd:body
<script src="http://www.google.com/jsapi" type="text/javascript"></script>
-<script src="/assets/jquery-history.js" type="text/javascript"></script>
+<script src="{@docRoot}assets/jquery-history.js" type="text/javascript"></script>
<script type="text/javascript">
google.load('search', '1');
diff --git a/keystore/java/android/security/Keystore.java b/keystore/java/android/security/Keystore.java new file mode 100644 index 0000000..3f83473 --- /dev/null +++ b/keystore/java/android/security/Keystore.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +/** + * The Keystore class provides the functions to list the certs/keys in keystore. + * {@hide} + */ +public abstract class Keystore { + private static final String TAG = "Keystore"; + private static final String[] NOTFOUND = new String[0]; + + /** + */ + public static Keystore getInstance() { + return new FileKeystore(); + } + + /** + */ + public abstract String getUserkey(String key); + + /** + */ + public abstract String getCertificate(String key); + + /** + */ + public abstract String[] getAllCertificateKeys(); + + /** + */ + public abstract String[] getAllUserkeyKeys(); + + private static class FileKeystore extends Keystore { + private static final String SERVICE_NAME = "keystore"; + private static final String LIST_CERTIFICATES = "listcerts"; + private static final String LIST_USERKEYS = "listuserkeys"; + private static final String PATH = "/data/misc/keystore/"; + private static final String USERKEY_PATH = PATH + "userkeys/"; + private static final String CERT_PATH = PATH + "certs/"; + private static final ServiceCommand mServiceCommand = + new ServiceCommand(SERVICE_NAME); + + @Override + public String getUserkey(String key) { + return USERKEY_PATH + key; + } + + @Override + public String getCertificate(String key) { + return CERT_PATH + key; + } + + /** + * Returns the array of the certificate names in keystore if successful. + * Or return an empty array if error. + * + * @return array of the certificates + */ + @Override + public String[] getAllCertificateKeys() { + try { + String result = mServiceCommand.execute(LIST_CERTIFICATES); + if (result != null) return result.split("\\s+"); + return NOTFOUND; + } catch (NumberFormatException ex) { + return NOTFOUND; + } + } + + /** + * Returns the array of the names of private keys in keystore if successful. + * Or return an empty array if errors. + * + * @return array of the user keys + */ + @Override + public String[] getAllUserkeyKeys() { + try { + String result = mServiceCommand.execute(LIST_USERKEYS); + if (result != null) return result.split("\\s+"); + return NOTFOUND; + } catch (NumberFormatException ex) { + return NOTFOUND; + } + } + } +} diff --git a/keystore/java/android/security/ServiceCommand.java b/keystore/java/android/security/ServiceCommand.java new file mode 100644 index 0000000..f1d4302 --- /dev/null +++ b/keystore/java/android/security/ServiceCommand.java @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +import android.net.LocalSocketAddress; +import android.net.LocalSocket; +import android.util.Config; +import android.util.Log; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; + +/* + * ServiceCommand is used to connect to a service throught the local socket, + * and send out the command, return the result to the caller. + * {@hide} + */ +public class ServiceCommand { + public static final String SUCCESS = "0"; + public static final String FAILED = "-1"; + + private String mServiceName; + private String mTag; + private InputStream mIn; + private OutputStream mOut; + private LocalSocket mSocket; + private static final int BUFFER_LENGTH = 1024; + + private byte buf[] = new byte[BUFFER_LENGTH]; + private int buflen = 0; + + private boolean connect() { + if (mSocket != null) { + return true; + } + Log.i(mTag, "connecting..."); + try { + mSocket = new LocalSocket(); + + LocalSocketAddress address = new LocalSocketAddress( + mServiceName, LocalSocketAddress.Namespace.RESERVED); + + mSocket.connect(address); + + mIn = mSocket.getInputStream(); + mOut = mSocket.getOutputStream(); + } catch (IOException ex) { + disconnect(); + return false; + } + return true; + } + + private void disconnect() { + Log.i(mTag,"disconnecting..."); + try { + if (mSocket != null) mSocket.close(); + } catch (IOException ex) { } + try { + if (mIn != null) mIn.close(); + } catch (IOException ex) { } + try { + if (mOut != null) mOut.close(); + } catch (IOException ex) { } + mSocket = null; + mIn = null; + mOut = null; + } + + private boolean readBytes(byte buffer[], int len) { + int off = 0, count; + if (len < 0) return false; + while (off != len) { + try { + count = mIn.read(buffer, off, len - off); + if (count <= 0) { + Log.e(mTag, "read error " + count); + break; + } + off += count; + } catch (IOException ex) { + Log.e(mTag,"read exception"); + break; + } + } + if (off == len) return true; + disconnect(); + return false; + } + + private boolean readReply() { + int len, ret; + buflen = 0; + + if (!readBytes(buf, 2)) return false; + ret = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8); + if (ret != 0) return false; + + if (!readBytes(buf, 2)) return false; + len = (((int) buf[0]) & 0xff) | ((((int) buf[1]) & 0xff) << 8); + if (len > BUFFER_LENGTH) { + Log.e(mTag,"invalid reply length (" + len + ")"); + disconnect(); + return false; + } + if (!readBytes(buf, len)) return false; + buflen = len; + return true; + } + + private boolean writeCommand(String _cmd) { + byte[] cmd = _cmd.getBytes(); + int len = cmd.length; + if ((len < 1) || (len > BUFFER_LENGTH)) return false; + buf[0] = (byte) (len & 0xff); + buf[1] = (byte) ((len >> 8) & 0xff); + try { + mOut.write(buf, 0, 2); + mOut.write(cmd, 0, len); + } catch (IOException ex) { + Log.e(mTag,"write error"); + disconnect(); + return false; + } + return true; + } + + private String executeCommand(String cmd) { + if (!writeCommand(cmd)) { + /* If service died and restarted in the background + * (unlikely but possible) we'll fail on the next + * write (this one). Try to reconnect and write + * the command one more time before giving up. + */ + Log.e(mTag, "write command failed? reconnect!"); + if (!connect() || !writeCommand(cmd)) { + return null; + } + } + if (readReply()) { + return new String(buf, 0, buflen); + } else { + return null; + } + } + + public synchronized String execute(String cmd) { + String result; + if (!connect()) { + Log.e(mTag, "connection failed"); + return null; + } + result = executeCommand(cmd); + disconnect(); + return result; + } + + public ServiceCommand(String service) { + mServiceName = service; + mTag = service; + } +} diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java index 725fbf9..9698553 100644 --- a/location/java/com/android/internal/location/GpsLocationProvider.java +++ b/location/java/com/android/internal/location/GpsLocationProvider.java @@ -410,6 +410,10 @@ public class GpsLocationProvider extends ILocationProvider.Stub { * Someday we might use this for network location injection to aid the GPS */ public void updateLocation(Location location) { + if (location.hasAccuracy()) { + native_inject_location(location.getLatitude(), location.getLongitude(), + location.getAccuracy()); + } } /** @@ -1210,7 +1214,8 @@ public class GpsLocationProvider extends ILocationProvider.Stub { // mask[0] is ephemeris mask and mask[1] is almanac mask private native int native_read_sv_status(int[] svs, float[] snrs, float[] elevations, float[] azimuths, int[] masks); - + private native void native_inject_location(double latitude, double longitude, float accuracy); + // XTRA Support private native void native_inject_time(long time, long timeReference, int uncertainty); private native boolean native_supports_xtra(); |
