summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmds/installd/commands.c16
-rw-r--r--cmds/keystore/keystore_get.h8
-rw-r--r--core/java/android/app/SearchDialog.java2
-rw-r--r--core/java/android/content/pm/PackageManager.java17
-rw-r--r--core/java/android/os/INetworkManagementService.aidl3
-rw-r--r--core/java/android/provider/Settings.java21
-rw-r--r--core/java/android/webkit/WebView.java1
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java47
-rwxr-xr-xcore/java/com/android/internal/app/IMediaContainerService.aidl1
-rw-r--r--core/java/com/android/internal/content/PackageHelper.java3
-rw-r--r--core/res/res/drawable-hdpi/ic_btn_search_go.pngbin0 -> 1338 bytes
-rw-r--r--core/res/res/drawable-hdpi/ic_btn_search_play.pngbin960 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_btn_search_go.pngbin0 -> 1046 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_btn_search_play.pngbin677 -> 0 bytes
-rw-r--r--core/res/res/layout-land/usb_storage_activity.xml13
-rw-r--r--core/res/res/layout/usb_storage_activity.xml11
-rw-r--r--core/res/res/values/strings.xml2
-rw-r--r--libs/audioflinger/AudioFlinger.cpp14
-rw-r--r--libs/audioflinger/AudioPolicyManagerBase.cpp34
-rw-r--r--libs/surfaceflinger/LayerBase.cpp1
-rw-r--r--libs/surfaceflinger/LayerBase.h4
-rw-r--r--libs/surfaceflinger/SurfaceFlinger.cpp72
-rw-r--r--media/libmedia/AudioSystem.cpp15
-rw-r--r--packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java77
-rw-r--r--services/java/com/android/server/MountService.java56
-rw-r--r--services/java/com/android/server/NetworkManagementService.java35
-rw-r--r--services/java/com/android/server/PackageManagerService.java62
-rw-r--r--services/java/com/android/server/UiModeManagerService.java20
-rw-r--r--services/java/com/android/server/WifiService.java153
-rw-r--r--services/java/com/android/server/status/StatusBarService.java2
-rw-r--r--services/java/com/android/server/status/UsbStorageActivity.java42
-rwxr-xr-xtests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java145
-rw-r--r--wifi/java/android/net/wifi/IWifiManager.aidl2
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java14
34 files changed, 660 insertions, 233 deletions
diff --git a/cmds/installd/commands.c b/cmds/installd/commands.c
index 654ee68..b8ba3f6 100644
--- a/cmds/installd/commands.c
+++ b/cmds/installd/commands.c
@@ -389,9 +389,10 @@ int get_size(const char *pkgname, const char *apkpath,
int cachesize = 0;
/* count the source apk as code -- but only if it's not
- * on the /system partition
+ * on the /system partition and its not on the sdcard.
*/
- if (strncmp(apkpath, "/system", 7) != 0) {
+ if (strncmp(apkpath, "/system", 7) != 0 &&
+ strncmp(apkpath, SDCARD_DIR_PREFIX, 7) != 0) {
if (stat(apkpath, &s) == 0) {
codesize += stat_size(&s);
}
@@ -403,17 +404,6 @@ int get_size(const char *pkgname, const char *apkpath,
codesize += stat_size(&s);
}
}
-
- /* count the source apk as code -- but only if it's not
- * installed on the sdcard
- */
- if (strncmp(apkpath, SDCARD_DIR_PREFIX, 7) != 0) {
- if (stat(apkpath, &s) == 0) {
- codesize += stat_size(&s);
- }
- }
-
-
/* count the cached dexfile as code */
if (!create_cache_path(path, apkpath)) {
if (stat(path, &s) == 0) {
diff --git a/cmds/keystore/keystore_get.h b/cmds/keystore/keystore_get.h
index 8330f8e..141f69b 100644
--- a/cmds/keystore/keystore_get.h
+++ b/cmds/keystore/keystore_get.h
@@ -32,9 +32,11 @@ extern "C" {
#endif
/* This function is provided for native components to get values from keystore.
- * Users are required to link against libcutils. The lengths of keys and values
- * are limited to KEYSTORE_MESSAGE_SIZE. This function returns the length of
- * the requested value or -1 if something goes wrong. */
+ * Users are required to link against libcutils. Keys are values are 8-bit safe.
+ * The first two arguments are the key and its length. The third argument
+ * specifies the buffer to store the retrieved value, which must be an array of
+ * KEYSTORE_MESSAGE_SIZE bytes. This function returns the length of the value or
+ * -1 if an error happens. */
static int keystore_get(const char *key, int length, char *value)
{
uint8_t bytes[2] = {length >> 8, length};
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index ebc64d7..add99d7 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -483,7 +483,7 @@ public class SearchDialog extends Dialog implements OnItemClickListener, OnItemS
int textId = mSearchable.getSearchButtonText();
if (isBrowserSearch()){
iconLabel = getContext().getResources()
- .getDrawable(com.android.internal.R.drawable.ic_btn_search_play);
+ .getDrawable(com.android.internal.R.drawable.ic_btn_search_go);
} else if (textId != 0) {
textLabel = mActivityContext.getResources().getString(textId);
} else {
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 271f477..e1fbe48 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -439,6 +439,15 @@ public abstract class PackageManager {
public static final int INSTALL_FAILED_INVALID_INSTALL_LOCATION = -19;
/**
+ * Installation return code: this is passed to the {@link IPackageInstallObserver} by
+ * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
+ * the new package couldn't be installed in the specified install
+ * location because the media is not available.
+ * @hide
+ */
+ public static final int INSTALL_FAILED_MEDIA_UNAVAILABLE = -20;
+
+ /**
* Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
* if the parser was given a path that is not a file, or does not end with the expected
@@ -586,6 +595,14 @@ public abstract class PackageManager {
public static final int MOVE_FAILED_INVALID_LOCATION = -5;
/**
+ * Error code that is passed to the {@link IPackageMoveObserver} by
+ * {@link #movePackage(android.net.Uri, IPackageMoveObserver)}
+ * if the specified package cannot be moved to the specified location.
+ * @hide
+ */
+ public static final int MOVE_FAILED_INTERNAL_ERROR = -6;
+
+ /**
* Flag parameter for {@link #movePackage} to indicate that
* the package should be moved to internal storage if its
* been installed on external media.
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index d1d8b0a..afe4191 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -19,6 +19,7 @@ package android.os;
import android.net.InterfaceConfiguration;
import android.net.INetworkManagementEventObserver;
+import android.net.wifi.WifiConfiguration;
/**
* @hide
@@ -166,7 +167,7 @@ interface INetworkManagementService
/**
* Start Wifi Access Point
*/
- void startAccessPoint();
+ void startAccessPoint(in WifiConfiguration wifiConfig, String intf);
/**
* Stop Wifi Access Point
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 503d8b8d..66f340e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2502,6 +2502,27 @@ public final class Settings {
public static final String WIFI_AP_ON = "wifi_ap_on";
/**
+ * AP SSID
+ *
+ * @hide
+ */
+ public static final String WIFI_AP_SSID = "wifi_ap_ssid";
+
+ /**
+ * AP security
+ *
+ * @hide
+ */
+ public static final String WIFI_AP_SECURITY = "wifi_ap_security";
+
+ /**
+ * AP passphrase
+ *
+ * @hide
+ */
+ public static final String WIFI_AP_PASSWD = "wifi_ap_passwd";
+
+ /**
* The acceptable packet loss percentage (range 0 - 100) before trying
* another AP on the same network.
*/
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 034a631..3a34fb4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -3851,7 +3851,6 @@ public class WebView extends AbsoluteLayout
|| keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
if (nativeFocusIsPlugin()) {
mShiftIsPressed = false;
- return true;
} else if (commitCopy()) {
return true;
}
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 9537ba0..5482958 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -985,6 +985,11 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
/** {@inheritDoc} */
public void onFilterComplete(int count) {
+ updateDropDownForFilter(count);
+
+ }
+
+ private void updateDropDownForFilter(int count) {
// Not attached to window, don't update drop-down
if (getWindowVisibility() == View.GONE) return;
@@ -1214,18 +1219,30 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
ViewGroup dropDownView;
int otherHeights = 0;
- if (mAdapter != null) {
+ final ListAdapter adapter = mAdapter;
+ if (adapter != null) {
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) {
- int N = mAdapter.getCount();
- if (N > 20) N = 20;
- CompletionInfo[] completions = new CompletionInfo[N];
- for (int i = 0; i < N; i++) {
- Object item = mAdapter.getItem(i);
- long id = mAdapter.getItemId(i);
- completions[i] = new CompletionInfo(id, i,
- convertSelectionToString(item));
+ final int count = Math.min(adapter.getCount(), 20);
+ CompletionInfo[] completions = new CompletionInfo[count];
+ int realCount = 0;
+
+ for (int i = 0; i < count; i++) {
+ if (adapter.isEnabled(i)) {
+ realCount++;
+ Object item = adapter.getItem(i);
+ long id = adapter.getItemId(i);
+ completions[i] = new CompletionInfo(id, i,
+ convertSelectionToString(item));
+ }
}
+
+ if (realCount != count) {
+ CompletionInfo[] tmp = new CompletionInfo[realCount];
+ System.arraycopy(completions, 0, tmp, 0, realCount);
+ completions = tmp;
+ }
+
imm.displayCompletions(this, completions);
}
}
@@ -1253,7 +1270,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
mDropDownList = new DropDownListView(context);
mDropDownList.setSelector(mDropDownListHighlight);
- mDropDownList.setAdapter(mAdapter);
+ mDropDownList.setAdapter(adapter);
mDropDownList.setVerticalFadingEdgeEnabled(true);
mDropDownList.setOnItemClickListener(mDropDownItemClickListener);
mDropDownList.setFocusable(true);
@@ -1599,6 +1616,16 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
if (isPopupShowing()) {
// This will resize the popup to fit the new adapter's content
showDropDown();
+ } else if (mAdapter != null) {
+ // If the popup is not showing already, showing it will cause
+ // the list of data set observers attached to the adapter to
+ // change. We can't do it from here, because we are in the middle
+ // of iterating throught he list of observers.
+ post(new Runnable() {
+ public void run() {
+ updateDropDownForFilter(mAdapter.getCount());
+ }
+ });
}
}
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
index fd1fd58..badabb0 100755
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -27,4 +27,5 @@ interface IMediaContainerService {
boolean copyResource(in Uri packageURI,
in ParcelFileDescriptor outStream);
PackageInfoLite getMinimalPackageInfo(in Uri fileUri);
+ boolean checkFreeStorage(boolean external, in Uri fileUri);
} \ No newline at end of file
diff --git a/core/java/com/android/internal/content/PackageHelper.java b/core/java/com/android/internal/content/PackageHelper.java
index 80efca4..4d0a9e0 100644
--- a/core/java/com/android/internal/content/PackageHelper.java
+++ b/core/java/com/android/internal/content/PackageHelper.java
@@ -38,6 +38,7 @@ public class PackageHelper {
public static final int RECOMMEND_FAILED_INVALID_APK = -2;
public static final int RECOMMEND_FAILED_INVALID_LOCATION = -3;
public static final int RECOMMEND_FAILED_ALREADY_EXISTS = -4;
+ public static final int RECOMMEND_MEDIA_UNAVAILABLE = -5;
private static final boolean localLOGV = true;
private static final String TAG = "PackageHelper";
// App installation location settings values
@@ -70,7 +71,7 @@ public class PackageHelper {
try {
int rc = mountService.createSecureContainer(
- cid, mbLen, "vfat", sdEncKey, uid);
+ cid, mbLen, "fat", sdEncKey, uid);
if (rc != StorageResultCode.OperationSucceeded) {
Log.e(TAG, "Failed to create secure container " + cid);
return null;
diff --git a/core/res/res/drawable-hdpi/ic_btn_search_go.png b/core/res/res/drawable-hdpi/ic_btn_search_go.png
new file mode 100644
index 0000000..8a3a402
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_btn_search_go.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_btn_search_play.png b/core/res/res/drawable-hdpi/ic_btn_search_play.png
deleted file mode 100644
index fb1b974..0000000
--- a/core/res/res/drawable-hdpi/ic_btn_search_play.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_search_go.png b/core/res/res/drawable-mdpi/ic_btn_search_go.png
new file mode 100644
index 0000000..0ed9e8e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_btn_search_go.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_btn_search_play.png b/core/res/res/drawable-mdpi/ic_btn_search_play.png
deleted file mode 100644
index dc25dae..0000000
--- a/core/res/res/drawable-mdpi/ic_btn_search_play.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/layout-land/usb_storage_activity.xml b/core/res/res/layout-land/usb_storage_activity.xml
index d714479..50ca569 100644
--- a/core/res/res/layout-land/usb_storage_activity.xml
+++ b/core/res/res/layout-land/usb_storage_activity.xml
@@ -24,7 +24,7 @@
<TextView android:id="@+id/banner"
android:layout_centerHorizontal="true"
- android:layout_below="@id/icon"
+ android:layout_alignParentTop="true"
android:layout_marginTop="10dip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -45,8 +45,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
- android:layout_below="@id/message"
- android:layout_marginTop="20dip"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="20dip"
>
<Button android:id="@+id/mount_button"
@@ -64,6 +64,13 @@
android:paddingRight="18dip"
android:text="@string/usb_storage_stop_button_mount"
/>
+ <ProgressBar android:id="@+id/progress"
+ android:visibility="gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:indeterminate="true"
+ style="?android:attr/progressBarStyle"
+ />
</RelativeLayout>
</RelativeLayout>
diff --git a/core/res/res/layout/usb_storage_activity.xml b/core/res/res/layout/usb_storage_activity.xml
index 86bfadb..76c30fd 100644
--- a/core/res/res/layout/usb_storage_activity.xml
+++ b/core/res/res/layout/usb_storage_activity.xml
@@ -37,8 +37,8 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
- android:layout_below="@id/message"
- android:layout_marginTop="20dip"
+ android:layout_alignParentBottom="true"
+ android:layout_marginBottom="20dip"
>
<Button android:id="@+id/mount_button"
@@ -56,6 +56,13 @@
android:paddingRight="18dip"
android:text="@string/usb_storage_stop_button_mount"
/>
+ <ProgressBar android:id="@+id/progress"
+ android:visibility="gone"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:indeterminate="true"
+ style="?android:attr/progressBarStyle"
+ />
</RelativeLayout>
</RelativeLayout>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 584fe25..bf7425f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2013,6 +2013,8 @@
<item quantity="one">Open Wi-Fi network available</item>
<item quantity="other">Open Wi-Fi networks available</item>
</plurals>
+ <!-- Do not translate. Default access point SSID used for tethering -->
+ <string name="wifi_tether_configure_ssid_default" translatable="false">AndroidAP</string>
<!-- Name of the dialog that lets the user choose an accented character to insert -->
<string name="select_character">Insert character</string>
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 7902212..815a367 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -72,6 +72,10 @@ static const float MAX_GAIN = 4096.0f;
// 50 * ~20msecs = 1 second
static const int8_t kMaxTrackRetries = 50;
static const int8_t kMaxTrackStartupRetries = 50;
+// allow less retry attempts on direct output thread.
+// direct outputs can be a scarce resource in audio hardware and should
+// be released as quickly as possible.
+static const int8_t kMaxTrackRetriesDirect = 2;
static const int kDumpLockRetries = 50;
static const int kDumpLockSleep = 20000;
@@ -1794,6 +1798,9 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
uint32_t activeSleepTime = activeSleepTimeUs();
uint32_t idleSleepTime = idleSleepTimeUs();
uint32_t sleepTime = idleSleepTime;
+ // use shorter standby delay as on normal output to release
+ // hardware resources as soon as possible
+ nsecs_t standbyDelay = microseconds(activeSleepTime*2);
while (!exitPending())
@@ -1810,6 +1817,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
mixBufferSize = mFrameCount*mFrameSize;
activeSleepTime = activeSleepTimeUs();
idleSleepTime = idleSleepTimeUs();
+ standbyDelay = microseconds(activeSleepTime*2);
}
// put audio hardware into standby after short delay
@@ -1842,7 +1850,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
}
}
- standbyTime = systemTime() + kStandbyTimeInNsecs;
+ standbyTime = systemTime() + standbyDelay;
sleepTime = idleSleepTime;
continue;
}
@@ -1896,7 +1904,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
}
// reset retry count
- track->mRetryCount = kMaxTrackRetries;
+ track->mRetryCount = kMaxTrackRetriesDirect;
activeTrack = t;
mixerStatus = MIXER_TRACKS_READY;
} else {
@@ -1949,7 +1957,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
activeTrack->releaseBuffer(&buffer);
}
sleepTime = 0;
- standbyTime = systemTime() + kStandbyTimeInNsecs;
+ standbyTime = systemTime() + standbyDelay;
} else {
if (sleepTime == 0) {
if (mixerStatus == MIXER_TRACKS_ENABLED) {
diff --git a/libs/audioflinger/AudioPolicyManagerBase.cpp b/libs/audioflinger/AudioPolicyManagerBase.cpp
index a61221a..c8b3f48 100644
--- a/libs/audioflinger/AudioPolicyManagerBase.cpp
+++ b/libs/audioflinger/AudioPolicyManagerBase.cpp
@@ -458,11 +458,8 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
}
#endif //AUDIO_POLICY_TEST
- // open a direct output if:
- // 1 a direct output is explicitely requested
- // 2 the audio format is compressed
- if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
- (format !=0 && !AudioSystem::isLinearPCM(format))) {
+ // open a direct output if required by specified parameters
+ if (needsDirectOuput(stream, samplingRate, format, channels, flags, device)) {
LOGV("getOutput() opening direct output device %x", device);
AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor();
@@ -472,7 +469,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str
outputDesc->mChannels = channels;
outputDesc->mLatency = 0;
outputDesc->mFlags = (AudioSystem::output_flags)(flags | AudioSystem::OUTPUT_FLAG_DIRECT);
- outputDesc->mRefCount[stream] = 1;
+ outputDesc->mRefCount[stream] = 0;
output = mpClientInterface->openOutput(&outputDesc->mDevice,
&outputDesc->mSamplingRate,
&outputDesc->mFormat,
@@ -609,6 +606,9 @@ status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output, AudioSyste
setStrategyMute(STRATEGY_MEDIA, false, mA2dpOutput, mOutputs.valueFor(mHardwareOutput)->mLatency*2);
}
#endif
+ if (output != mHardwareOutput) {
+ setOutputDevice(mHardwareOutput, getNewDevice(mHardwareOutput), true);
+ }
return NO_ERROR;
} else {
LOGW("stopOutput() refcount is already 0 for output %d", output);
@@ -1550,10 +1550,10 @@ void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t
}
#ifdef WITH_A2DP
// filter devices according to output selected
- if (output == mHardwareOutput) {
- device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
- } else {
+ if (output == mA2dpOutput) {
device &= AudioSystem::DEVICE_OUT_ALL_A2DP;
+ } else {
+ device &= ~AudioSystem::DEVICE_OUT_ALL_A2DP;
}
#endif
@@ -1562,8 +1562,7 @@ void AudioPolicyManagerBase::setOutputDevice(audio_io_handle_t output, uint32_t
// - the requestede device is 0
// - the requested device is the same as current device and force is not specified.
// Doing this check here allows the caller to call setOutputDevice() without conditions
- if (device == 0 ||
- (device == prevDevice && !force)) {
+ if ((device == 0 || device == prevDevice) && !force) {
LOGV("setOutputDevice() setting same device %x or null device for output %d", device, output);
return;
}
@@ -1666,7 +1665,7 @@ float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_hand
int volInt = (100 * (index - streamDesc.mIndexMin)) / (streamDesc.mIndexMax - streamDesc.mIndexMin);
volume = AudioSystem::linearToLog(volInt);
- // if a heaset is connected, apply the following rules to ring tones and notifications
+ // if a headset is connected, apply the following rules to ring tones and notifications
// to avoid sound level bursts in user's ears:
// - always attenuate ring tones and notifications volume by 6dB
// - if music is playing, always limit the volume to current music volume,
@@ -1825,6 +1824,17 @@ void AudioPolicyManagerBase::handleIncallSonification(int stream, bool starting,
}
}
+bool AudioPolicyManagerBase::needsDirectOuput(AudioSystem::stream_type stream,
+ uint32_t samplingRate,
+ uint32_t format,
+ uint32_t channels,
+ AudioSystem::output_flags flags,
+ uint32_t device)
+{
+ return ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) ||
+ (format !=0 && !AudioSystem::isLinearPCM(format)));
+}
+
// --- AudioOutputDescriptor class implementation
AudioPolicyManagerBase::AudioOutputDescriptor::AudioOutputDescriptor()
diff --git a/libs/surfaceflinger/LayerBase.cpp b/libs/surfaceflinger/LayerBase.cpp
index 140f10c..efbc77a 100644
--- a/libs/surfaceflinger/LayerBase.cpp
+++ b/libs/surfaceflinger/LayerBase.cpp
@@ -214,7 +214,6 @@ uint32_t LayerBase::doTransaction(uint32_t flags)
if ((front.w != temp.w) || (front.h != temp.h)) {
// invalidate and recompute the visible regions if needed
flags |= Layer::eVisibleRegion;
- this->contentDirty = true;
}
if (temp.sequence != front.sequence) {
diff --git a/libs/surfaceflinger/LayerBase.h b/libs/surfaceflinger/LayerBase.h
index a6e5644..62ec839 100644
--- a/libs/surfaceflinger/LayerBase.h
+++ b/libs/surfaceflinger/LayerBase.h
@@ -157,11 +157,11 @@ public:
/**
* setCoveredRegion - called when the covered region changes. The covered
- * region correspond to any area of the surface that is covered
+ * region corresponds to any area of the surface that is covered
* (transparently or not) by another surface.
*/
virtual void setCoveredRegion(const Region& coveredRegion);
-
+
/**
* validateVisibility - cache a bunch of things
*/
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 26ee285..0722fda 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -674,6 +674,8 @@ void SurfaceFlinger::computeVisibleRegions(
{
const GraphicPlane& plane(graphicPlane(0));
const Transform& planeTransform(plane.transform());
+ const DisplayHardware& hw(plane.displayHardware());
+ const Region screenRegion(hw.bounds());
Region aboveOpaqueLayers;
Region aboveCoveredLayers;
@@ -689,31 +691,56 @@ void SurfaceFlinger::computeVisibleRegions(
// start with the whole surface at its current location
const Layer::State& s(layer->drawingState());
- // handle hidden surfaces by setting the visible region to empty
+ /*
+ * opaqueRegion: area of a surface that is fully opaque.
+ */
Region opaqueRegion;
+
+ /*
+ * visibleRegion: area of a surface that is visible on screen
+ * and not fully transparent. This is essentially the layer's
+ * footprint minus the opaque regions above it.
+ * Areas covered by a translucent surface are considered visible.
+ */
Region visibleRegion;
+
+ /*
+ * coveredRegion: area of a surface that is covered by all
+ * visible regions above it (which includes the translucent areas).
+ */
Region coveredRegion;
+
+
+ // handle hidden surfaces by setting the visible region to empty
if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
const bool translucent = layer->needsBlending();
const Rect bounds(layer->visibleBounds());
visibleRegion.set(bounds);
- coveredRegion = visibleRegion;
-
- // Remove the transparent area from the visible region
- if (translucent) {
- visibleRegion.subtractSelf(layer->transparentRegionScreen);
- }
+ visibleRegion.andSelf(screenRegion);
+ if (!visibleRegion.isEmpty()) {
+ // Remove the transparent area from the visible region
+ if (translucent) {
+ visibleRegion.subtractSelf(layer->transparentRegionScreen);
+ }
- // compute the opaque region
- if (s.alpha==255 && !translucent && layer->getOrientation()>=0) {
- // the opaque region is the visible region
- opaqueRegion = visibleRegion;
+ // compute the opaque region
+ const int32_t layerOrientation = layer->getOrientation();
+ if (s.alpha==255 && !translucent &&
+ ((layerOrientation & Transform::ROT_INVALID) == false)) {
+ // the opaque region is the layer's footprint
+ opaqueRegion = visibleRegion;
+ }
}
}
+ // Clip the covered region to the visible region
+ coveredRegion = aboveCoveredLayers.intersect(visibleRegion);
+
+ // Update aboveCoveredLayers for next (lower) layer
+ aboveCoveredLayers.orSelf(visibleRegion);
+
// subtract the opaque region covered by the layers above us
visibleRegion.subtractSelf(aboveOpaqueLayers);
- coveredRegion.andSelf(aboveCoveredLayers);
// compute this layer's dirty region
if (layer->contentDirty) {
@@ -724,19 +751,30 @@ void SurfaceFlinger::computeVisibleRegions(
layer->contentDirty = false;
} else {
/* compute the exposed region:
- * exposed = what's VISIBLE and NOT COVERED now
- * but was COVERED before
+ * the exposed region consists of two components:
+ * 1) what's VISIBLE now and was COVERED before
+ * 2) what's EXPOSED now less what was EXPOSED before
+ *
+ * note that (1) is conservative, we start with the whole
+ * visible region but only keep what used to be covered by
+ * something -- which mean it may have been exposed.
+ *
+ * (2) handles areas that were not covered by anything but got
+ * exposed because of a resize.
*/
- dirty = (visibleRegion - coveredRegion) & layer->coveredRegionScreen;
+ const Region newExposed = visibleRegion - coveredRegion;
+ const Region oldVisibleRegion = layer->visibleRegionScreen;
+ const Region oldCoveredRegion = layer->coveredRegionScreen;
+ const Region oldExposed = oldVisibleRegion - oldCoveredRegion;
+ dirty = (visibleRegion&oldCoveredRegion) | (newExposed-oldExposed);
}
dirty.subtractSelf(aboveOpaqueLayers);
// accumulate to the screen dirty region
dirtyRegion.orSelf(dirty);
- // Update aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
+ // Update aboveOpaqueLayers for next (lower) layer
aboveOpaqueLayers.orSelf(opaqueRegion);
- aboveCoveredLayers.orSelf(visibleRegion);
// Store the visible region is screen space
layer->setVisibleRegion(visibleRegion);
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 4b364f2..5e6ce42 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -358,7 +358,7 @@ unsigned int AudioSystem::getInputFramesLost(audio_io_handle_t ioHandle) {
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
unsigned int result = 0;
if (af == 0) return result;
- if (ioHandle == NULL) return result;
+ if (ioHandle == 0) return result;
result = af->getInputFramesLost(ioHandle);
return result;
@@ -556,7 +556,18 @@ audio_io_handle_t AudioSystem::getOutput(stream_type stream,
output_flags flags)
{
audio_io_handle_t output = 0;
- if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0) {
+ // Do not use stream to output map cache if the direct output
+ // flag is set or if we are likely to use a direct output
+ // (e.g voice call stream @ 8kHz could use BT SCO device and be routed to
+ // a direct output on some platforms).
+ // TODO: the output cache and stream to output mapping implementation needs to
+ // be reworked for proper operation with direct outputs. This code is too specific
+ // to the first use case we want to cover (Voice Recognition and Voice Dialer over
+ // Bluetooth SCO
+ if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) == 0 &&
+ ((stream != AudioSystem::VOICE_CALL && stream != AudioSystem::BLUETOOTH_SCO) ||
+ channels != AudioSystem::CHANNEL_OUT_MONO ||
+ (samplingRate != 8000 && samplingRate != 16000))) {
Mutex::Autolock _l(gLock);
output = AudioSystem::gStreamOutputMap.valueFor(stream);
LOGV_IF((output != 0), "getOutput() read %d from cache for stream %d", output, stream);
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index c6b617d..77d11cc 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -24,7 +24,6 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.Package;
import android.net.Uri;
import android.os.Environment;
import android.os.IBinder;
@@ -45,7 +44,6 @@ import java.io.IOException;
import java.io.InputStream;
import android.os.FileUtils;
-import android.os.storage.IMountService;
import android.provider.Settings;
/*
@@ -130,26 +128,21 @@ public class DefaultContainerService extends IntentService {
ret.packageName = pkg.packageName;
ret.installLocation = pkg.installLocation;
// Nuke the parser reference right away and force a gc
- Runtime.getRuntime().gc();
packageParser = null;
+ Runtime.getRuntime().gc();
if (pkg == null) {
Log.w(TAG, "Failed to parse package");
ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INVALID_APK;
return ret;
}
ret.packageName = pkg.packageName;
- int loc = recommendAppInstallLocation(pkg.installLocation, archiveFilePath);
- if (loc == PackageManager.INSTALL_EXTERNAL) {
- ret.recommendedInstallLocation = PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
- } else if (loc == ERR_LOC) {
- Log.i(TAG, "Failed to install insufficient storage");
- ret.recommendedInstallLocation = PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
- } else {
- // Implies install on internal storage.
- ret.recommendedInstallLocation = PackageHelper.RECOMMEND_INSTALL_INTERNAL;
- }
+ ret.recommendedInstallLocation = recommendAppInstallLocation(pkg.installLocation, archiveFilePath);
return ret;
}
+
+ public boolean checkFreeStorage(boolean external, Uri fileUri) {
+ return checkFreeStorageInner(external, fileUri);
+ }
};
public DefaultContainerService() {
@@ -190,6 +183,12 @@ public class DefaultContainerService extends IntentService {
}
private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName) {
+ // Make sure the sdcard is mounted.
+ String status = Environment.getExternalStorageState();
+ if (!status.equals(Environment.MEDIA_MOUNTED)) {
+ Log.w(TAG, "Make sure sdcard is mounted.");
+ return null;
+ }
// Create new container at newCachePath
String codePath = packageURI.getPath();
File codeFile = new File(codePath);
@@ -313,11 +312,13 @@ public class DefaultContainerService extends IntentService {
// Else install on internal NAND flash, unless space on NAND is less than 10%
String status = Environment.getExternalStorageState();
long availSDSize = -1;
+ boolean mediaAvailable = false;
if (status.equals(Environment.MEDIA_MOUNTED)) {
StatFs sdStats = new StatFs(
Environment.getExternalStorageDirectory().getPath());
availSDSize = (long)sdStats.getAvailableBlocks() *
(long)sdStats.getBlockSize();
+ mediaAvailable = true;
}
StatFs internalStats = new StatFs(Environment.getDataDirectory().getPath());
long totalInternalSize = (long)internalStats.getBlockCount() *
@@ -337,7 +338,8 @@ public class DefaultContainerService extends IntentService {
long reqInternalSize = 0;
boolean intThresholdOk = (pctNandFree >= LOW_NAND_FLASH_TRESHOLD);
boolean intAvailOk = ((reqInstallSize + reqInternalSize) < availInternalSize);
- boolean fitsOnSd = (reqInstallSize < availSDSize) && intThresholdOk &&
+ boolean fitsOnSd = mediaAvailable && (reqInstallSize < availSDSize)
+ && intThresholdOk &&
(reqInternalSize < availInternalSize);
boolean fitsOnInt = intThresholdOk && intAvailOk;
@@ -377,21 +379,58 @@ public class DefaultContainerService extends IntentService {
}
if (!auto) {
if (installOnlyOnSd) {
- return fitsOnSd ? PackageManager.INSTALL_EXTERNAL : ERR_LOC;
+ if (fitsOnSd) {
+ return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
+ }
+ if (!mediaAvailable) {
+ return PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE;
+ }
+ return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
} else if (installOnlyInternal){
// Check on internal flash
- return fitsOnInt ? 0 : ERR_LOC;
+ return fitsOnInt ? PackageHelper.RECOMMEND_INSTALL_INTERNAL :
+ PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
}
}
// Try to install internally
if (fitsOnInt) {
- return 0;
+ return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
}
// Try the sdcard now.
if (fitsOnSd) {
- return PackageManager.INSTALL_EXTERNAL;
+ return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
}
// Return error code
- return ERR_LOC;
+ return PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE;
+ }
+
+ private boolean checkFreeStorageInner(boolean external, Uri packageURI) {
+ File apkFile = new File(packageURI.getPath());
+ long size = apkFile.length();
+ if (external) {
+ String status = Environment.getExternalStorageState();
+ long availSDSize = -1;
+ if (status.equals(Environment.MEDIA_MOUNTED)) {
+ StatFs sdStats = new StatFs(
+ Environment.getExternalStorageDirectory().getPath());
+ availSDSize = (long)sdStats.getAvailableBlocks() *
+ (long)sdStats.getBlockSize();
+ }
+ return availSDSize > size;
+ }
+ StatFs internalStats = new StatFs(Environment.getDataDirectory().getPath());
+ long totalInternalSize = (long)internalStats.getBlockCount() *
+ (long)internalStats.getBlockSize();
+ long availInternalSize = (long)internalStats.getAvailableBlocks() *
+ (long)internalStats.getBlockSize();
+
+ double pctNandFree = (double)availInternalSize / (double)totalInternalSize;
+ // To make final copy
+ long reqInstallSize = size;
+ // For dex files. Just ignore and fail when extracting. Max limit of 2Gig for now.
+ long reqInternalSize = 0;
+ boolean intThresholdOk = (pctNandFree >= LOW_NAND_FLASH_TRESHOLD);
+ boolean intAvailOk = ((reqInstallSize + reqInternalSize) < availInternalSize);
+ return intThresholdOk && intAvailOk;
}
}
diff --git a/services/java/com/android/server/MountService.java b/services/java/com/android/server/MountService.java
index b8b94a1..d50f591 100644
--- a/services/java/com/android/server/MountService.java
+++ b/services/java/com/android/server/MountService.java
@@ -51,6 +51,8 @@ import java.util.HashSet;
class MountService extends IMountService.Stub
implements INativeDaemonConnectorCallbacks {
private static final boolean LOCAL_LOGD = false;
+ private static final boolean DEBUG_UNMOUNT = false;
+ private static final boolean DEBUG_EVENTS = false;
private static final String TAG = "MountService";
@@ -156,6 +158,7 @@ class MountService extends IMountService.Stub
}
void handleFinished() {
+ if (DEBUG_UNMOUNT) Log.i(TAG, "Unmounting " + path);
doUnmountVolume(path, true);
}
}
@@ -205,22 +208,27 @@ class MountService extends IMountService.Stub
void registerReceiver() {
mRegistered = true;
+ if (DEBUG_UNMOUNT) Log.i(TAG, "Registering receiver");
mContext.registerReceiver(mPmReceiver, mPmFilter);
}
void unregisterReceiver() {
mRegistered = false;
+ if (DEBUG_UNMOUNT) Log.i(TAG, "Unregistering receiver");
mContext.unregisterReceiver(mPmReceiver);
}
public void handleMessage(Message msg) {
switch (msg.what) {
case H_UNMOUNT_PM_UPDATE: {
+ if (DEBUG_UNMOUNT) Log.i(TAG, "H_UNMOUNT_PM_UPDATE");
UnmountCallBack ucb = (UnmountCallBack) msg.obj;
mForceUnmounts.add(ucb);
+ if (DEBUG_UNMOUNT) Log.i(TAG, " registered = " + mRegistered);
// Register only if needed.
if (!mRegistered) {
registerReceiver();
+ if (DEBUG_UNMOUNT) Log.i(TAG, "Updating external media status");
boolean hasExtPkgs = mPms.updateExternalMediaStatus(false);
if (!hasExtPkgs) {
// Unregister right away
@@ -230,6 +238,7 @@ class MountService extends IMountService.Stub
break;
}
case H_UNMOUNT_PM_DONE: {
+ if (DEBUG_UNMOUNT) Log.i(TAG, "H_UNMOUNT_PM_DONE");
// Unregister now.
if (mRegistered) {
unregisterReceiver();
@@ -286,6 +295,7 @@ class MountService extends IMountService.Stub
break;
}
case H_UNMOUNT_MS : {
+ if (DEBUG_UNMOUNT) Log.i(TAG, "H_UNMOUNT_MS");
UnmountCallBack ucb = (UnmountCallBack) msg.obj;
ucb.handleFinished();
break;
@@ -393,7 +403,12 @@ class MountService extends IMountService.Stub
Log.w(TAG, String.format("Duplicate state transition (%s -> %s)", mLegacyState, state));
return;
}
-
+ // Update state on PackageManager
+ if (Environment.MEDIA_UNMOUNTED.equals(state)) {
+ mPms.updateExternalMediaStatus(false);
+ } else if (Environment.MEDIA_MOUNTED.equals(state)) {
+ mPms.updateExternalMediaStatus(true);
+ }
String oldState = mLegacyState;
mLegacyState = state;
@@ -456,6 +471,7 @@ class MountService extends IMountService.Stub
}
}
if (state != null) {
+ if (DEBUG_EVENTS) Log.i(TAG, "Updating valid state " + state);
updatePublicVolumeState(path, state);
}
} catch (Exception e) {
@@ -484,6 +500,18 @@ class MountService extends IMountService.Stub
public boolean onEvent(int code, String raw, String[] cooked) {
Intent in = null;
+ if (DEBUG_EVENTS) {
+ StringBuilder builder = new StringBuilder();
+ builder.append("onEvent::");
+ builder.append(" raw= " + raw);
+ if (cooked != null) {
+ builder.append(" cooked = " );
+ for (String str : cooked) {
+ builder.append(" " + str);
+ }
+ }
+ Log.i(TAG, builder.toString());
+ }
if (code == VoldResponseCode.VolumeStateChange) {
/*
* One of the volumes we're managing has changed state.
@@ -541,18 +569,22 @@ class MountService extends IMountService.Stub
return true;
}
/* Send the media unmounted event first */
+ if (DEBUG_EVENTS) Log.i(TAG, "Sending unmounted event first");
updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
mContext.sendBroadcast(in);
+ if (DEBUG_EVENTS) Log.i(TAG, "Sending media removed");
updatePublicVolumeState(path, Environment.MEDIA_REMOVED);
in = new Intent(Intent.ACTION_MEDIA_REMOVED, Uri.parse("file://" + path));
} else if (code == VoldResponseCode.VolumeBadRemoval) {
+ if (DEBUG_EVENTS) Log.i(TAG, "Sending unmounted event first");
/* Send the media unmounted event first */
updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
mContext.sendBroadcast(in);
+ if (DEBUG_EVENTS) Log.i(TAG, "Sending media bad removal");
updatePublicVolumeState(path, Environment.MEDIA_BAD_REMOVAL);
in = new Intent(Intent.ACTION_MEDIA_BAD_REMOVAL, Uri.parse("file://" + path));
} else {
@@ -570,6 +602,7 @@ class MountService extends IMountService.Stub
private void notifyVolumeStateChange(String label, String path, int oldState, int newState) {
String vs = getVolumeState(path);
+ if (DEBUG_EVENTS) Log.i(TAG, "notifyVolumeStateChanged::" + vs);
Intent in = null;
@@ -591,29 +624,31 @@ class MountService extends IMountService.Stub
Environment.MEDIA_BAD_REMOVAL) && !vs.equals(
Environment.MEDIA_NOFS) && !vs.equals(
Environment.MEDIA_UNMOUNTABLE) && !getUmsEnabling()) {
+ if (DEBUG_EVENTS) Log.i(TAG, "updating volume state for media bad removal nofs and unmountable");
updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
}
} else if (newState == VolumeState.Pending) {
} else if (newState == VolumeState.Checking) {
+ if (DEBUG_EVENTS) Log.i(TAG, "updating volume state checking");
updatePublicVolumeState(path, Environment.MEDIA_CHECKING);
in = new Intent(Intent.ACTION_MEDIA_CHECKING, Uri.parse("file://" + path));
} else if (newState == VolumeState.Mounted) {
+ if (DEBUG_EVENTS) Log.i(TAG, "updating volume state mounted");
updatePublicVolumeState(path, Environment.MEDIA_MOUNTED);
- // Update media status on PackageManagerService to mount packages on sdcard
- mPms.updateExternalMediaStatus(true);
in = new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + path));
in.putExtra("read-only", false);
} else if (newState == VolumeState.Unmounting) {
- mPms.updateExternalMediaStatus(false);
in = new Intent(Intent.ACTION_MEDIA_EJECT, Uri.parse("file://" + path));
} else if (newState == VolumeState.Formatting) {
} else if (newState == VolumeState.Shared) {
+ if (DEBUG_EVENTS) Log.i(TAG, "Updating volume state media mounted");
/* Send the media unmounted event first */
updatePublicVolumeState(path, Environment.MEDIA_UNMOUNTED);
in = new Intent(Intent.ACTION_MEDIA_UNMOUNTED, Uri.parse("file://" + path));
mContext.sendBroadcast(in);
+ if (DEBUG_EVENTS) Log.i(TAG, "Updating media shared");
updatePublicVolumeState(path, Environment.MEDIA_SHARED);
in = new Intent(Intent.ACTION_MEDIA_SHARED, Uri.parse("file://" + path));
if (LOCAL_LOGD) Log.d(TAG, "Sending ACTION_MEDIA_SHARED intent");
@@ -657,6 +692,7 @@ class MountService extends IMountService.Stub
private int doMountVolume(String path) {
int rc = StorageResultCode.OperationSucceeded;
+ if (DEBUG_EVENTS) Log.i(TAG, "doMountVolume: Mouting " + path);
try {
mConnector.doCommand(String.format("volume mount %s", path));
} catch (NativeDaemonConnectorException e) {
@@ -671,6 +707,7 @@ class MountService extends IMountService.Stub
*/
rc = StorageResultCode.OperationFailedNoMedia;
} else if (code == VoldResponseCode.OpFailedMediaBlank) {
+ if (DEBUG_EVENTS) Log.i(TAG, " updating volume state :: media nofs");
/*
* Media is blank or does not contain a supported filesystem
*/
@@ -678,6 +715,7 @@ class MountService extends IMountService.Stub
in = new Intent(Intent.ACTION_MEDIA_NOFS, Uri.parse("file://" + path));
rc = StorageResultCode.OperationFailedMediaBlank;
} else if (code == VoldResponseCode.OpFailedMediaCorrupt) {
+ if (DEBUG_EVENTS) Log.i(TAG, "updating volume state media corrupt");
/*
* Volume consistency check failed
*/
@@ -1040,6 +1078,16 @@ class MountService extends IMountService.Stub
validatePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS);
waitForReady();
+ String volState = getVolumeState(path);
+ if (DEBUG_UNMOUNT) Log.i(TAG, "Unmounting " + path + " force = " + force);
+ if (Environment.MEDIA_UNMOUNTED.equals(volState) ||
+ Environment.MEDIA_REMOVED.equals(volState) ||
+ Environment.MEDIA_SHARED.equals(volState) ||
+ Environment.MEDIA_UNMOUNTABLE.equals(volState)) {
+ // Media already unmounted or cannot be unmounted.
+ // TODO return valid return code when adding observer call back.
+ return;
+ }
UnmountCallBack ucb = new UnmountCallBack(path, force);
mHandler.sendMessage(mHandler.obtainMessage(H_UNMOUNT_PM_UPDATE, ucb));
}
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index aa9ced8..b114ca2 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -26,10 +26,13 @@ import android.content.pm.PackageManager;
import android.net.Uri;
import android.net.InterfaceConfiguration;
import android.net.INetworkManagementEventObserver;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.os.INetworkManagementService;
import android.os.Handler;
import android.os.SystemProperties;
import android.text.TextUtils;
+import android.util.Log;
import android.util.Slog;
import java.util.ArrayList;
import java.util.StringTokenizer;
@@ -457,14 +460,38 @@ class NetworkManagementService extends INetworkManagementService.Stub {
throw new IllegalStateException("Got an empty response");
}
- public void startAccessPoint()
+ public void startAccessPoint(WifiConfiguration wifiConfig, String intf)
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"));
+ mConnector.doCommand(String.format("softap stop " + intf));
+ mConnector.doCommand(String.format("softap fwreload " + intf + " AP"));
+ mConnector.doCommand(String.format("softap start " + intf));
+ if (wifiConfig == null) {
+ mConnector.doCommand(String.format("softap set " + intf + " wl0.1"));
+ } else {
+ /**
+ * softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8]
+ * argv1 - wlan interface
+ * argv2 - softap interface
+ * argv3 - SSID
+ * argv4 - Security
+ * argv5 - Key
+ * argv6 - Channel
+ * argv7 - Preamble
+ * argv8 - Max SCB
+ *
+ * TODO: get a configurable softap interface from driver
+ */
+ String str = String.format("softap set " + intf + " wl0.1 %s %s %s", wifiConfig.SSID,
+ wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?
+ "wpa2-psk" : "open",
+ wifiConfig.preSharedKey);
+ mConnector.doCommand(str);
+ }
+ mConnector.doCommand(String.format("softap startap"));
}
public void stopAccessPoint() throws IllegalStateException {
@@ -472,7 +499,7 @@ class NetworkManagementService extends INetworkManagementService.Stub {
android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
- mConnector.doCommand("softap stop");
+ mConnector.doCommand("softap stopap");
}
}
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 139c05f..818e99e 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -4613,6 +4613,12 @@ class PackageManagerService extends IPackageManager.Stub {
return pkgLite.recommendedInstallLocation;
}
+ /*
+ * Invoke remote method to get package information and install
+ * location values. Override install location based on default
+ * policy if needed and then create install arguments based
+ * on the install location.
+ */
public void handleStartCopy() throws RemoteException {
int ret = PackageManager.INSTALL_SUCCEEDED;
boolean fwdLocked = (flags & PackageManager.INSTALL_FORWARD_LOCK) != 0;
@@ -4624,9 +4630,7 @@ class PackageManagerService extends IPackageManager.Stub {
} else {
// Remote call to find out default install location
PackageInfoLite pkgLite = mContainerService.getMinimalPackageInfo(packageURI);
- int loc = installLocationPolicy(pkgLite, flags);
- // Use install location to create InstallArgs and temporary
- // install location
+ int loc = pkgLite.recommendedInstallLocation;
if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_LOCATION){
ret = PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
} else if (loc == PackageHelper.RECOMMEND_FAILED_ALREADY_EXISTS){
@@ -4635,7 +4639,11 @@ class PackageManagerService extends IPackageManager.Stub {
ret = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
} else if (loc == PackageHelper.RECOMMEND_FAILED_INVALID_APK) {
ret = PackageManager.INSTALL_FAILED_INVALID_APK;
+ } else if (loc == PackageHelper.RECOMMEND_MEDIA_UNAVAILABLE) {
+ ret = PackageManager.INSTALL_FAILED_MEDIA_UNAVAILABLE;
} else {
+ // Override with defaults if needed.
+ loc = installLocationPolicy(pkgLite, flags);
// Override install location with flags
if ((flags & PackageManager.INSTALL_EXTERNAL) == 0){
if (loc == PackageHelper.RECOMMEND_INSTALL_EXTERNAL) {
@@ -4701,6 +4709,12 @@ class PackageManagerService extends IPackageManager.Stub {
}
public void handleStartCopy() throws RemoteException {
+ mRet = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;
+ // Check for storage space on target medium
+ if (!targetArgs.checkFreeStorage(mContainerService)) {
+ Log.w(TAG, "Insufficient storage to install");
+ return;
+ }
// Create the file args now.
mRet = targetArgs.copyApk(mContainerService, false);
targetArgs.doPreInstall(mRet);
@@ -4714,15 +4728,20 @@ class PackageManagerService extends IPackageManager.Stub {
builder.append(" target : ");
builder.append(targetArgs.getCodePath());
}
- Log.i(TAG, "Posting move MCS_UNBIND for " + builder.toString());
+ Log.i(TAG, builder.toString());
}
}
@Override
void handleReturnCode() {
targetArgs.doPostInstall(mRet);
- // TODO invoke pending move
- processPendingMove(this, mRet);
+ int currentStatus = PackageManager.MOVE_FAILED_INTERNAL_ERROR;
+ if (mRet == PackageManager.INSTALL_SUCCEEDED) {
+ currentStatus = PackageManager.MOVE_SUCCEEDED;
+ } else if (mRet == PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE){
+ currentStatus = PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE;
+ }
+ processPendingMove(this, currentStatus);
}
@Override
@@ -4782,6 +4801,7 @@ class PackageManagerService extends IPackageManager.Stub {
// Need installer lock especially for dex file removal.
abstract void cleanUpResourcesLI();
abstract boolean doPostDeleteLI(boolean delete);
+ abstract boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException;
}
class FileInstallArgs extends InstallArgs {
@@ -4812,6 +4832,10 @@ class PackageManagerService extends IPackageManager.Stub {
resourceFileName = getResourcePathFromCodePath();
}
+ boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
+ return imcs.checkFreeStorage(false, packageURI);
+ }
+
String getCodePath() {
return codeFileName;
}
@@ -5013,6 +5037,10 @@ class PackageManagerService extends IPackageManager.Stub {
cid = getTempContainerId();
}
+ boolean checkFreeStorage(IMediaContainerService imcs) throws RemoteException {
+ return imcs.checkFreeStorage(true, packageURI);
+ }
+
int copyApk(IMediaContainerService imcs, boolean temp) throws RemoteException {
if (temp) {
createCopyFile();
@@ -9109,6 +9137,9 @@ class PackageManagerService extends IPackageManager.Stub {
public boolean updateExternalMediaStatus(final boolean mediaStatus) {
final boolean ret;
synchronized (mPackages) {
+ Log.i(TAG, "Updating external media status from " +
+ (mMediaMounted ? "mounted" : "unmounted") + " to " +
+ (mediaStatus ? "mounted" : "unmounted"));
if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus:: mediaStatus=" +
mediaStatus+", mMediaMounted=" + mMediaMounted);
if (mediaStatus == mMediaMounted) {
@@ -9117,6 +9148,14 @@ class PackageManagerService extends IPackageManager.Stub {
mMediaMounted = mediaStatus;
Set<String> appList = mSettings.findPackagesWithFlag(ApplicationInfo.FLAG_EXTERNAL_STORAGE);
ret = appList != null && appList.size() > 0;
+ if (DEBUG_SD_INSTALL) {
+ if (appList != null) {
+ for (String app : appList) {
+ Log.i(TAG, "Should enable " + app + " on sdcard");
+ }
+ }
+ }
+ if (DEBUG_SD_INSTALL) Log.i(TAG, "updateExternalMediaStatus returning " + ret);
}
// Queue up an async operation since the package installation may take a little while.
mHandler.post(new Runnable() {
@@ -9134,6 +9173,7 @@ class PackageManagerService extends IPackageManager.Stub {
// enabled or disabled.
final String list[] = PackageHelper.getSecureContainerList();
if (list == null || list.length == 0) {
+ Log.i(TAG, "No secure containers on sdcard");
return;
}
@@ -9141,16 +9181,6 @@ class PackageManagerService extends IPackageManager.Stub {
int num = 0;
HashSet<String> removeCids = new HashSet<String>();
HashMap<SdInstallArgs, String> processCids = new HashMap<SdInstallArgs, String>();
- /*HashMap<String, String> cidPathMap = new HashMap<String, String>();
- // Don't hold any locks when getting cache paths
- for (String cid : list) {
- String cpath = PackageHelper.getSdDir(cid);
- if (cpath == null) {
- removeCids.add(cid);
- } else {
- cidPathMap.put(cid, cpath);
- }
- }*/
synchronized (mPackages) {
for (String cid : list) {
SdInstallArgs args = new SdInstallArgs(cid);
diff --git a/services/java/com/android/server/UiModeManagerService.java b/services/java/com/android/server/UiModeManagerService.java
index 37a3cdf..5bd23f4 100644
--- a/services/java/com/android/server/UiModeManagerService.java
+++ b/services/java/com/android/server/UiModeManagerService.java
@@ -20,7 +20,6 @@ import android.app.Activity;
import android.app.ActivityManagerNative;
import android.app.AlarmManager;
import android.app.IActivityManager;
-import android.app.KeyguardManager;
import android.app.IUiModeManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -103,7 +102,6 @@ class UiModeManagerService extends IUiModeManager.Stub {
private LocationManager mLocationManager;
private Location mLocation;
private StatusBarManager mStatusBarManager;
- private KeyguardManager.KeyguardLock mKeyguardLock;
private final PowerManager.WakeLock mWakeLock;
// The broadcast receiver which receives the result of the ordered broadcast sent when
@@ -347,24 +345,6 @@ class UiModeManagerService extends IUiModeManager.Stub {
void setCarModeLocked(boolean enabled) {
if (mCarModeEnabled != enabled) {
mCarModeEnabled = enabled;
-
- // Disable keyguard when in car mode
- if (mKeyguardLock == null) {
- KeyguardManager km =
- (KeyguardManager)mContext.getSystemService(Context.KEYGUARD_SERVICE);
- if (km != null) {
- mKeyguardLock = km.newKeyguardLock(TAG);
- }
- }
- if (mKeyguardLock != null) {
- long ident = Binder.clearCallingIdentity();
- if (enabled) {
- mKeyguardLock.disableKeyguard();
- } else {
- mKeyguardLock.reenableKeyguard();
- }
- Binder.restoreCallingIdentity(ident);
- }
}
}
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 599eec5..4eb529c 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -46,6 +46,7 @@ import android.net.wifi.WifiStateTracker;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.SupplicantState;
+import android.net.wifi.WifiConfiguration.KeyMgmt;
import android.net.ConnectivityManager;
import android.net.InterfaceConfiguration;
import android.net.NetworkStateTracker;
@@ -81,6 +82,7 @@ import java.net.UnknownHostException;
import com.android.internal.app.IBatteryStats;
import android.app.backup.IBackupManager;
import com.android.server.am.BatteryStatsService;
+import com.android.internal.R;
/**
* WifiService handles remote WiFi operation requests by implementing
@@ -105,6 +107,8 @@ public class WifiService extends IWifiManager.Stub {
private boolean mDeviceIdle;
private int mPluggedType;
+ private enum DriverAction {DRIVER_UNLOAD, NO_DRIVER_UNLOAD};
+
// true if the user enabled Wifi while in airplane mode
private boolean mAirplaneModeOverwridden;
@@ -271,11 +275,9 @@ public class WifiService extends IWifiManager.Stub {
*/
public void startWifi() {
boolean wifiEnabled = getPersistedWifiEnabled();
- boolean wifiAPEnabled = wifiEnabled ? false : getPersistedWifiApEnabled();
Slog.i(TAG, "WifiService starting up with Wi-Fi " +
(wifiEnabled ? "enabled" : "disabled"));
setWifiEnabledBlocking(wifiEnabled, false, Process.myUid());
- setWifiApEnabledBlocking(wifiAPEnabled, true, Process.myUid(), null);
}
private void updateTetherState(ArrayList<String> available, ArrayList<String> tethered) {
@@ -297,28 +299,22 @@ public class WifiService extends IWifiManager.Stub {
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;
+ /* IP/netmask: 169.254.2.2/255.255.255.0 */
+ ifcg.ipAddr = (169 << 24) + (254 << 16) + (2 << 8) + 2;
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);
+ setWifiApEnabledState(WIFI_AP_STATE_FAILED, 0, DriverAction.DRIVER_UNLOAD);
return;
}
- /**
- * TODO: Add broadcast to indicate tether failed
- */
- if(mCm.tether(intf) == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
- Slog.d(TAG, "Tethered "+intf);
- } else {
+ if(mCm.tether(intf) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Slog.e(TAG, "Error tethering "+intf);
+ setWifiApEnabledState(WIFI_AP_STATE_FAILED, 0, DriverAction.DRIVER_UNLOAD);
}
break;
}
@@ -434,7 +430,7 @@ public class WifiService extends IWifiManager.Stub {
setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid);
if ((mWifiApState == WIFI_AP_STATE_ENABLED) && enable) {
- setWifiApEnabledBlocking(false, true, Process.myUid(), null);
+ setWifiApEnabledBlocking(false, Process.myUid(), null);
}
if (enable) {
@@ -581,21 +577,6 @@ public class WifiService extends IWifiManager.Stub {
return mWifiStateTracker.reassociate();
}
- 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
@@ -621,46 +602,101 @@ public class WifiService extends IWifiManager.Stub {
return true;
}
+ public WifiConfiguration getWifiApConfiguration() {
+ final ContentResolver cr = mContext.getContentResolver();
+ WifiConfiguration wifiConfig = new WifiConfiguration();
+ int authType;
+ try {
+ wifiConfig.SSID = Settings.Secure.getString(cr, Settings.Secure.WIFI_AP_SSID);
+ if (wifiConfig.SSID == null)
+ return null;
+ authType = Settings.Secure.getInt(cr, Settings.Secure.WIFI_AP_SECURITY);
+ wifiConfig.allowedKeyManagement.set(authType);
+ wifiConfig.preSharedKey = Settings.Secure.getString(cr, Settings.Secure.WIFI_AP_PASSWD);
+ return wifiConfig;
+ } catch (Settings.SettingNotFoundException e) {
+ Slog.e(TAG,"AP settings not found, returning");
+ return null;
+ }
+ }
+
+ private void persistApConfiguration(WifiConfiguration wifiConfig) {
+ final ContentResolver cr = mContext.getContentResolver();
+ boolean isWpa;
+ if (wifiConfig == null)
+ return;
+ Settings.Secure.putString(cr, Settings.Secure.WIFI_AP_SSID, wifiConfig.SSID);
+ isWpa = wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK);
+ Settings.Secure.putInt(cr,
+ Settings.Secure.WIFI_AP_SECURITY,
+ isWpa ? KeyMgmt.WPA_PSK : KeyMgmt.NONE);
+ if (isWpa)
+ Settings.Secure.putString(cr, Settings.Secure.WIFI_AP_PASSWD, wifiConfig.preSharedKey);
+ }
+
/**
* 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
+ * @param wifiConfig 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) {
+ int uid, WifiConfiguration wifiConfig) {
final int eventualWifiApState = enable ? WIFI_AP_STATE_ENABLED : WIFI_AP_STATE_DISABLED;
if (mWifiApState == eventualWifiApState) {
- return true;
+ /* Configuration changed on a running access point */
+ if(enable && (wifiConfig != null)) {
+ try {
+ persistApConfiguration(wifiConfig);
+ nwService.stopAccessPoint();
+ nwService.startAccessPoint(wifiConfig, mWifiStateTracker.getInterfaceName());
+ return true;
+ } catch(Exception e) {
+ Slog.e(TAG, "Exception in nwService during AP restart");
+ setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid, DriverAction.DRIVER_UNLOAD);
+ return false;
+ }
+ } else {
+ return true;
+ }
}
- setWifiApEnabledState(enable ? WIFI_AP_STATE_ENABLING : WIFI_AP_STATE_DISABLING, uid);
-
- if (enable && (mWifiStateTracker.getWifiState() == WIFI_STATE_ENABLED)) {
- setWifiEnabledBlocking(false, true, Process.myUid());
- }
+ setWifiApEnabledState(enable ? WIFI_AP_STATE_ENABLING :
+ WIFI_AP_STATE_DISABLING, uid, DriverAction.NO_DRIVER_UNLOAD);
if (enable) {
+
+ /**
+ * Disable client mode for starting AP
+ */
+ if (mWifiStateTracker.getWifiState() == WIFI_STATE_ENABLED) {
+ setWifiEnabledBlocking(false, true, Process.myUid());
+ }
+
+ /* Use default config if there is no existing config */
+ if (wifiConfig == null && ((wifiConfig = getWifiApConfiguration()) == null)) {
+ wifiConfig = new WifiConfiguration();
+ wifiConfig.SSID = mContext.getString(R.string.wifi_tether_configure_ssid_default);
+ wifiConfig.allowedKeyManagement.set(KeyMgmt.NONE);
+ }
+ persistApConfiguration(wifiConfig);
+
if (!mWifiStateTracker.loadDriver()) {
Slog.e(TAG, "Failed to load Wi-Fi driver for AP mode");
- setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid);
+ setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid, DriverAction.NO_DRIVER_UNLOAD);
return false;
}
try {
- nwService.startAccessPoint();
+ nwService.startAccessPoint(wifiConfig, mWifiStateTracker.getInterfaceName());
} catch(Exception e) {
Slog.e(TAG, "Exception in startAccessPoint()");
+ setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid, DriverAction.DRIVER_UNLOAD);
+ return false;
}
} else {
@@ -669,20 +705,18 @@ public class WifiService extends IWifiManager.Stub {
nwService.stopAccessPoint();
} catch(Exception e) {
Slog.e(TAG, "Exception in stopAccessPoint()");
+ setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid, DriverAction.DRIVER_UNLOAD);
+ return false;
}
if (!mWifiStateTracker.unloadDriver()) {
Slog.e(TAG, "Failed to unload Wi-Fi driver for AP mode");
- setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid);
+ setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid, DriverAction.NO_DRIVER_UNLOAD);
return false;
}
}
- // Success!
- if (persist) {
- persistWifiApEnabled(enable);
- }
- setWifiApEnabledState(eventualWifiApState, uid);
+ setWifiApEnabledState(eventualWifiApState, uid, DriverAction.NO_DRIVER_UNLOAD);
return true;
}
@@ -699,9 +733,16 @@ public class WifiService extends IWifiManager.Stub {
return mWifiApState;
}
- private void setWifiApEnabledState(int wifiAPState, int uid) {
+ private void setWifiApEnabledState(int wifiAPState, int uid, DriverAction flag) {
final int previousWifiApState = mWifiApState;
+ /**
+ * Unload the driver if going to a failed state
+ */
+ if ((mWifiApState == WIFI_AP_STATE_FAILED) && (flag == DriverAction.DRIVER_UNLOAD)) {
+ mWifiStateTracker.unloadDriver();
+ }
+
long ident = Binder.clearCallingIdentity();
try {
if (wifiAPState == WIFI_AP_STATE_ENABLED) {
@@ -1694,7 +1735,7 @@ public class WifiService extends IWifiManager.Stub {
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();
+ uid, 0, wifiConfig).sendToTarget();
}
private void updateWifiState() {
@@ -1841,15 +1882,13 @@ public class WifiService extends IWifiManager.Stub {
case MESSAGE_START_ACCESS_POINT:
setWifiApEnabledBlocking(true,
- msg.arg1 == 1,
- msg.arg2,
+ msg.arg1,
(WifiConfiguration) msg.obj);
break;
case MESSAGE_STOP_ACCESS_POINT:
setWifiApEnabledBlocking(false,
- msg.arg1 == 1,
- msg.arg2,
+ msg.arg1,
(WifiConfiguration) msg.obj);
sWakeLock.release();
break;
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index d5f2c1d..e43b12e 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -1502,7 +1502,7 @@ public class StatusBarService extends IStatusBar.Stub
Drawable bg;
/// ---------- Tracking View --------------
- pixelFormat = PixelFormat.TRANSLUCENT;
+ pixelFormat = PixelFormat.RGBX_8888;
bg = mTrackingView.getBackground();
if (bg != null) {
pixelFormat = bg.getOpacity();
diff --git a/services/java/com/android/server/status/UsbStorageActivity.java b/services/java/com/android/server/status/UsbStorageActivity.java
index c1c8c22..b3ee257 100644
--- a/services/java/com/android/server/status/UsbStorageActivity.java
+++ b/services/java/com/android/server/status/UsbStorageActivity.java
@@ -28,6 +28,7 @@ import android.content.IntentFilter;
import android.content.DialogInterface.OnCancelListener;
import android.os.Bundle;
import android.os.Environment;
+import android.os.Handler;
import android.os.IBinder;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
@@ -36,8 +37,10 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.widget.ImageView;
import android.widget.Button;
+import android.widget.ProgressBar;
import android.widget.TextView;
import android.view.View;
+import android.view.Window;
import android.util.Log;
/**
@@ -48,8 +51,10 @@ import android.util.Log;
public class UsbStorageActivity extends Activity
implements View.OnClickListener, OnCancelListener {
private static final String TAG = "UsbStorageActivity";
+
private Button mMountButton;
private Button mUnmountButton;
+ private ProgressBar mProgressBar;
private TextView mBanner;
private TextView mMessage;
private ImageView mIcon;
@@ -71,11 +76,8 @@ public class UsbStorageActivity extends Activity
private StorageEventListener mStorageListener = new StorageEventListener() {
@Override
public void onStorageStateChanged(String path, String oldState, String newState) {
- if (newState.equals(Environment.MEDIA_SHARED)) {
- switchDisplay(true);
- } else {
- switchDisplay(false);
- }
+ final boolean on = newState.equals(Environment.MEDIA_SHARED);
+ switchDisplay(on);
}
};
@@ -90,6 +92,9 @@ public class UsbStorageActivity extends Activity
}
}
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setProgressBarIndeterminateVisibility(true);
+
setTitle(getString(com.android.internal.R.string.usb_storage_activity_title));
setContentView(com.android.internal.R.layout.usb_storage_activity);
@@ -102,16 +107,19 @@ public class UsbStorageActivity extends Activity
mMountButton.setOnClickListener(this);
mUnmountButton = (Button) findViewById(com.android.internal.R.id.unmount_button);
mUnmountButton.setOnClickListener(this);
+ mProgressBar = (ProgressBar) findViewById(com.android.internal.R.id.progress);
}
private void switchDisplay(boolean usbStorageInUse) {
if (usbStorageInUse) {
+ mProgressBar.setVisibility(View.GONE);
mUnmountButton.setVisibility(View.VISIBLE);
mMountButton.setVisibility(View.GONE);
mIcon.setImageResource(com.android.internal.R.drawable.usb_android_connected);
mBanner.setText(com.android.internal.R.string.usb_storage_stop_title);
mMessage.setText(com.android.internal.R.string.usb_storage_stop_message);
} else {
+ mProgressBar.setVisibility(View.GONE);
mUnmountButton.setVisibility(View.GONE);
mMountButton.setVisibility(View.VISIBLE);
mIcon.setImageResource(com.android.internal.R.drawable.usb_android);
@@ -189,6 +197,25 @@ public class UsbStorageActivity extends Activity
showDialog(id);
}
+ private void switchUsbMassStorageAsync(boolean on) {
+ mUnmountButton.setVisibility(View.GONE);
+ mMountButton.setVisibility(View.GONE);
+
+ mProgressBar.setVisibility(View.VISIBLE);
+ // will be hidden once USB mass storage kicks in (or fails)
+
+ final boolean _on = on;
+ new Thread() {
+ public void run() {
+ if (_on) {
+ mStorageManager.enableUsbMassStorage();
+ } else {
+ mStorageManager.disableUsbMassStorage();
+ }
+ }
+ }.start();
+ }
+
private void checkStorageUsers() {
IMountService ims = getMountService();
if (ims == null) {
@@ -208,18 +235,17 @@ public class UsbStorageActivity extends Activity
showDialogInner(DLG_CONFIRM_KILL_STORAGE_USERS);
} else {
if (localLOGV) Log.i(TAG, "Enabling UMS");
- mStorageManager.enableUsbMassStorage();
+ switchUsbMassStorageAsync(true);
}
}
public void onClick(View v) {
- Log.i(TAG, "Clicked button");
if (v == mMountButton) {
// Check for list of storage users and display dialog if needed.
checkStorageUsers();
} else if (v == mUnmountButton) {
if (localLOGV) Log.i(TAG, "Disabling UMS");
- mStorageManager.disableUsbMassStorage();
+ switchUsbMassStorageAsync(false);
}
}
diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
index 8c8b00c..a06a13b 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
@@ -72,8 +72,8 @@ import android.provider.Settings.SettingNotFoundException;
public class PackageManagerTests extends AndroidTestCase {
private static final boolean localLOGV = true;
public static final String TAG="PackageManagerTests";
- public final long MAX_WAIT_TIME=120*1000;
- public final long WAIT_TIME_INCR=20*1000;
+ public final long MAX_WAIT_TIME = 25*1000;
+ public final long WAIT_TIME_INCR = 5*1000;
private static final String SECURE_CONTAINERS_PREFIX = "/mnt/asec";
private static final int APP_INSTALL_AUTO = PackageHelper.APP_INSTALL_AUTO;
private static final int APP_INSTALL_DEVICE = PackageHelper.APP_INSTALL_INTERNAL;
@@ -378,39 +378,50 @@ public class PackageManagerTests extends AndroidTestCase {
private InstallParams installFromRawResource(String outFileName,
int rawResId, int flags, boolean cleanUp, boolean fail, int result,
int expInstallLocation) {
+ PackageManager pm = mContext.getPackageManager();
File filesDir = mContext.getFilesDir();
File outFile = new File(filesDir, outFileName);
Uri packageURI = getInstallablePackage(rawResId, outFile);
PackageParser.Package pkg = parsePackage(packageURI);
assertNotNull(pkg);
- InstallParams ip = null;
- // Make sure the package doesn't exist
- getPm().deletePackage(pkg.packageName, null, 0);
- // Clean up the containers as well
- clearSecureContainersForPkg(pkg.packageName);
- try {
+ if ((flags & PackageManager.INSTALL_REPLACE_EXISTING) == 0) {
+ // Make sure the package doesn't exist
try {
- if (fail) {
- assertTrue(invokeInstallPackageFail(packageURI, flags,
- pkg.packageName, result));
- assertNotInstalled(pkg.packageName);
- } else {
- InstallReceiver receiver = new InstallReceiver(pkg.packageName);
- assertTrue(invokeInstallPackage(packageURI, flags,
- pkg.packageName, receiver));
- // Verify installed information
- assertInstall(pkg, flags, expInstallLocation);
- ip = new InstallParams(pkg, outFileName, packageURI);
- }
+ ApplicationInfo appInfo = pm.getApplicationInfo(pkg.packageName,
+ PackageManager.GET_UNINSTALLED_PACKAGES);
+ GenericReceiver receiver = new DeleteReceiver(pkg.packageName);
+ invokeDeletePackage(packageURI, 0,
+ pkg.packageName, receiver);
+ } catch (NameNotFoundException e1) {
} catch (Exception e) {
- failStr("Failed with exception : " + e);
+ failStr(e);
+ }
+ // Clean up the containers as well
+ clearSecureContainersForPkg(pkg.packageName);
+ }
+ InstallParams ip = null;
+ try {
+ if (fail) {
+ assertTrue(invokeInstallPackageFail(packageURI, flags,
+ pkg.packageName, result));
+ assertNotInstalled(pkg.packageName);
+ } else {
+ InstallReceiver receiver = new InstallReceiver(pkg.packageName);
+ assertTrue(invokeInstallPackage(packageURI, flags,
+ pkg.packageName, receiver));
+ // Verify installed information
+ assertInstall(pkg, flags, expInstallLocation);
+ ip = new InstallParams(pkg, outFileName, packageURI);
}
return ip;
+ } catch (Exception e) {
+ failStr("Failed with exception : " + e);
} finally {
if (cleanUp) {
cleanUpInstall(ip);
}
}
+ return ip;
}
@MediumTest
@@ -820,7 +831,7 @@ public class PackageManagerTests extends AndroidTestCase {
try {
// Wait on observer
synchronized(observer) {
- getMs().unmountVolume(path, false);
+ getMs().unmountVolume(path, true);
long waitTime = 0;
while((!observer.isDone()) && (waitTime < MAX_WAIT_TIME) ) {
observer.wait(WAIT_TIME_INCR);
@@ -949,14 +960,21 @@ public class PackageManagerTests extends AndroidTestCase {
PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
}
- private void replaceManifestLocation(int iFlags, int rFlags) {
+ /*
+ * Install a package on internal flash via PackageManager install flag. Replace
+ * the package via flag to install on sdcard. Make sure the new flag overrides
+ * the old install location.
+ */
+ public void testReplaceFlagInternalSdcard() {
+ int iFlags = 0;
+ int rFlags = PackageManager.INSTALL_EXTERNAL;
InstallParams ip = sampleInstallFromRawResource(iFlags, false);
GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
try {
assertEquals(invokeInstallPackage(ip.packageURI, replaceFlags,
ip.pkg.packageName, receiver), true);
- assertInstall(ip.pkg, replaceFlags, ip.pkg.installLocation);
+ assertInstall(ip.pkg, rFlags, ip.pkg.installLocation);
} catch (Exception e) {
failStr("Failed with exception : " + e);
} finally {
@@ -964,12 +982,26 @@ public class PackageManagerTests extends AndroidTestCase {
}
}
- public void testReplaceFlagInternalSdcard() {
- replaceManifestLocation(0, PackageManager.INSTALL_EXTERNAL);
- }
-
+ /*
+ * Install a package on sdcard via PackageManager install flag. Replace
+ * the package with no flags or manifest option and make sure the old
+ * install location is retained.
+ */
public void testReplaceFlagSdcardInternal() {
- replaceManifestLocation(PackageManager.INSTALL_EXTERNAL, 0);
+ int iFlags = PackageManager.INSTALL_EXTERNAL;
+ int rFlags = 0;
+ InstallParams ip = sampleInstallFromRawResource(iFlags, false);
+ GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
+ int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
+ try {
+ assertEquals(invokeInstallPackage(ip.packageURI, replaceFlags,
+ ip.pkg.packageName, receiver), true);
+ assertInstall(ip.pkg, iFlags, ip.pkg.installLocation);
+ } catch (Exception e) {
+ failStr("Failed with exception : " + e);
+ } finally {
+ cleanUpInstall(ip);
+ }
}
public void testManifestInstallLocationReplaceInternalSdcard() {
@@ -984,7 +1016,7 @@ public class PackageManagerTests extends AndroidTestCase {
int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
try {
InstallParams rp = installFromRawResource("install.apk", rApk,
- rFlags, false,
+ replaceFlags, false,
false, -1, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
assertInstall(rp.pkg, replaceFlags, rp.pkg.installLocation);
} catch (Exception e) {
@@ -1002,11 +1034,10 @@ public class PackageManagerTests extends AndroidTestCase {
InstallParams ip = installFromRawResource("install.apk", iApk,
iFlags, false,
false, -1, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
- GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
try {
InstallParams rp = installFromRawResource("install.apk", rApk,
- rFlags, false,
+ replaceFlags, false,
false, -1, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
assertInstall(rp.pkg, replaceFlags, ip.pkg.installLocation);
} catch (Exception e) {
@@ -1211,6 +1242,56 @@ public class PackageManagerTests extends AndroidTestCase {
moveFromRawResource(PackageManager.INSTALL_EXTERNAL, PackageManager.MOVE_INTERNAL,
PackageManager.MOVE_SUCCEEDED);
}
+
+ /*
+ * Test that an install error code is returned when media is unmounted
+ * and package installed on sdcard via package manager flag.
+ */
+ public void testInstallSdcardUnmount() {
+ boolean origState = getMediaState();
+ try {
+ // Unmount sdcard
+ assertTrue(unmountMedia());
+ // Try to install and make sure an error code is returned.
+ assertNull(installFromRawResource("install.apk", R.raw.install,
+ PackageManager.INSTALL_EXTERNAL, false,
+ true, PackageManager.INSTALL_FAILED_CONTAINER_ERROR,
+ PackageInfo.INSTALL_LOCATION_AUTO));
+ } finally {
+ // Restore original media state
+ if (origState) {
+ mountMedia();
+ } else {
+ unmountMedia();
+ }
+ }
+ }
+
+ /*
+ * Unmount sdcard. Try installing an app with manifest option to install
+ * on sdcard. Make sure it gets installed on internal flash.
+ */
+ public void testInstallManifestSdcardUnmount() {
+ boolean origState = getMediaState();
+ try {
+ // Unmount sdcard
+ assertTrue(unmountMedia());
+ // Try to install and make sure an error code is returned.
+ assertNotNull(installFromRawResource("install.apk", R.raw.install_loc_sdcard,
+ 0, false,
+ false, -1,
+ PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY));
+ } finally {
+ // Restore original media state
+ if (origState) {
+ mountMedia();
+ } else {
+ unmountMedia();
+ }
+ }
+ }
+
+ /*---------- Recommended install location tests ----*/
/*
* TODO's
* check version numbers for upgrades
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index d833e33..5fd44b1 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -81,5 +81,7 @@ interface IWifiManager
boolean setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
int getWifiApEnabledState();
+
+ WifiConfiguration getWifiApConfiguration();
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 9ef8ba1..970d5fc 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -810,6 +810,20 @@ public class WifiManager {
}
/**
+ * Gets the Wi-Fi AP Configuration.
+ * @return AP details in WifiConfiguration
+ *
+ * @hide Dont open yet
+ */
+ public WifiConfiguration getWifiApConfiguration() {
+ try {
+ return mService.getWifiApConfiguration();
+ } catch (RemoteException e) {
+ return null;
+ }
+ }
+
+ /**
* 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