Merge "NPR's audio streams start with a 30sec segment whose mp3 headers are subtly different from those following. Allow certain bits to vary that were thought to be fixed before."
diff --git a/api/current.xml b/api/current.xml
index 442fc4f..3e8b9ac3 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -71481,6 +71481,19 @@
visibility="public"
>
</method>
+<method name="reconnect"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<exception name="IOException" type="java.io.IOException">
+</exception>
+</method>
<method name="release"
return="void"
abstract="false"
@@ -74110,7 +74123,7 @@
type="float"
transient="false"
volatile="false"
- value="0.001f"
+ value="0.0010f"
static="true"
final="true"
deprecated="not deprecated"
@@ -82150,6 +82163,210 @@
</parameter>
</method>
</interface>
+<class name="CamcorderProfile"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="get"
+ return="android.media.CamcorderProfile"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="quality" type="android.media.CamcorderProfile.Quality">
+</parameter>
+</method>
+<method name="getMmsRecordingDurationInSeconds"
+ return="int"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<field name="mAudioBitRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mAudioChannels"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mAudioCodec"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mAudioSampleRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mFileFormat"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mQuality"
+ type="android.media.CamcorderProfile.Quality"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mVideoBitRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mVideoCodec"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mVideoFrameHeight"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mVideoFrameRate"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="mVideoFrameWidth"
+ type="int"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="CamcorderProfile.Quality"
+ extends="java.lang.Enum"
+ abstract="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<method name="valueOf"
+ return="android.media.CamcorderProfile.Quality"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="name" type="java.lang.String">
+</parameter>
+</method>
+<method name="values"
+ return="android.media.CamcorderProfile.Quality[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
+<class name="CameraProfile"
+ extends="java.lang.Object"
+ abstract="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="CameraProfile"
+ type="android.media.CameraProfile"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="getImageEncodingQualityLevels"
+ return="int[]"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+</class>
<class name="ExifInterface"
extends="java.lang.Object"
abstract="false"
@@ -213929,7 +214146,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="t" type="T">
+<parameter name="arg0" type="T">
</parameter>
</method>
</interface>
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 7e9fd61..67c658d 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -311,7 +311,7 @@
doRestorePackage(arg);
} else {
try {
- long token = Long.parseLong(nextArg(), 16);
+ long token = Long.parseLong(arg, 16);
doRestoreAll(token);
} catch (NumberFormatException e) {
showUsage();
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index e2263fc..1bb1d0f 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -704,6 +704,15 @@
throws OperationCanceledException, IOException, AuthenticatorException {
Bundle bundle = getAuthToken(account, authTokenType, notifyAuthFailure, null /* callback */,
null /* handler */).getResult();
+ if (bundle == null) {
+ // This should never happen, but it does, occasionally. If it does return null to
+ // signify that we were not able to get the authtoken.
+ // TODO: remove this when the bug is found that sometimes causes a null bundle to be
+ // returned
+ Log.e(TAG, "blockingGetAuthToken: null was returned from getResult() for "
+ + account + ", authTokenType " + authTokenType);
+ return null;
+ }
return bundle.getString(KEY_AUTHTOKEN);
}
@@ -1166,6 +1175,16 @@
return this;
}
+ protected void set(Bundle bundle) {
+ // TODO: somehow a null is being set as the result of the Future. Log this
+ // case to help debug where this is occurring. When this bug is fixed this
+ // condition statement should be removed.
+ if (bundle == null) {
+ Log.e(TAG, "the bundle must not be null", new Exception());
+ }
+ super.set(bundle);
+ }
+
public abstract void doWork() throws RemoteException;
private Bundle internalGetResult(Long timeout, TimeUnit unit)
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index c2afd07..c951ce9 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -576,7 +576,14 @@
}
mVoiceButton.setVisibility(visibility);
}
-
+
+ /** Called by SuggestionsAdapter when the cursor contents changed. */
+ void onDataSetChanged() {
+ if (mSearchAutoComplete != null && mSuggestionsAdapter != null) {
+ mSearchAutoComplete.onFilterComplete(mSuggestionsAdapter.getCount());
+ }
+ }
+
/**
* Hack to determine whether this is the browser, so we can adjust the UI.
*/
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 3e11a3f..1ae9315 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -189,6 +189,8 @@
if (DBG) Log.d(LOG_TAG, "notifyDataSetChanged");
super.notifyDataSetChanged();
+ mSearchDialog.onDataSetChanged();
+
updateSpinnerState(getCursor());
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 179b807..e63851f 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1423,7 +1423,7 @@
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE =
- "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABILE";
+ "android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE";
/**
* Broadcast Action: The current system wallpaper has changed. See
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 0efcad9..85d52ec 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -137,8 +137,6 @@
* can be connected to another process.
*
* @throws IOException if the method fails.
- *
- * @hide
*/
public native final void reconnect() throws IOException;
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 6941e57..a8c6f9b 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -158,7 +158,7 @@
private synchronized SSLSocketFactory getDelegate() {
// Relax the SSL check if instructed (for this factory, or systemwide)
- if (!mSecure || ("0".equals(SystemProperties.get("ro.secure")) &&
+ if (!mSecure || ("1".equals(SystemProperties.get("ro.debuggable")) &&
"yes".equals(SystemProperties.get("socket.relaxsslcheck")))) {
if (mInsecureFactory == null) {
if (mSecure) {
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 92041d8..d1d8b0a 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -162,4 +162,15 @@
* Check the status of USB RNDIS support
*/
boolean isUsbRNDISStarted();
+
+ /**
+ * Start Wifi Access Point
+ */
+ void startAccessPoint();
+
+ /**
+ * Stop Wifi Access Point
+ */
+ void stopAccessPoint();
+
}
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 0b90f91..46c82e4 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -2935,6 +2935,13 @@
*/
public static final Uri CONTENT_FILTER_URI = Uri.withAppendedPath(AUTHORITY_URI,
"phone_lookup");
+
+ /**
+ * The MIME type of {@link #CONTENT_FILTER_URI} providing a directory of phone lookup rows.
+ *
+ * @hide
+ */
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/phone_lookup";
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 18e2647..7df509f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2386,6 +2386,13 @@
public static final String WIFI_ON = "wifi_on";
/**
+ * Whether the Wi-Fi AP should be on.
+ *
+ * @hide
+ */
+ public static final String WIFI_AP_ON = "wifi_ap_on";
+
+ /**
* The acceptable packet loss percentage (range 0 - 100) before trying
* another AP on the same network.
*/
@@ -3078,13 +3085,6 @@
public static final String MOUNT_UMS_NOTIFY_ENABLED = "mount_ums_notify_enabled";
/**
- * Whether or not a notification is displayed when a Tetherable interface is detected.
- * (0 = false, 1 = true)
- * @hide
- */
- public static final String TETHER_NOTIFY = "tether_notify";
-
- /**
* If nonzero, ANRs in invisible background processes bring up a dialog.
* Otherwise, the process will be silently killed.
* @hide
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 52de64c..444135a 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -821,6 +821,7 @@
case MSG_WINDOW_RESIZED: {
final boolean reportDraw = message.arg1 != 0;
mEngine.updateSurface(true, false);
+ mEngine.doOffsetsChanged();
if (reportDraw) {
try {
mEngine.mSession.finishDrawing(mEngine.mWindow);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 4db5871..40702b5 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -1254,20 +1254,19 @@
final FileOutputStream out = new FileOutputStream(dest);
p.writeToStream(out);
out.close();
- } catch (FileNotFoundException e){
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (RuntimeException e) {
- e.printStackTrace();
- }
- if (dest.length() > 0) {
+ // now update the bundle
b.putInt("scrollX", mScrollX);
b.putInt("scrollY", mScrollY);
b.putFloat("scale", mActualScale);
b.putFloat("textwrapScale", mTextWrapScale);
b.putBoolean("overview", mInZoomOverview);
return true;
+ } catch (FileNotFoundException e){
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (RuntimeException e) {
+ e.printStackTrace();
}
return false;
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index b78373d4..06880a1 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2067,10 +2067,10 @@
// Remember where the motion event started
v = getChildAt(motionPosition - mFirstPosition);
mMotionViewOriginalTop = v.getTop();
- mMotionX = x;
- mMotionY = y;
- mMotionPosition = motionPosition;
}
+ mMotionX = x;
+ mMotionY = y;
+ mMotionPosition = motionPosition;
mLastY = Integer.MIN_VALUE;
break;
}
diff --git a/core/java/com/android/internal/app/TetherActivity.java b/core/java/com/android/internal/app/TetherActivity.java
deleted file mode 100644
index 7f83b2b..0000000
--- a/core/java/com/android/internal/app/TetherActivity.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (C) 2007 Google Inc.
- *
- * 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 com.android.internal.app;
-
-import android.app.AlertDialog;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.ConnectivityManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.widget.Toast;
-import android.util.Log;
-
-/**
- * This activity is shown to the user in two cases: when a connection is possible via
- * a usb tether and when any type of tether is connected. In the connecting case
- * It allows them to start a USB tether. In the Tethered/disconnecting case it
- * will disconnect all tethers.
- */
-public class TetherActivity extends AlertActivity implements
- DialogInterface.OnClickListener {
-
- private static final int POSITIVE_BUTTON = AlertDialog.BUTTON1;
-
- // count of the number of tethered connections at activity create time.
- private int mTethered;
-
- /* Used to detect when the USB cable is unplugged, so we can call finish() */
- private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction() == ConnectivityManager.ACTION_TETHER_STATE_CHANGED) {
- handleTetherStateChanged(intent);
- }
- }
- };
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- // determine if we advertise tethering or untethering
- ConnectivityManager cm =
- (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
-
- mTethered = cm.getTetheredIfaces().length;
- int tetherable = cm.getTetherableIfaces().length;
- if ((mTethered == 0) && (tetherable == 0)) {
- finish();
- return;
- }
-
- // Set up the dialog
- // if we have a tethered connection we put up a "Do you want to Disconect" dialog
- // otherwise we must have a tetherable interface (else we'd return above)
- // and so we want to put up the "do you want to connect" dialog
- if (mTethered == 0) {
- mAlertParams.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
- mAlertParams.mTitle = getString(com.android.internal.R.string.tether_title);
- mAlertParams.mMessage = getString(com.android.internal.R.string.tether_message);
- mAlertParams.mPositiveButtonText =
- getString(com.android.internal.R.string.tether_button);
- mAlertParams.mPositiveButtonListener = this;
- mAlertParams.mNegativeButtonText =
- getString(com.android.internal.R.string.tether_button_cancel);
- mAlertParams.mNegativeButtonListener = this;
- } else {
- mAlertParams.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
- mAlertParams.mTitle = getString(com.android.internal.R.string.tether_stop_title);
- mAlertParams.mMessage = getString(com.android.internal.R.string.tether_stop_message);
- mAlertParams.mPositiveButtonText =
- getString(com.android.internal.R.string.tether_stop_button);
- mAlertParams.mPositiveButtonListener = this;
- mAlertParams.mNegativeButtonText =
- getString(com.android.internal.R.string.tether_stop_button_cancel);
- mAlertParams.mNegativeButtonListener = this;
- }
- setupAlert();
- }
-
- @Override
- protected void onResume() {
- super.onResume();
-
- registerReceiver(mTetherReceiver, new IntentFilter(
- ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
- }
-
- @Override
- protected void onPause() {
- super.onPause();
-
- unregisterReceiver(mTetherReceiver);
- }
-
- /**
- * {@inheritDoc}
- */
- public void onClick(DialogInterface dialog, int which) {
- int error = ConnectivityManager.TETHER_ERROR_NO_ERROR;
-
- if (which == POSITIVE_BUTTON) {
- ConnectivityManager cm =
- (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
- // start/stop tethering
- String[] tethered = cm.getTetheredIfaces();
-
- if (tethered.length == 0) {
- String[] tetherable = cm.getTetherableIfaces();
- String[] usbRegexs = cm.getTetherableUsbRegexs();
- for (String t : tetherable) {
- for (String r : usbRegexs) {
- if (t.matches(r)) {
- error = cm.tether(t);
- break;
- }
- }
- }
- showTetheringError(error);
- } else {
- for (String t : tethered) {
- error = cm.untether(t);
- }
- showUnTetheringError(error);
- }
- }
- // No matter what, finish the activity
- finish();
- }
-
- private void handleTetherStateChanged(Intent intent) {
- // determine if we advertise tethering or untethering
- ConnectivityManager cm =
- (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
- if (mTethered != cm.getTetheredIfaces().length) {
- finish();
- }
- }
-
- private void showTetheringError(int error) {
- switch(error) {
- case ConnectivityManager.TETHER_ERROR_NO_ERROR:
- return;
- default:
- Toast.makeText(this, com.android.internal.R.string.tether_error_message,
- Toast.LENGTH_LONG).show();
- }
- }
-
- private void showUnTetheringError(int error) {
- switch(error) {
- case ConnectivityManager.TETHER_ERROR_NO_ERROR:
- return;
- default:
- Toast.makeText(this, com.android.internal.R.string.tether_stop_error_message,
- Toast.LENGTH_LONG).show();
- }
- }
-}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 63584ed..a41d25b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1271,10 +1271,6 @@
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
- <activity android:name="com.android.internal.app.TetherActivity"
- android:theme="@style/Theme.Dialog.Alert"
- android:excludeFromRecents="true">
- </activity>
<activity android:name="com.android.server.status.UsbStorageActivity"
android:excludeFromRecents="true">
</activity>
diff --git a/core/res/res/drawable-hdpi/ic_lock_silent_mode.png b/core/res/res/drawable-hdpi/ic_lock_silent_mode.png
index 00e1960..0d4c590 100644
--- a/core/res/res/drawable-hdpi/ic_lock_silent_mode.png
+++ b/core/res/res/drawable-hdpi/ic_lock_silent_mode.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_silent_mode_off.png b/core/res/res/drawable-hdpi/ic_lock_silent_mode_off.png
index 6b4ce89..17d705c 100644
--- a/core/res/res/drawable-hdpi/ic_lock_silent_mode_off.png
+++ b/core/res/res/drawable-hdpi/ic_lock_silent_mode_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_lock_silent_mode_vibrate.png b/core/res/res/drawable-hdpi/ic_lock_silent_mode_vibrate.png
new file mode 100644
index 0000000..4503aceb
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_lock_silent_mode_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_vibrate.png b/core/res/res/drawable-hdpi/ic_vibrate.png
index aa83534..ca23372 100644
--- a/core/res/res/drawable-hdpi/ic_vibrate.png
+++ b/core/res/res/drawable-hdpi/ic_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_vibrate_small.png b/core/res/res/drawable-hdpi/ic_vibrate_small.png
new file mode 100644
index 0000000..61b8bd9
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_vibrate_small.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_volume.png b/core/res/res/drawable-hdpi/ic_volume.png
index 7714f6a..bf538ee 100644
--- a/core/res/res/drawable-hdpi/ic_volume.png
+++ b/core/res/res/drawable-hdpi/ic_volume.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_volume_off.png b/core/res/res/drawable-hdpi/ic_volume_off.png
index 313dd5b..aa344083 100644
--- a/core/res/res/drawable-hdpi/ic_volume_off.png
+++ b/core/res/res/drawable-hdpi/ic_volume_off.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_volume_off_small.png b/core/res/res/drawable-hdpi/ic_volume_off_small.png
index 62322ec..1329414 100644
--- a/core/res/res/drawable-hdpi/ic_volume_off_small.png
+++ b/core/res/res/drawable-hdpi/ic_volume_off_small.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_volume_small.png b/core/res/res/drawable-hdpi/ic_volume_small.png
index 96c7948..4e9a7ea 100644
--- a/core/res/res/drawable-hdpi/ic_volume_small.png
+++ b/core/res/res/drawable-hdpi/ic_volume_small.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_silent_mode.png b/core/res/res/drawable-mdpi/ic_lock_silent_mode.png
index 439a6f5..5c3a226 100644
--- a/core/res/res/drawable-mdpi/ic_lock_silent_mode.png
+++ b/core/res/res/drawable-mdpi/ic_lock_silent_mode.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_silent_mode_off.png b/core/res/res/drawable-mdpi/ic_lock_silent_mode_off.png
index fc7e960..95257a3 100644
--- a/core/res/res/drawable-mdpi/ic_lock_silent_mode_off.png
+++ b/core/res/res/drawable-mdpi/ic_lock_silent_mode_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_silent_mode_vibrate.png b/core/res/res/drawable-mdpi/ic_lock_silent_mode_vibrate.png
new file mode 100644
index 0000000..7da79aa
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_lock_silent_mode_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_vibrate.png b/core/res/res/drawable-mdpi/ic_vibrate.png
old mode 100755
new mode 100644
index eb24e50..4fecce1
--- a/core/res/res/drawable-mdpi/ic_vibrate.png
+++ b/core/res/res/drawable-mdpi/ic_vibrate.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_vibrate_small.png b/core/res/res/drawable-mdpi/ic_vibrate_small.png
new file mode 100644
index 0000000..f04804e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_vibrate_small.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_volume.png b/core/res/res/drawable-mdpi/ic_volume.png
old mode 100755
new mode 100644
index cee70f0..20aa030
--- a/core/res/res/drawable-mdpi/ic_volume.png
+++ b/core/res/res/drawable-mdpi/ic_volume.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_volume_off.png b/core/res/res/drawable-mdpi/ic_volume_off.png
index f3850fc..fefb9c4 100644
--- a/core/res/res/drawable-mdpi/ic_volume_off.png
+++ b/core/res/res/drawable-mdpi/ic_volume_off.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_volume_off_small.png b/core/res/res/drawable-mdpi/ic_volume_off_small.png
old mode 100755
new mode 100644
index ae55bd66..529298c
--- a/core/res/res/drawable-mdpi/ic_volume_off_small.png
+++ b/core/res/res/drawable-mdpi/ic_volume_off_small.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_volume_small.png b/core/res/res/drawable-mdpi/ic_volume_small.png
old mode 100755
new mode 100644
index 00a4f89..2a7ec034
--- a/core/res/res/drawable-mdpi/ic_volume_small.png
+++ b/core/res/res/drawable-mdpi/ic_volume_small.png
Binary files differ
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 0c8bafc..72fd0ad 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -185,18 +185,12 @@
<string name="permdesc_setDebugApp" msgid="5584310661711990702">"允許應用程式為其他程式開啟偵錯功能。請注意:惡意程式可利用此功能終止其他應用程式。"</string>
<string name="permlab_changeConfiguration" msgid="8214475779521218295">"變更介面設定"</string>
<string name="permdesc_changeConfiguration" msgid="3465121501528064399">"允許應用程式變更目前設定,例如:地區設定或字型大小。"</string>
- <!-- no translation found for permlab_enableCarMode (5684504058192921098) -->
- <skip />
- <!-- no translation found for permdesc_enableCarMode (5673461159384850628) -->
- <skip />
- <!-- no translation found for permlab_killBackgroundProcesses (8373714752793061963) -->
- <skip />
- <!-- no translation found for permdesc_killBackgroundProcesses (2908829602869383753) -->
- <skip />
- <!-- no translation found for permlab_forceStopPackages (1447830113260156236) -->
- <skip />
- <!-- no translation found for permdesc_forceStopPackages (7263036616161367402) -->
- <skip />
+ <string name="permlab_enableCarMode" msgid="5684504058192921098">"啟用行車模式"</string>
+ <string name="permdesc_enableCarMode" msgid="5673461159384850628">"允許應用程式啟用行車模式。"</string>
+ <string name="permlab_killBackgroundProcesses" msgid="8373714752793061963">"關閉背景程序"</string>
+ <string name="permdesc_killBackgroundProcesses" msgid="2908829602869383753">"允許應用程式關閉其他應用程式背景程序 (即使記憶體足夠)。"</string>
+ <string name="permlab_forceStopPackages" msgid="1447830113260156236">"強制停止應用程式"</string>
+ <string name="permdesc_forceStopPackages" msgid="7263036616161367402">"允許應用程式強制停止其他應用程式。"</string>
<string name="permlab_forceBack" msgid="1804196839880393631">"強制關閉應用程式"</string>
<string name="permdesc_forceBack" msgid="6534109744159919013">"允許應用程式強制關閉在前端運作的活動並返回。一般應用程式不需要此功能。"</string>
<string name="permlab_dump" msgid="1681799862438954752">"接收系統內部狀態"</string>
@@ -237,10 +231,8 @@
<string name="permdesc_bindInputMethod" msgid="3734838321027317228">"允許擁有人連結至輸入法的最頂層介面。一般應用程式不需使用此選項。"</string>
<string name="permlab_bindWallpaper" msgid="8716400279937856462">"連結至桌布"</string>
<string name="permdesc_bindWallpaper" msgid="5287754520361915347">"允許擁有人連結至桌布的最頂層介面,一般應用程式不需使用此選項。"</string>
- <!-- no translation found for permlab_bindDeviceAdmin (8704986163711455010) -->
- <skip />
- <!-- no translation found for permdesc_bindDeviceAdmin (8714424333082216979) -->
- <skip />
+ <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"與裝置管理員互動"</string>
+ <string name="permdesc_bindDeviceAdmin" msgid="8714424333082216979">"允許應用程式將調用請求 (intent) 傳送至裝置管理員;一般應用程式不需使用此選項。"</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"變更螢幕顯示方向"</string>
<string name="permdesc_setOrientation" msgid="6335814461615851863">"允許應用程式隨時變更螢幕顯示方向。一般應用程式不需要此功能。"</string>
<string name="permlab_signalPersistentProcesses" msgid="4255467255488653854">"傳送 Linux 訊號到應用程式"</string>
@@ -324,26 +316,16 @@
<string name="permdesc_mount_unmount_filesystems" msgid="6253263792535859767">"允許應用程式掛載/卸載抽取式儲存設備的檔案系統。"</string>
<string name="permlab_mount_format_filesystems" msgid="5523285143576718981">"將外接式儲存裝置格式化"</string>
<string name="permdesc_mount_format_filesystems" msgid="574060044906047386">"允許應用程式將可移除式儲存裝置格式化。"</string>
- <!-- no translation found for permlab_asec_access (1070364079249834666) -->
- <skip />
- <!-- no translation found for permdesc_asec_access (7691616292170590244) -->
- <skip />
- <!-- no translation found for permlab_asec_create (7312078032326928899) -->
- <skip />
- <!-- no translation found for permdesc_asec_create (7041802322759014035) -->
- <skip />
- <!-- no translation found for permlab_asec_destroy (7787322878955261006) -->
- <skip />
- <!-- no translation found for permdesc_asec_destroy (5740754114967893169) -->
- <skip />
- <!-- no translation found for permlab_asec_mount_unmount (7517449694667828592) -->
- <skip />
- <!-- no translation found for permdesc_asec_mount_unmount (5438078121718738625) -->
- <skip />
- <!-- no translation found for permlab_asec_rename (5685344390439934495) -->
- <skip />
- <!-- no translation found for permdesc_asec_rename (1387881770708872470) -->
- <skip />
+ <string name="permlab_asec_access" msgid="1070364079249834666">"取得安全儲存空間的資訊"</string>
+ <string name="permdesc_asec_access" msgid="7691616292170590244">"允許應用程式取得安全儲存空間的資訊。"</string>
+ <string name="permlab_asec_create" msgid="7312078032326928899">"建立安全儲存空間"</string>
+ <string name="permdesc_asec_create" msgid="7041802322759014035">"允許應用程式建立安全儲存空間。"</string>
+ <string name="permlab_asec_destroy" msgid="7787322878955261006">"銷毀安全儲存空間"</string>
+ <string name="permdesc_asec_destroy" msgid="5740754114967893169">"允許應用程式銷毀安全儲存空間。"</string>
+ <string name="permlab_asec_mount_unmount" msgid="7517449694667828592">"掛載/卸載安全儲存空間"</string>
+ <string name="permdesc_asec_mount_unmount" msgid="5438078121718738625">"允許應用程式掛載/卸載安全儲存空間。"</string>
+ <string name="permlab_asec_rename" msgid="5685344390439934495">"重新命名安全儲存空間"</string>
+ <string name="permdesc_asec_rename" msgid="1387881770708872470">"允許應用程式重新命名安全儲存空間。"</string>
<string name="permlab_vibrate" msgid="7768356019980849603">"控制震動"</string>
<string name="permdesc_vibrate" msgid="2886677177257789187">"允許應用程式控制震動。"</string>
<string name="permlab_flashlight" msgid="2155920810121984215">"控制閃光燈"</string>
@@ -378,10 +360,8 @@
<string name="permdesc_setWallpaperHints" msgid="6019479164008079626">"允許應用程式設定系統桌布大小提示。"</string>
<string name="permlab_masterClear" msgid="2315750423139697397">"將系統還原至出廠預設值"</string>
<string name="permdesc_masterClear" msgid="5033465107545174514">"允許應用程式將手機完全重設至出廠設定,清除所有資料、設定與已安裝程式。"</string>
- <!-- no translation found for permlab_setTime (2021614829591775646) -->
- <skip />
- <!-- no translation found for permdesc_setTime (667294309287080045) -->
- <skip />
+ <string name="permlab_setTime" msgid="2021614829591775646">"設定時間"</string>
+ <string name="permdesc_setTime" msgid="667294309287080045">"允許應用程式變更手機時鐘時間。"</string>
<string name="permlab_setTimeZone" msgid="2945079801013077340">"設定時區"</string>
<string name="permdesc_setTimeZone" msgid="1902540227418179364">"允許應用程式變更時區。"</string>
<string name="permlab_accountManagerService" msgid="4829262349691386986">"作為 AccountManagerService"</string>
@@ -401,12 +381,9 @@
<string name="permlab_writeApnSettings" msgid="7823599210086622545">"輸入存取點名稱設定"</string>
<string name="permdesc_writeApnSettings" msgid="7443433457842966680">"允許應用程式修改 APN 設定,例如:Proxy 及 APN 的連接埠。"</string>
<string name="permlab_changeNetworkState" msgid="958884291454327309">"變更網路連線"</string>
- <!-- no translation found for permdesc_changeNetworkState (4199958910396387075) -->
- <skip />
- <!-- no translation found for permlab_changeTetherState (5952584964373017960) -->
- <skip />
- <!-- no translation found for permdesc_changeTetherState (8905815579146349568) -->
- <skip />
+ <string name="permdesc_changeNetworkState" msgid="4199958910396387075">"允許應用程式變更網路連線狀態。"</string>
+ <string name="permlab_changeTetherState" msgid="5952584964373017960">"變更數據連線"</string>
+ <string name="permdesc_changeTetherState" msgid="8905815579146349568">"允許應用程式變更數據網路連線狀態。"</string>
<string name="permlab_changeBackgroundDataSetting" msgid="1400666012671648741">"變更背景資料使用設定"</string>
<string name="permdesc_changeBackgroundDataSetting" msgid="1001482853266638864">"允許應用程式變更背景資料使用設定。"</string>
<string name="permlab_accessWifiState" msgid="8100926650211034400">"檢視 Wi-Fi 狀態"</string>
@@ -437,30 +414,18 @@
<string name="permdesc_writeDictionary" msgid="2241256206524082880">"允許應用程式將新字詞寫入使用者的字典。"</string>
<string name="permlab_sdcardWrite" msgid="8079403759001777291">"修改/刪除 SD 卡的內容"</string>
<string name="permdesc_sdcardWrite" msgid="6643963204976471878">"允許應用程式寫入 SD 卡。"</string>
- <!-- no translation found for permlab_cache_filesystem (5656487264819669824) -->
- <skip />
- <!-- no translation found for permdesc_cache_filesystem (1624734528435659906) -->
- <skip />
- <!-- no translation found for policylab_limitPassword (4307861496302850201) -->
- <skip />
- <!-- no translation found for policydesc_limitPassword (1719877245692318299) -->
- <skip />
- <!-- no translation found for policylab_watchLogin (7374780712664285321) -->
- <skip />
- <!-- no translation found for policydesc_watchLogin (1961251179624843483) -->
- <skip />
- <!-- no translation found for policylab_resetPassword (9084772090797485420) -->
- <skip />
- <!-- no translation found for policydesc_resetPassword (3332167600331799991) -->
- <skip />
- <!-- no translation found for policylab_forceLock (5760466025247634488) -->
- <skip />
- <!-- no translation found for policydesc_forceLock (2819868664946089740) -->
- <skip />
- <!-- no translation found for policylab_wipeData (3910545446758639713) -->
- <skip />
- <!-- no translation found for policydesc_wipeData (2314060933796396205) -->
- <skip />
+ <string name="permlab_cache_filesystem" msgid="5656487264819669824">"存取快取檔案系統"</string>
+ <string name="permdesc_cache_filesystem" msgid="1624734528435659906">"允許應用程式讀取及寫入快取檔案系統。"</string>
+ <string name="policylab_limitPassword" msgid="4307861496302850201">"限制密碼設定規則"</string>
+ <string name="policydesc_limitPassword" msgid="1719877245692318299">"限制允許使用的密碼類型。"</string>
+ <string name="policylab_watchLogin" msgid="7374780712664285321">"查看登入嘗試記錄"</string>
+ <string name="policydesc_watchLogin" msgid="1961251179624843483">"監視者無法登入裝置執行部分動作。"</string>
+ <string name="policylab_resetPassword" msgid="9084772090797485420">"重設密碼"</string>
+ <string name="policydesc_resetPassword" msgid="3332167600331799991">"強制重新設定密碼。您必須取得以管理員提供的新密碼,才能登入。"</string>
+ <string name="policylab_forceLock" msgid="5760466025247634488">"強制鎖定"</string>
+ <string name="policydesc_forceLock" msgid="2819868664946089740">"裝置鎖定時可取得控制,但必須重新輸入密碼。"</string>
+ <string name="policylab_wipeData" msgid="3910545446758639713">"清除所有資料"</string>
+ <string name="policydesc_wipeData" msgid="2314060933796396205">"重設為原廠設定 (系統會刪除所有資料,且不會向您進行確認)。"</string>
<string-array name="phoneTypes">
<item msgid="8901098336658710359">"住家電話"</item>
<item msgid="869923650527136615">"行動電話"</item>
@@ -557,8 +522,7 @@
<string name="contact_status_update_attribution" msgid="5112589886094402795">"透過 <xliff:g id="SOURCE">%1$s</xliff:g>"</string>
<string name="contact_status_update_attribution_with_date" msgid="5945386376369979909">"<xliff:g id="DATE">%1$s</xliff:g>透過「<xliff:g id="SOURCE">%2$s</xliff:g>」"</string>
<string name="keyguard_password_enter_pin_code" msgid="3731488827218876115">"輸入 PIN 碼"</string>
- <!-- no translation found for keyguard_password_enter_password_code (9138158344813213754) -->
- <skip />
+ <string name="keyguard_password_enter_password_code" msgid="9138158344813213754">"輸入密碼即可解鎖"</string>
<string name="keyguard_password_wrong_pin_code" msgid="1295984114338107718">"PIN 碼錯誤!"</string>
<string name="keyguard_label_text" msgid="861796461028298424">"如要解鎖,請按 Menu 鍵,然後按 0。"</string>
<string name="emergency_call_dialog_number_for_display" msgid="696192103195090970">"緊急電話號碼"</string>
@@ -579,7 +543,7 @@
<string name="lockscreen_missing_sim_message_short" msgid="7381499217732227295">"沒有 SIM 卡。"</string>
<string name="lockscreen_missing_sim_message" msgid="2186920585695169078">"手機未插入 SIM 卡。"</string>
<string name="lockscreen_missing_sim_instructions" msgid="8874620818937719067">"請插入 SIM 卡。"</string>
- <string name="emergency_calls_only" msgid="6733978304386365407">"只能撥打緊急電話"</string>
+ <string name="emergency_calls_only" msgid="6733978304386365407">"僅可撥打緊急電話"</string>
<string name="lockscreen_network_locked_message" msgid="143389224986028501">"網路已鎖定"</string>
<string name="lockscreen_sim_puk_locked_message" msgid="7441797339976230">"SIM 的 PUK 已鎖定。"</string>
<string name="lockscreen_sim_puk_locked_instructions" msgid="635967534992394321">"請參閱《使用者指南》或聯絡客戶服務中心。"</string>
@@ -600,12 +564,9 @@
<string name="lockscreen_unlock_label" msgid="737440483220667054">"解除封鎖"</string>
<string name="lockscreen_sound_on_label" msgid="9068877576513425970">"開啟音效"</string>
<string name="lockscreen_sound_off_label" msgid="996822825154319026">"關閉音效"</string>
- <!-- no translation found for password_keyboard_label_symbol_key (992280756256536042) -->
- <skip />
- <!-- no translation found for password_keyboard_label_alpha_key (8001096175167485649) -->
- <skip />
- <!-- no translation found for password_keyboard_label_alt_key (1284820942620288678) -->
- <skip />
+ <string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
+ <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
+ <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
<string name="hour_ampm" msgid="4329881288269772723">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%P</xliff:g>"</string>
<string name="hour_cap_ampm" msgid="1829009197680861107">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
<string name="status_bar_clear_all_button" msgid="7774721344716731603">"清除"</string>
@@ -631,10 +592,8 @@
<string name="permdesc_readHistoryBookmarks" msgid="4981489815467617191">"允許應用程式讀取瀏覽器曾經造訪過的所有網址,以及瀏覽器的所有書籤。"</string>
<string name="permlab_writeHistoryBookmarks" msgid="9009434109836280374">"寫入瀏覽器的記錄與書籤"</string>
<string name="permdesc_writeHistoryBookmarks" msgid="945571990357114950">"允許應用程式修改儲存在電話上的瀏覽記錄或書籤。請注意:惡意應用程式可能會使用此選項來清除或修改您瀏覽器的資料。"</string>
- <!-- no translation found for permlab_writeGeolocationPermissions (4715212655598275532) -->
- <skip />
- <!-- no translation found for permdesc_writeGeolocationPermissions (4011908282980861679) -->
- <skip />
+ <string name="permlab_writeGeolocationPermissions" msgid="4715212655598275532">"修改瀏覽器地理資訊的權限"</string>
+ <string name="permdesc_writeGeolocationPermissions" msgid="4011908282980861679">"允許應用程式修改瀏覽器的地理位置權限,惡意應用程式可能會透過此方式允許將您的位置資訊任意傳送給某些網站。"</string>
<string name="save_password_message" msgid="767344687139195790">"是否記憶此密碼?"</string>
<string name="save_password_notnow" msgid="6389675316706699758">"現在不要"</string>
<string name="save_password_remember" msgid="6491879678996749466">"記住"</string>
@@ -733,11 +692,6 @@
<string name="weeks" msgid="6509623834583944518">"週"</string>
<string name="year" msgid="4001118221013892076">"年"</string>
<string name="years" msgid="6881577717993213522">"年"</string>
- <string name="every_weekday" msgid="8777593878457748503">"每天 (週一至週五)"</string>
- <string name="daily" msgid="5738949095624133403">"每天"</string>
- <string name="weekly" msgid="983428358394268344">"每週<xliff:g id="DAY">%s</xliff:g>"</string>
- <string name="monthly" msgid="2667202947170988834">"每月"</string>
- <string name="yearly" msgid="1519577999407493836">"每年"</string>
<string name="VideoView_error_title" msgid="3359437293118172396">"無法播放影片"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="897920883624437033">"很抱歉,影片格式無效,裝置無法進行串流處理。"</string>
<string name="VideoView_error_text_unknown" msgid="710301040038083944">"很抱歉,此影片無法播放。"</string>
@@ -820,26 +774,19 @@
<string name="no_permissions" msgid="7283357728219338112">"無須許可"</string>
<string name="perms_hide" msgid="7283915391320676226"><b>" 隱藏"</b></string>
<string name="perms_show_all" msgid="2671791163933091180"><b>"顯示全部"</b></string>
- <!-- no translation found for usb_storage_activity_title (2399289999608900443) -->
- <skip />
+ <string name="usb_storage_activity_title" msgid="2399289999608900443">"USB 大量儲存裝置"</string>
<string name="usb_storage_title" msgid="5901459041398751495">"USB 已連接"</string>
- <!-- no translation found for usb_storage_message (4796759646167247178) -->
- <skip />
- <!-- no translation found for usb_storage_button_mount (1052259930369508235) -->
- <skip />
+ <string name="usb_storage_message" msgid="4796759646167247178">"已透過 USB 連接手機與電腦。如要從電腦或 Android 系統的 SD 卡複製檔案,請選取下方按鈕。"</string>
+ <string name="usb_storage_button_mount" msgid="1052259930369508235">"開啟 USB 儲存裝置"</string>
<string name="usb_storage_error_message" msgid="2534784751603345363">"把 SD 卡當成 USB 儲存裝置時發生問題。"</string>
<string name="usb_storage_notification_title" msgid="8175892554757216525">"USB 已連接"</string>
<string name="usb_storage_notification_message" msgid="7380082404288219341">"選取此項將檔案複製到電腦,或從電腦複製。"</string>
<string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"關閉 USB 儲存裝置"</string>
<string name="usb_storage_stop_notification_message" msgid="2591813490269841539">"選取此處關閉 USB 儲存裝置。"</string>
- <!-- no translation found for usb_storage_stop_title (660129851708775853) -->
- <skip />
- <!-- no translation found for usb_storage_stop_message (3613713396426604104) -->
- <skip />
- <!-- no translation found for usb_storage_stop_button_mount (7060218034900696029) -->
- <skip />
- <!-- no translation found for usb_storage_stop_error_message (143881914840412108) -->
- <skip />
+ <string name="usb_storage_stop_title" msgid="660129851708775853">"USB 儲存空間使用中"</string>
+ <string name="usb_storage_stop_message" msgid="3613713396426604104">"關閉 USB 儲存裝置前,請務必先將 Android 系統的 SD 卡從電腦上卸下 (退出)。"</string>
+ <string name="usb_storage_stop_button_mount" msgid="7060218034900696029">"關閉 USB 儲存裝置"</string>
+ <string name="usb_storage_stop_error_message" msgid="143881914840412108">"關閉 USB 儲存裝置時發生問題。請檢查您是否已卸載 USB Host,然後再試一次。"</string>
<!-- no translation found for dlg_confirm_kill_storage_users_title (203356557714612214) -->
<skip />
<!-- no translation found for dlg_confirm_kill_storage_users_text (3902998926994232358) -->
@@ -872,10 +819,8 @@
<string name="activity_list_empty" msgid="4168820609403385789">"找不到符合的活動"</string>
<string name="permlab_pkgUsageStats" msgid="8787352074326748892">"更新元件使用統計資料"</string>
<string name="permdesc_pkgUsageStats" msgid="891553695716752835">"允許修改收集到的元件使用統計資料。一般應用程式不會使用此功能。"</string>
- <!-- no translation found for permlab_copyProtectedData (1660908117394854464) -->
- <skip />
- <!-- no translation found for permdesc_copyProtectedData (537780957633976401) -->
- <skip />
+ <string name="permlab_copyProtectedData" msgid="1660908117394854464">"允許觸發預設容器服務,以便複製內容 (不建議一般應用程式使用)。"</string>
+ <string name="permdesc_copyProtectedData" msgid="537780957633976401">"允許觸發預設容器服務,以便複製內容 (不建議一般應用程式使用)。"</string>
<string name="tutorial_double_tap_to_zoom_message_short" msgid="1311810005957319690">"點兩下以進行縮放控制"</string>
<string name="gadget_host_error_inflating" msgid="2613287218853846830">"擴大小工具時發生錯誤"</string>
<string name="ime_action_go" msgid="8320845651737369027">"開始"</string>
@@ -888,12 +833,9 @@
<string name="create_contact_using" msgid="4947405226788104538">"建立手機號碼為 <xliff:g id="NUMBER">%s</xliff:g>"\n"的聯絡人"</string>
<string name="accessibility_compound_button_selected" msgid="5612776946036285686">"已勾選"</string>
<string name="accessibility_compound_button_unselected" msgid="8864512895673924091">"未勾選"</string>
- <!-- no translation found for grant_credentials_permission_message_header (6824538733852821001) -->
- <skip />
- <!-- no translation found for grant_credentials_permission_message_footer (3125211343379376561) -->
- <skip />
- <!-- no translation found for grant_permissions_header_text (2722567482180797717) -->
- <skip />
+ <string name="grant_credentials_permission_message_header" msgid="6824538733852821001">"下列一或多個應用程式要求現在及將來的帳戶存取權限。"</string>
+ <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"您確定要允許這個要求嗎?"</string>
+ <string name="grant_permissions_header_text" msgid="2722567482180797717">"存取要求"</string>
<string name="allow" msgid="7225948811296386551">"允許"</string>
<string name="deny" msgid="2081879885755434506">"拒絕"</string>
<string name="permission_request_notification_title" msgid="5390555465778213840">"已要求權限"</string>
@@ -907,44 +849,27 @@
<string name="l2tp_vpn_description" msgid="3750692169378923304">"第二層通道通訊協定"</string>
<string name="l2tp_ipsec_psk_vpn_description" msgid="3945043564008303239">"採用預先共用金鑰的 L2TP/IPSec VPN"</string>
<string name="l2tp_ipsec_crt_vpn_description" msgid="5382714073103653577">"採用憑證的 L2TP/IPSec VPN"</string>
- <!-- no translation found for upload_file (2897957172366730416) -->
+ <string name="upload_file" msgid="2897957172366730416">"選擇檔案"</string>
+ <string name="reset" msgid="2448168080964209908">"重設"</string>
+ <string name="submit" msgid="1602335572089911941">"提交"</string>
+ <string name="description_star" msgid="2654319874908576133">"我的最愛"</string>
+ <string name="tether_title" msgid="6970447107301643248">"USB 數據連線運作中"</string>
+ <string name="tether_message" msgid="554549994538298101">"如要與電腦分享手機的資料連線,請選取 [數據連線]。"</string>
+ <string name="tether_button" msgid="7409514810151603641">"數據連線"</string>
+ <string name="tether_button_cancel" msgid="6744369928952219677">"取消"</string>
+ <!-- no translation found for tether_error_message (950843122853838817) -->
<skip />
- <!-- no translation found for reset (2448168080964209908) -->
- <skip />
- <!-- no translation found for submit (1602335572089911941) -->
- <skip />
- <!-- no translation found for description_star (2654319874908576133) -->
- <skip />
- <!-- no translation found for tether_title (6970447107301643248) -->
- <skip />
- <!-- no translation found for tether_message (554549994538298101) -->
- <skip />
- <!-- no translation found for tether_button (7409514810151603641) -->
- <skip />
- <!-- no translation found for tether_button_cancel (6744369928952219677) -->
- <skip />
- <!-- no translation found for tether_error_message (6672110337349077628) -->
- <skip />
- <!-- no translation found for tether_available_notification_title (367754042700082080) -->
- <skip />
- <!-- no translation found for tether_available_notification_message (8439443306503453793) -->
- <skip />
- <!-- no translation found for tether_stop_notification_title (1902246071807668101) -->
- <skip />
- <!-- no translation found for tether_stop_notification_message (6920086906891516128) -->
- <skip />
- <!-- no translation found for tether_stop_title (3118332507220912235) -->
- <skip />
- <!-- no translation found for tether_stop_message (7741840433788363174) -->
- <skip />
- <!-- no translation found for tether_stop_button (8061941592702063029) -->
- <skip />
- <!-- no translation found for tether_stop_button_cancel (3694669546501300230) -->
- <skip />
- <!-- no translation found for tether_stop_error_message (4244697367270211648) -->
- <skip />
+ <string name="tether_available_notification_title" msgid="367754042700082080">"USB 數據連線運作中"</string>
+ <string name="tether_available_notification_message" msgid="8439443306503453793">"選取此選項可讓您的電腦與手機進行數據連線。"</string>
+ <string name="tether_stop_notification_title" msgid="1902246071807668101">"中斷數據連線"</string>
+ <string name="tether_stop_notification_message" msgid="6920086906891516128">"選取即可中斷與電腦的數據連線。"</string>
+ <string name="tether_stop_title" msgid="3118332507220912235">"中斷數據連線"</string>
+ <string name="tether_stop_message" msgid="7741840433788363174">"您已與電腦分享手機的行動資料連線,如要中斷 USB 數據連線,請選取 [中斷連線]。"</string>
+ <string name="tether_stop_button" msgid="8061941592702063029">"中斷連線"</string>
+ <string name="tether_stop_button_cancel" msgid="3694669546501300230">"取消"</string>
+ <string name="tether_stop_error_message" msgid="4244697367270211648">"關閉數據連線時發生問題,請再試一次。"</string>
<!-- no translation found for car_mode_disable_notification_title (3164768212003864316) -->
<skip />
- <!-- no translation found for car_mode_disable_notification_message (3262812780382240778) -->
+ <!-- no translation found for car_mode_disable_notification_message (668663626721675614) -->
<skip />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d34599f..e68f214 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -131,9 +131,17 @@
<!-- Displayed to tell the user that emergency service is blocked by access control. -->
<string name="RestrictedOnEmergency">Emergency service is blocked.</string>
<!-- Displayed to tell the user that normal service is blocked by access control. -->
- <string name="RestrictedOnNormal">Voice/SMS service is blocked.</string>
- <!-- Displayed to tell the user that all voice service is blocked by access control. -->
- <string name="RestrictedOnAll">All voice/SMS services are blocked.</string>
+ <string name="RestrictedOnNormal">Voice service is blocked.</string>
+ <!-- Displayed to tell the user that all emergency and normal voice services are blocked by access control. -->
+ <string name="RestrictedOnAllVoice">All Voice services are blocked.</string>
+ <!-- Displayed to tell the user that sms service is blocked by access control. -->
+ <string name="RestrictedOnSms">SMS service is blocked.</string>
+ <!-- Displayed to tell the user that voice/data service is blocked by access control. -->
+ <string name="RestrictedOnVoiceData">Voice/Data services are blocked.</string>
+ <!-- Displayed to tell the user that voice and sms service are blocked by access control. -->
+ <string name="RestrictedOnVoiceSms">Voice/SMS services are blocked.</string>
+ <!-- Displayed to tell the user that all service is blocked by access control. -->
+ <string name="RestrictedOnAll">All Voice/Data/SMS services are blocked.</string>
<!-- Mappings between TS 27.007 +CFCC/+CLCK "service classes" and human-readable strings--> <skip />
<!-- Example: Service was enabled for: Voice, Data -->
@@ -1093,7 +1101,7 @@
the state of network connectivity.</string>
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
- <string name="permlab_changeTetherState">change tethered connectivity</string>
+ <string name="permlab_changeTetherState">Change tethered connectivity</string>
<!-- Description of an application permission, listed so the user can choose whether they want to allow the applicaiton to do this. -->
<string name="permdesc_changeTetherState">Allows an application to change
the state of tethered network connectivity.</string>
@@ -2238,44 +2246,6 @@
-->
<string name="description_star">favorite</string>
-
- <!-- Strings for Tethering dialogs -->
- <!-- This is the label for the activity, and should never be visible to the user. -->
- <!-- See TETHERING. TETHERING_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to Tether. This is the title. -->
- <string name="tether_title">USB tethering available</string>
- <!-- See TETHER. This is the message. -->
- <string name="tether_message">Select \"Tether\" if you want to share your phone\'s data connection with your computer.</string>
- <!-- See TETHER. This is the button text to Tether the computer with the phone. -->
- <string name="tether_button">Tether</string>
- <!-- See TETHER. This is the button text to ignore the plugging in of the phone.. -->
- <string name="tether_button_cancel">Cancel</string>
-
- <!-- See TETHER. If there was a recoverable error, this is the text. -->
- <string name="tether_error_message">We\'ve encountered a problem turning on Tethering. Please try again.</string>
-
- <!-- TETHER: When the user connects the phone to a computer, we show a notification asking if he wants to share his cellular network connection. This is the title -->
- <string name="tether_available_notification_title">USB tethering available</string>
- <!-- See USB_STORAGE. This is the message. -->
- <string name="tether_available_notification_message">Select to tether your computer to your phone.</string>
- <!-- TETHER_STOP: While TETHER is enabled, we show a notification dialog asking if he wants to stop. This is the title -->
- <string name="tether_stop_notification_title">Untether</string>
- <!-- See TETHER. This is the message. -->
- <string name="tether_stop_notification_message">Select to untether your computer.</string>
-
- <!-- TETHER stop dialog strings -->
- <!-- This is the label for the activity, and should never be visible to the user. -->
- <!-- See TETHER_STOP. TETHER_STOP_DIALOG: After the user selects the notification, a dialog is shown asking if he wants to stop tethering. This is the title. -->
- <string name="tether_stop_title">Disconnect tethering</string>
- <!-- See TETHER_STOP. This is the message. -->
- <string name="tether_stop_message">You have been sharing your phone\'s cellular data connection with your computer. Select \"Disconnect\" to disconnect USB tethering.</string>
- <!-- See TETHER_STOP. This is the button text to disconnect tethering. -->
- <string name="tether_stop_button">Disconnect</string>
- <!-- See TETHER_STOP. This is the button text to cancel disconnecting the tether. -->
- <string name="tether_stop_button_cancel">Cancel</string>
-
- <!-- See TETHER_STOP. If there was an error disconnect, this is the text. -->
- <string name="tether_stop_error_message">We\'ve encountered a problem turning off Tethering. Please try again.</string>
-
<!-- Strings for car mode notification -->
<!-- Shown when car mode is enabled -->
<string name="car_mode_disable_notification_title">Car mode enabled</string>
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 57192a5..34cd9d1 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -608,7 +608,7 @@
// consider up through the function keys; we don't want to include
// ones after that (play cd etc) so we don't mistakenly consider a
// controller to be a keyboard.
- uint8_t key_bitmask[(KEY_PLAYCD+1)/8];
+ uint8_t key_bitmask[(KEY_MAX+1)/8];
memset(key_bitmask, 0, sizeof(key_bitmask));
LOGV("Getting keys...");
if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
diff --git a/media/java/android/media/CamcorderProfile.java b/media/java/android/media/CamcorderProfile.java
index eade680..09ac0ac 100644
--- a/media/java/android/media/CamcorderProfile.java
+++ b/media/java/android/media/CamcorderProfile.java
@@ -34,7 +34,6 @@
* <li> Audio sample rate
* <li> Number of audio channels for recording.
* </ul>
- * {@hide}
*/
public class CamcorderProfile
{
diff --git a/media/java/android/media/CameraProfile.java b/media/java/android/media/CameraProfile.java
index 9685e7e..f1616cc 100644
--- a/media/java/android/media/CameraProfile.java
+++ b/media/java/android/media/CameraProfile.java
@@ -21,7 +21,6 @@
* capture (jpeg) quality levels (0-100) used for low, medium, and high
* quality settings in the Camera application.
*
- * {@hide}
*/
public class CameraProfile
{
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 73e760e..28236f0 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -181,8 +181,7 @@
public void onLocationChanged(Location location) {
final boolean hasMoved = hasMoved(location);
- final boolean hasBetterAccuracy = location.getAccuracy() < mLocation.getAccuracy();
- if (hasMoved || hasBetterAccuracy) {
+ if (hasMoved || hasBetterAccuracy(location)) {
synchronized (this) {
mLocation = location;
}
@@ -201,6 +200,16 @@
public void onStatusChanged(String provider, int status, Bundle extras) {
}
+ private boolean hasBetterAccuracy(Location location) {
+ if (location == null) {
+ return false;
+ }
+ if (mLocation == null) {
+ return true;
+ }
+ return location.getAccuracy() < mLocation.getAccuracy();
+ }
+
/*
* The user has moved if the accuracy circles of the two locations
* don't overlap.
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index eaf4802..8d00deb 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -1205,8 +1205,9 @@
// Remove expired alerts
if (intentsToRemove != null) {
for (PendingIntent i : intentsToRemove) {
- ProximityAlert alert = mProximityAlerts.remove(i);
+ ProximityAlert alert = mProximityAlerts.get(i);
mProximitiesEntered.remove(alert);
+ removeProximityAlertLocked(i);
}
}
}
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 53076de..aa9ced8 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -456,4 +456,23 @@
}
throw new IllegalStateException("Got an empty response");
}
+
+ public void startAccessPoint()
+ throws IllegalStateException {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
+ mConnector.doCommand(String.format("softap set"));
+ mConnector.doCommand(String.format("softap start"));
+ }
+
+ public void stopAccessPoint() throws IllegalStateException {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
+ mConnector.doCommand("softap stop");
+ }
+
}
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index ee69715..f97f50a 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -34,8 +34,10 @@
import android.provider.Settings;
import android.util.Config;
import android.util.EventLog;
+import android.util.Log;
import android.util.Slog;
+import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
@@ -804,19 +806,14 @@
// to timeout on is asleep as well and won't have a chance to run. Causing a false
// positive on when to kill things.
long start = SystemClock.uptimeMillis();
- do {
+ while (timeout > 0 && !mForceKillSystem) {
try {
- wait(timeout);
+ wait(timeout); // notifyAll() is called when mForceKillSystem is set
} catch (InterruptedException e) {
- if (SystemProperties.getBoolean("ro.secure", false)) {
- // If this is a secure build, just log the error.
- Slog.e("WatchDog", "Woof! Woof! Interrupter!");
- } else {
- throw new AssertionError("Someone interrupted the watchdog");
- }
+ Log.wtf(TAG, e);
}
timeout = TIME_TO_WAIT - (SystemClock.uptimeMillis() - start);
- } while (timeout > 0 && !mForceKillSystem);
+ }
if (mCompleted && !mForceKillSystem) {
// The monitors have returned.
@@ -825,22 +822,24 @@
}
// If we got here, that means that the system is most likely hung.
- // First send a SIGQUIT so that we can see where it was hung. Then
- // kill this process so that the system will restart.
+ // First collect stack traces from all threads of the system process.
+ // Then kill this process so that the system will restart.
+
String name = (mCurrentMonitor != null) ? mCurrentMonitor.getClass().getName() : "null";
EventLog.writeEvent(EventLogTags.WATCHDOG, name);
- Process.sendSignal(Process.myPid(), Process.SIGNAL_QUIT);
- // Wait a bit longer before killing so we can make sure that the stacks are captured.
- try {
- Thread.sleep(10*1000);
- } catch (InterruptedException e) {
- }
+ ArrayList pids = new ArrayList();
+ pids.add(Process.myPid());
+ File stack = ActivityManagerService.dumpStackTraces(pids);
+ mActivity.addErrorToDropBox("watchdog", null, null, null, name, null, stack, null);
// Only kill the process if the debugger is not attached.
if (!Debug.isDebuggerConnected()) {
- Slog.i(TAG, "Watchdog is killing the system process");
+ Slog.w(TAG, "*** WATCHDOG KILLING SYSTEM PROCESS: " + name);
Process.killProcess(Process.myPid());
+ System.exit(10);
+ } else {
+ Slog.w(TAG, "Debugger connected: Watchdog is *not* killing the system process");
}
}
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 1455973..7378333f 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -22,6 +22,12 @@
import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
+
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.bluetooth.BluetoothA2dp;
@@ -40,6 +46,8 @@
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.SupplicantState;
+import android.net.ConnectivityManager;
+import android.net.InterfaceConfiguration;
import android.net.NetworkStateTracker;
import android.net.DhcpInfo;
import android.net.NetworkUtils;
@@ -47,6 +55,7 @@
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.INetworkManagementService;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
@@ -67,6 +76,7 @@
import java.util.regex.Pattern;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.net.UnknownHostException;
import com.android.internal.app.IBatteryStats;
import android.backup.IBackupManager;
@@ -87,6 +97,7 @@
private Context mContext;
private int mWifiState;
+ private int mWifiApState;
private AlarmManager mAlarmManager;
private PendingIntent mIdleIntent;
@@ -112,6 +123,10 @@
private final IBatteryStats mBatteryStats;
+ private INetworkManagementService nwService;
+ ConnectivityManager mCm;
+ private String[] mWifiRegexs;
+
/**
* See {@link Settings.Secure#WIFI_IDLE_MS}. This is the default value if a
* Settings.Secure value is not present. This timeout value is chosen as
@@ -145,6 +160,9 @@
private static final int MESSAGE_START_WIFI = 3;
private static final int MESSAGE_RELEASE_WAKELOCK = 4;
private static final int MESSAGE_UPDATE_STATE = 5;
+ private static final int MESSAGE_START_ACCESS_POINT = 6;
+ private static final int MESSAGE_STOP_ACCESS_POINT = 7;
+
private final WifiHandler mWifiHandler;
@@ -180,6 +198,9 @@
mWifiStateTracker.enableRssiPolling(true);
mBatteryStats = BatteryStatsService.getService();
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ nwService = INetworkManagementService.Stub.asInterface(b);
+
mScanResultCache = new LinkedHashMap<String, ScanResult>(
SCAN_RESULT_CACHE_SIZE, 0.75f, true) {
/*
@@ -196,7 +217,9 @@
mWifiHandler = new WifiHandler(wifiThread.getLooper());
mWifiState = WIFI_STATE_DISABLED;
+ mWifiApState = WIFI_AP_STATE_DISABLED;
boolean wifiEnabled = getPersistedWifiEnabled();
+ boolean wifiAPEnabled = wifiEnabled ? false : getPersistedWifiApEnabled();
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
@@ -232,7 +255,70 @@
},
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
+ mContext.registerReceiver(
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ ArrayList<String> available = intent.getStringArrayListExtra(
+ ConnectivityManager.EXTRA_AVAILABLE_TETHER);
+ ArrayList<String> active = intent.getStringArrayListExtra(
+ ConnectivityManager.EXTRA_ACTIVE_TETHER);
+ updateTetherState(available, active);
+
+ }
+ },new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
+
setWifiEnabledBlocking(wifiEnabled, false, Process.myUid());
+ setWifiApEnabledBlocking(wifiAPEnabled, true, Process.myUid(), null);
+ }
+
+ private void updateTetherState(ArrayList<String> available, ArrayList<String> tethered) {
+
+ boolean wifiTethered = false;
+ boolean wifiAvailable = false;
+
+ IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
+ INetworkManagementService service = INetworkManagementService.Stub.asInterface(b);
+
+ mCm = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
+ mWifiRegexs = mCm.getTetherableWifiRegexs();
+
+ for (String intf : available) {
+ for (String regex : mWifiRegexs) {
+ if (intf.matches(regex)) {
+
+ InterfaceConfiguration ifcg = null;
+ try {
+ ifcg = service.getInterfaceConfig(intf);
+ if (ifcg != null) {
+ /* IP/netmask: 169.254.2.1/255.255.255.0 */
+ ifcg.ipAddr = (169 << 24) + (254 << 16) + (2 << 8) + 1;
+ ifcg.netmask = (255 << 24) + (255 << 16) + (255 << 8) + 0;
+ ifcg.interfaceFlags = "up";
+
+ service.setInterfaceConfig(intf, ifcg);
+ }
+ } catch (Exception e) {
+ /**
+ * TODO: Add broadcast to indicate tether failed
+ */
+ Slog.e(TAG, "Error configuring interface " + intf + ", :" + e);
+ return;
+ }
+
+ /**
+ * TODO: Add broadcast to indicate tether failed
+ */
+ if(mCm.tether(intf) == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+ Slog.d(TAG, "Tethered "+intf);
+ } else {
+ Slog.e(TAG, "Error tethering "+intf);
+ }
+ break;
+ }
+ }
+ }
}
private boolean getPersistedWifiEnabled() {
@@ -337,12 +423,16 @@
* Avoid doing a disable when the current Wifi state is UNKNOWN
* TODO: Handle driver load fail and supplicant lost as seperate states
*/
- if (mWifiState == WIFI_STATE_UNKNOWN && !enable) {
+ if ((mWifiState == WIFI_STATE_UNKNOWN) && !enable) {
return false;
}
setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid);
+ if ((mWifiApState == WIFI_AP_STATE_ENABLED) && enable) {
+ setWifiApEnabledBlocking(false, true, Process.myUid(), null);
+ }
+
if (enable) {
synchronized (mWifiStateTracker) {
if (!WifiNative.loadDriver()) {
@@ -490,6 +580,154 @@
}
}
+ private boolean getPersistedWifiApEnabled() {
+ final ContentResolver cr = mContext.getContentResolver();
+ try {
+ return Settings.Secure.getInt(cr, Settings.Secure.WIFI_AP_ON) == 1;
+ } catch (Settings.SettingNotFoundException e) {
+ Settings.Secure.putInt(cr, Settings.Secure.WIFI_AP_ON, 0);
+ return false;
+ }
+ }
+
+ private void persistWifiApEnabled(boolean enabled) {
+ final ContentResolver cr = mContext.getContentResolver();
+ Settings.Secure.putInt(cr, Settings.Secure.WIFI_AP_ON, enabled ? 1 : 0);
+ }
+
+ /**
+ * see {@link android.net.wifi.WifiManager#startAccessPoint(WifiConfiguration)}
+ * @param wifiConfig SSID, security and channel details as
+ * part of WifiConfiguration
+ * @return {@code true} if the start operation was
+ * started or is already in the queue.
+ */
+ public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
+ enforceChangePermission();
+ if (mWifiHandler == null) return false;
+
+ synchronized (mWifiHandler) {
+
+ long ident = Binder.clearCallingIdentity();
+ sWakeLock.acquire();
+ Binder.restoreCallingIdentity(ident);
+
+ mLastEnableUid = Binder.getCallingUid();
+
+ sendAccessPointMessage(enabled, wifiConfig, Binder.getCallingUid());
+ }
+
+ return true;
+ }
+
+ /**
+ * Enables/disables Wi-Fi AP synchronously. The driver is loaded
+ * and soft access point configured as a single operation.
+ * @param enable {@code true} to turn Wi-Fi on, {@code false} to turn it off.
+ * @param persist {@code true} if the setting should be persisted.
+ * @param uid The UID of the process making the request.
+ * @param config The WifiConfiguration for AP
+ * @return {@code true} if the operation succeeds (or if the existing state
+ * is the same as the requested state)
+ */
+ /**
+ * TODO: persist needs to go away in WifiService
+ * This will affect all persist related functions
+ * for Access Point
+ */
+ private boolean setWifiApEnabledBlocking(boolean enable,
+ boolean persist, int uid, WifiConfiguration wifiConfig) {
+ final int eventualWifiApState = enable ? WIFI_AP_STATE_ENABLED : WIFI_AP_STATE_DISABLED;
+
+ if (mWifiApState == eventualWifiApState) {
+ return true;
+ }
+
+ setWifiApEnabledState(enable ? WIFI_AP_STATE_ENABLING : WIFI_AP_STATE_DISABLING, uid);
+
+ if (enable && (mWifiState == WIFI_STATE_ENABLED)) {
+ setWifiEnabledBlocking(false, true, Process.myUid());
+ }
+
+ if (enable) {
+ synchronized (mWifiStateTracker) {
+ if (!WifiNative.loadDriver()) {
+ Slog.e(TAG, "Failed to load Wi-Fi driver for AP mode");
+ setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid);
+ return false;
+ }
+ }
+
+ try {
+ nwService.startAccessPoint();
+ } catch(Exception e) {
+ Slog.e(TAG, "Exception in startAccessPoint()");
+ }
+
+ } else {
+
+ try {
+ nwService.stopAccessPoint();
+ } catch(Exception e) {
+ Slog.e(TAG, "Exception in stopAccessPoint()");
+ }
+
+ synchronized (mWifiStateTracker) {
+ if (!WifiNative.unloadDriver()) {
+ Slog.e(TAG, "Failed to unload Wi-Fi driver for AP mode");
+ setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid);
+ return false;
+ }
+ }
+ }
+
+ // Success!
+ if (persist) {
+ persistWifiApEnabled(enable);
+ }
+ setWifiApEnabledState(eventualWifiApState, uid);
+ return true;
+ }
+
+ /**
+ * see {@link WifiManager#getWifiApState()}
+ * @return One of {@link WifiManager#WIFI_AP_STATE_DISABLED},
+ * {@link WifiManager#WIFI_AP_STATE_DISABLING},
+ * {@link WifiManager#WIFI_AP_STATE_ENABLED},
+ * {@link WifiManager#WIFI_AP_STATE_ENABLING},
+ * {@link WifiManager#WIFI_AP_STATE_FAILED}
+ */
+ public int getWifiApEnabledState() {
+ enforceAccessPermission();
+ return mWifiApState;
+ }
+
+ private void setWifiApEnabledState(int wifiAPState, int uid) {
+ final int previousWifiApState = mWifiApState;
+
+ long ident = Binder.clearCallingIdentity();
+ try {
+ if (wifiAPState == WIFI_AP_STATE_ENABLED) {
+ mBatteryStats.noteWifiOn(uid);
+ } else if (wifiAPState == WIFI_AP_STATE_DISABLED) {
+ mBatteryStats.noteWifiOff(uid);
+ }
+ } catch (RemoteException e) {
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+
+ // Update state
+ mWifiApState = wifiAPState;
+
+ // Broadcast
+ final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, wifiAPState);
+ intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE, previousWifiApState);
+ mContext.sendStickyBroadcast(intent);
+ }
+
/**
* see {@link android.net.wifi.WifiManager#getConfiguredNetworks()}
* @return the list of configured networks
@@ -1472,6 +1710,12 @@
Message.obtain(mWifiHandler, MESSAGE_START_WIFI, scanOnlyMode ? 1 : 0, 0).sendToTarget();
}
+ private void sendAccessPointMessage(boolean enable, WifiConfiguration wifiConfig, int uid) {
+ Message.obtain(mWifiHandler,
+ (enable ? MESSAGE_START_ACCESS_POINT : MESSAGE_STOP_ACCESS_POINT),
+ 0, uid, wifiConfig).sendToTarget();
+ }
+
private void updateWifiState() {
// send a message so it's all serialized
Message.obtain(mWifiHandler, MESSAGE_UPDATE_STATE, 0, 0).sendToTarget();
@@ -1606,6 +1850,21 @@
}
}
break;
+
+ case MESSAGE_START_ACCESS_POINT:
+ setWifiApEnabledBlocking(true,
+ msg.arg1 == 1,
+ msg.arg2,
+ (WifiConfiguration) msg.obj);
+ break;
+
+ case MESSAGE_STOP_ACCESS_POINT:
+ setWifiApEnabledBlocking(false,
+ msg.arg1 == 1,
+ msg.arg2,
+ (WifiConfiguration) msg.obj);
+ sWakeLock.release();
+ break;
}
}
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index a263b23..9018872 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -4662,7 +4662,7 @@
* @param pids of dalvik VM processes to dump stack traces for
* @return file containing stack traces, or null if no dump file is configured
*/
- private static File dumpStackTraces(ArrayList<Integer> pids) {
+ public static File dumpStackTraces(ArrayList<Integer> pids) {
String tracesPath = SystemProperties.get("dalvik.vm.stack-trace-file", null);
if (tracesPath == null || tracesPath.length() == 0) {
return null;
@@ -8958,10 +8958,13 @@
* @param logFile to include in the report, null if none
* @param crashInfo giving an application stack trace, null if absent
*/
- private void addErrorToDropBox(String eventType,
+ public void addErrorToDropBox(String eventType,
ProcessRecord process, HistoryRecord activity, HistoryRecord parent,
String subject, String report, File logFile,
ApplicationErrorReport.CrashInfo crashInfo) {
+ // NOTE -- this must never acquire the ActivityManagerService lock,
+ // otherwise the watchdog may be prevented from resetting the system.
+
String dropboxTag;
if (process == null || process.pid == MY_PID) {
dropboxTag = "system_server_" + eventType;
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index ee54f73..78329db 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -40,7 +40,6 @@
import android.os.ServiceManager;
import android.provider.Settings;
import android.util.Log;
-import android.widget.Toast;
import com.android.internal.telephony.Phone;
import com.android.internal.util.HierarchicalState;
@@ -66,7 +65,6 @@
private Context mContext;
private final String TAG = "Tethering";
- private boolean mPlaySounds = false;
private boolean mBooted = false;
//used to remember if we got connected before boot finished
private boolean mDeferedUsbConnection = false;
@@ -78,8 +76,6 @@
private HashMap<String, TetherInterfaceSM> mIfaces;
- private ArrayList<String> mActiveTtys;
-
private BroadcastReceiver mStateReceiver;
private static final String USB_NEAR_IFACE_ADDR = "169.254.2.1";
@@ -112,7 +108,6 @@
}
mIfaces = new HashMap<String, TetherInterfaceSM>();
- mActiveTtys = new ArrayList<String>();
mTetherMasterSM = new TetherMasterSM("TetherMaster");
mTetherMasterSM.start();
@@ -323,142 +318,6 @@
mContext.sendStickyBroadcast(broadcast);
Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
activeList.size() + ", " + erroredList.size());
- // check if we need to send a USB notification
- // Check if the user wants to be bothered
- boolean tellUser = (Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.TETHER_NOTIFY, 0) == 1);
- for (Object o : activeList) {
- String s = (String)o;
- for (Object regexObject : mTetherableUsbRegexs) {
- if (s.matches((String)regexObject)) {
- showTetheredNotification();
- return;
- }
- }
- }
- if (tellUser) {
- for (Object o : availableList) {
- String s = (String)o;
- for (String match : mTetherableUsbRegexs) {
- if (s.matches(match)) {
- showTetherAvailableNotification();
- return;
- }
- }
- }
- }
- clearNotification();
- }
-
- private void showTetherAvailableNotification() {
- NotificationManager notificationManager = (NotificationManager)mContext.
- getSystemService(Context.NOTIFICATION_SERVICE);
- if (notificationManager == null) {
- return;
- }
- Intent intent = new Intent();
- intent.setClass(mContext, com.android.internal.app.TetherActivity.class);
-
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
-
- Resources r = Resources.getSystem();
- CharSequence title = r.getText(com.android.internal.R.string.
- tether_available_notification_title);
- CharSequence message = r.getText(com.android.internal.R.string.
- tether_available_notification_message);
-
- if(mTetheringNotification == null) {
- mTetheringNotification = new Notification();
- mTetheringNotification.when = 0;
- }
- mTetheringNotification.icon = com.android.internal.R.drawable.stat_sys_tether_usb;
-
- boolean playSounds = false;
- //playSounds = SystemProperties.get("persist.service.mount.playsnd", "1").equals("1");
- if (playSounds) {
- mTetheringNotification.defaults |= Notification.DEFAULT_SOUND;
- } else {
- mTetheringNotification.defaults &= ~Notification.DEFAULT_SOUND;
- }
-
- mTetheringNotification.flags = Notification.FLAG_ONGOING_EVENT;
- mTetheringNotification.tickerText = title;
- mTetheringNotification.setLatestEventInfo(mContext, title, message, pi);
-
- notificationManager.notify(mTetheringNotification.icon, mTetheringNotification);
-
- }
-
- private void showTetheredNotification() {
- NotificationManager notificationManager = (NotificationManager)mContext.
- getSystemService(Context.NOTIFICATION_SERVICE);
- if (notificationManager == null) {
- return;
- }
-
- Intent intent = new Intent();
- intent.setClass(mContext, com.android.internal.app.TetherActivity.class);
-
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0);
-
- Resources r = Resources.getSystem();
- CharSequence title = r.getText(com.android.internal.R.string.
- tether_stop_notification_title);
- CharSequence message = r.getText(com.android.internal.R.string.
- tether_stop_notification_message);
-
- if(mTetheringNotification == null) {
- mTetheringNotification = new Notification();
- mTetheringNotification.when = 0;
- }
- mTetheringNotification.icon = com.android.internal.R.drawable.stat_sys_tether_usb;
-
- boolean playSounds = false;
- //playSounds = SystemProperties.get("persist.service.mount.playsnd", "1").equals("1");
- if (playSounds) {
- mTetheringNotification.defaults |= Notification.DEFAULT_SOUND;
- } else {
- mTetheringNotification.defaults &= ~Notification.DEFAULT_SOUND;
- }
-
- mTetheringNotification.flags = Notification.FLAG_ONGOING_EVENT;
- mTetheringNotification.tickerText = title;
- mTetheringNotification.setLatestEventInfo(mContext, title, message, pi);
-
- notificationManager.notify(mTetheringNotification.icon, mTetheringNotification);
- }
-
- private void clearNotification() {
- NotificationManager notificationManager = (NotificationManager)mContext.
- getSystemService(Context.NOTIFICATION_SERVICE);
- if (notificationManager != null && mTetheringNotification != null) {
- notificationManager.cancel(mTetheringNotification.icon);
- mTetheringNotification = null;
- }
- }
-
- private void showErrorToast(int error) {
- int num;
- switch(error) {
- case ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR:
- case ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR:
- case ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR:
- case ConnectivityManager.TETHER_ERROR_MASTER_ERROR:
- num = com.android.internal.R.string.tether_error_message;
- break;
- case ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR:
- case ConnectivityManager.TETHER_ERROR_DISABLE_NAT_ERROR:
- num = com.android.internal.R.string.tether_stop_error_message;
- break;
- default:
- // do nothing
- return;
- }
- String text = mContext.getResources().getString(num) + " - EC" + error;
- Log.e(TAG, text);
- Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
}
private class StateReceiver extends BroadcastReceiver {
@@ -748,7 +607,6 @@
// further error..
Tethering.this.configureUsbIface(false);
}
- Tethering.this.showErrorToast(error);
}
}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 6797f78..32e7176 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1311,7 +1311,12 @@
number = extractNetworkPortionAlt(number);
// retrieve the list of emergency numbers
- String numbers = SystemProperties.get("ro.ril.ecclist");
+ // check read-write ecclist property first
+ String numbers = SystemProperties.get("ril.ecclist");
+ if (TextUtils.isEmpty(numbers)) {
+ // then read-only ecclist property since old RIL only uses this
+ numbers = SystemProperties.get("ro.ril.ecclist");
+ }
if (!TextUtils.isEmpty(numbers)) {
// searches through the comma-separated list for a match,
diff --git a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
index 6352b41..e4fcf6c 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GsmServiceStateTracker.java
@@ -1630,7 +1630,7 @@
notificationId = PS_NOTIFICATION;
break;
case CS_ENABLED:
- details = context.getText(com.android.internal.R.string.RestrictedOnAll);;
+ details = context.getText(com.android.internal.R.string.RestrictedOnAllVoice);;
break;
case CS_NORMAL_ENABLED:
details = context.getText(com.android.internal.R.string.RestrictedOnNormal);;
diff --git a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java b/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java
index aa2981b..02590d3 100644
--- a/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java
+++ b/telephony/tests/telephonytests/src/android/telephony/PhoneNumberUtilsTest.java
@@ -401,7 +401,7 @@
PhoneNumberUtils.convertKeypadLettersToDigits("(800) ABC-DEFG"));
}
- @SmallTest
+ // To run this test, the device has to be registered with network
public void testCheckAndProcessPlusCode() {
assertEquals("0118475797000",
PhoneNumberUtils.cdmaCheckAndProcessPlusCode("+8475797000"));
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index f3738e30..d833e33 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -29,7 +29,7 @@
interface IWifiManager
{
List<WifiConfiguration> getConfiguredNetworks();
-
+
int addOrUpdateNetwork(in WifiConfiguration config);
boolean removeNetwork(int netId);
@@ -47,7 +47,7 @@
boolean disconnect();
boolean reconnect();
-
+
boolean reassociate();
WifiInfo getConnectionInfo();
@@ -61,7 +61,7 @@
boolean setNumAllowedChannels(int numChannels, boolean persist);
int[] getValidChannelCounts();
-
+
boolean saveConfiguration();
DhcpInfo getDhcpInfo();
@@ -77,5 +77,9 @@
void acquireMulticastLock(IBinder binder, String tag);
void releaseMulticastLock();
+
+ boolean setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
+
+ int getWifiApEnabledState();
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 178f76e..9ef8ba1 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -123,7 +123,88 @@
* @see #getWifiState()
*/
public static final int WIFI_STATE_UNKNOWN = 4;
-
+
+ /**
+ * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled,
+ * enabling, disabling, or failed.
+ *
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String WIFI_AP_STATE_CHANGED_ACTION =
+ "android.net.wifi.WIFI_AP_STATE_CHANGED";
+
+ /**
+ * The lookup key for an int that indicates whether Wi-Fi AP is enabled,
+ * disabled, enabling, disabling, or failed. Retrieve it with
+ * {@link android.content.Intent#getIntExtra(String,int)}.
+ *
+ * @see #WIFI_AP_STATE_DISABLED
+ * @see #WIFI_AP_STATE_DISABLING
+ * @see #WIFI_AP_STATE_ENABLED
+ * @see #WIFI_AP_STATE_ENABLING
+ * @see #WIFI_AP_STATE_FAILED
+ *
+ * @hide
+ */
+ public static final String EXTRA_WIFI_AP_STATE = "wifi_state";
+ /**
+ * The previous Wi-Fi state.
+ *
+ * @see #EXTRA_WIFI_AP_STATE
+ *
+ * @hide
+ */
+ public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
+ /**
+ * Wi-Fi AP is currently being disabled. The state will change to
+ * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully.
+ *
+ * @see #WIFI_AP_STATE_CHANGED_ACTION
+ * @see #getWifiApState()
+ *
+ * @hide
+ */
+ public static final int WIFI_AP_STATE_DISABLING = 0;
+ /**
+ * Wi-Fi AP is disabled.
+ *
+ * @see #WIFI_AP_STATE_CHANGED_ACTION
+ * @see #getWifiState()
+ *
+ * @hide
+ */
+ public static final int WIFI_AP_STATE_DISABLED = 1;
+ /**
+ * Wi-Fi AP is currently being enabled. The state will change to
+ * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully.
+ *
+ * @see #WIFI_AP_STATE_CHANGED_ACTION
+ * @see #getWifiApState()
+ *
+ * @hide
+ */
+ public static final int WIFI_AP_STATE_ENABLING = 2;
+ /**
+ * Wi-Fi AP is enabled.
+ *
+ * @see #WIFI_AP_STATE_CHANGED_ACTION
+ * @see #getWifiApState()
+ *
+ * @hide
+ */
+ public static final int WIFI_AP_STATE_ENABLED = 3;
+ /**
+ * Wi-Fi AP is in a failed state. This state will occur when an error occurs during
+ * enabling or disabling
+ *
+ * @see #WIFI_AP_STATE_CHANGED_ACTION
+ * @see #getWifiApState()
+ *
+ * @hide
+ */
+ public static final int WIFI_AP_STATE_FAILED = 4;
+
/**
* Broadcast intent action indicating that a connection to the supplicant has
* been established (and it is now possible
@@ -681,6 +762,54 @@
}
/**
+ * Start AccessPoint mode with the specified
+ * configuration. If the radio is already running in
+ * AP mode, update the new configuration
+ * Note that starting in access point mode disables station
+ * mode operation
+ * @param wifiConfig SSID, security and channel details as
+ * part of WifiConfiguration
+ * @return {@code true} if the operation succeeds, {@code false} otherwise
+ *
+ * @hide Dont open up yet
+ */
+ public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
+ try {
+ return mService.setWifiApEnabled(wifiConfig, enabled);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Gets the Wi-Fi enabled state.
+ * @return One of {@link #WIFI_AP_STATE_DISABLED},
+ * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
+ * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
+ * @see #isWifiApEnabled()
+ *
+ * @hide Dont open yet
+ */
+ public int getWifiApState() {
+ try {
+ return mService.getWifiApEnabledState();
+ } catch (RemoteException e) {
+ return WIFI_AP_STATE_FAILED;
+ }
+ }
+
+ /**
+ * Return whether Wi-Fi AP is enabled or disabled.
+ * @return {@code true} if Wi-Fi AP is enabled
+ * @see #getWifiApState()
+ *
+ * @hide Dont open yet
+ */
+ public boolean isWifiApEnabled() {
+ return getWifiApState() == WIFI_AP_STATE_ENABLED;
+ }
+
+ /**
* Allows an application to keep the Wi-Fi radio awake.
* Normally the Wi-Fi radio may turn off when the user has not used the device in a while.
* Acquiring a WifiLock will keep the radio on until the lock is released. Multiple