summaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/DocumentsUI/res/values-gu-rIN/strings.xml8
-rw-r--r--packages/DocumentsUI/res/values-pa-rIN/strings.xml8
-rw-r--r--packages/DocumentsUI/res/values-sq-rAL/strings.xml8
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/CopyService.java31
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java290
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java100
-rw-r--r--packages/Keyguard/res/values-sq-rAL/strings.xml2
-rw-r--r--packages/Keyguard/src/com/android/keyguard/EmergencyButton.java7
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java1
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java23
-rw-r--r--packages/PrintSpooler/res/values-sq-rAL/strings.xml4
-rw-r--r--packages/SettingsLib/res/values/strings.xml11
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java25
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java216
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java12
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java25
-rw-r--r--packages/SettingsProvider/res/values-sq-rAL/defaults.xml24
-rw-r--r--packages/SystemUI/res/values-pa-rIN/strings.xml21
-rw-r--r--packages/SystemUI/res/values-sq-rAL/strings.xml33
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java73
20 files changed, 661 insertions, 261 deletions
diff --git a/packages/DocumentsUI/res/values-gu-rIN/strings.xml b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
index 41bd168..cac6021 100644
--- a/packages/DocumentsUI/res/values-gu-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-gu-rIN/strings.xml
@@ -65,9 +65,11 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલો કૉપિ કરી રહ્યાં છે.</item>
</plurals>
<string name="copy_preparing" msgid="3896202461003039386">"કૉપિ માટે તૈયારી કરી રહ્યું છે…"</string>
- <!-- no translation found for copy_error_notification_title (5267616889076217261) -->
+ <plurals name="copy_error_notification_title" formatted="false" msgid="5267616889076217261">
+ <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલો કૉપિ કરી શકાઈ નથી</item>
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ફાઇલો કૉપિ કરી શકાઈ નથી</item>
+ </plurals>
<string name="notification_touch_for_details" msgid="4483108577842961665">"વિગતો જોવા માટે ટચ કરો"</string>
<string name="retry" msgid="7564024179122207376">"ફરી પ્રયાસ કરો"</string>
- <!-- no translation found for copy_failure_alert_content (3715575000297709082) -->
- <skip />
+ <string name="copy_failure_alert_content" msgid="3715575000297709082">"આ ફાઇલો કૉપિ કરી નહોતી: <xliff:g id="LIST">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/DocumentsUI/res/values-pa-rIN/strings.xml b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
index 978ea5a..56e4aa8 100644
--- a/packages/DocumentsUI/res/values-pa-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-pa-rIN/strings.xml
@@ -65,9 +65,11 @@
<item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> ਫਾਈਲਾਂ ਕਾਪੀ ਕਰ ਰਿਹਾ ਹੈ।</item>
</plurals>
<string name="copy_preparing" msgid="3896202461003039386">"ਕਾਪੀ ਲਈ ਤਿਆਰ ਕਰ ਰਿਹਾ ਹੈ…"</string>
- <!-- no translation found for copy_error_notification_title (5267616889076217261) -->
+ <plurals name="copy_error_notification_title" formatted="false" msgid="5267616889076217261">
+ <item quantity="one"> <xliff:g id="COUNT_1">%1$d</xliff:g> ਫ਼ਾਈਲਾਂ ਦੀ ਪ੍ਰਤੀਲਿਪੀ ਨਹੀਂ ਬਣਾ ਸਕਿਆ</item>
+ <item quantity="other"> <xliff:g id="COUNT_1">%1$d</xliff:g> ਫ਼ਾਈਲਾਂ ਦੀ ਪ੍ਰਤੀਲਿਪੀ ਨਹੀਂ ਬਣਾ ਸਕਿਆ</item>
+ </plurals>
<string name="notification_touch_for_details" msgid="4483108577842961665">"ਵੇਰਵੇ ਵੇਖਣ ਲਈ ਸਪਰਸ਼ ਕਰੋ"</string>
<string name="retry" msgid="7564024179122207376">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
- <!-- no translation found for copy_failure_alert_content (3715575000297709082) -->
- <skip />
+ <string name="copy_failure_alert_content" msgid="3715575000297709082">"ਇਹਨਾਂ ਫ਼ਾਈਲਾਂ ਦੀ ਪ੍ਰਤੀਲਿਪੀ ਨਹੀਂ ਬਣਾਈ ਗਈ: <xliff:g id="LIST">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index 0e10e5d..37c063f 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -65,9 +65,11 @@
<item quantity="one">Po kopjon <xliff:g id="COUNT_0">%1$d</xliff:g> skedar.</item>
</plurals>
<string name="copy_preparing" msgid="3896202461003039386">"Po përgatitet për kopjimin…"</string>
- <!-- no translation found for copy_error_notification_title (5267616889076217261) -->
+ <plurals name="copy_error_notification_title" formatted="false" msgid="5267616889076217261">
+ <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> skedarë nuk mund të kopjoheshin</item>
+ <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> skedar nuk mund të kopjohej</item>
+ </plurals>
<string name="notification_touch_for_details" msgid="4483108577842961665">"Prek për të parë detajet"</string>
<string name="retry" msgid="7564024179122207376">"Provo përsëri"</string>
- <!-- no translation found for copy_failure_alert_content (3715575000297709082) -->
- <skip />
+ <string name="copy_failure_alert_content" msgid="3715575000297709082">"Këta skedarë nuk u kopjuan: <xliff:g id="LIST">%1$s</xliff:g>"</string>
</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
index 2e0bece..9dd2b20 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CopyService.java
@@ -449,7 +449,7 @@ public class CopyService extends IntentService {
InputStream src = null;
OutputStream dst = null;
- boolean errorOccurred = false;
+ IOException copyError = null;
try {
srcFile = mSrcClient.openFile(srcUri, "r", canceller);
dstFile = mDstClient.openFile(dstUri, "w", canceller);
@@ -462,24 +462,35 @@ public class CopyService extends IntentService {
dst.write(buffer, 0, len);
makeProgress(len);
}
+
srcFile.checkError();
- dstFile.checkError();
} catch (IOException e) {
- errorOccurred = true;
- Log.e(TAG, "Error while copying " + srcUri.toString(), e);
+ copyError = e;
+ } finally {
+ if (copyError != null) {
+ try {
+ dstFile.closeWithError(copyError.getMessage());
+ } catch (IOException e) {
+ Log.e(TAG, "Error closing destination", e);
+ }
+ }
+ // This also ensures the file descriptors are closed.
+ IoUtils.closeQuietly(src);
+ IoUtils.closeQuietly(dst);
+ }
+
+ if (copyError != null) {
+ // Log errors.
+ Log.e(TAG, "Error while copying " + srcUri.toString(), copyError);
try {
mFailedFiles.add(DocumentInfo.fromUri(getContentResolver(), srcUri));
} catch (FileNotFoundException ignore) {
- Log.w(TAG, "Source file gone: " + srcUri, e);
+ Log.w(TAG, "Source file gone: " + srcUri, copyError);
// The source file is gone.
}
- } finally {
- // This also ensures the file descriptors are closed.
- IoUtils.closeQuietly(src);
- IoUtils.closeQuietly(dst);
}
- if (errorOccurred || mIsCancelled) {
+ if (copyError != null || mIsCancelled) {
// Clean up half-copied files.
canceller.cancel();
try {
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java
index 13f7daa..b1c84dd 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/CopyTest.java
@@ -16,23 +16,21 @@
package com.android.documentsui;
-import static com.android.documentsui.model.DocumentInfo.getCursorString;
-
-import android.app.NotificationManager;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
+import android.content.pm.ProviderInfo;
+import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
-import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
import android.os.RemoteException;
import android.provider.DocumentsContract;
-import android.provider.DocumentsContract.Document;
import android.test.MoreAsserts;
import android.test.ServiceTestCase;
+import android.test.mock.MockContentResolver;
import android.util.Log;
import com.android.documentsui.model.DocumentInfo;
@@ -43,40 +41,93 @@ import com.google.common.collect.Lists;
import libcore.io.IoUtils;
import libcore.io.Streams;
-import org.mockito.Mockito;
-
+import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
public class CopyTest extends ServiceTestCase<CopyService> {
+ /**
+ * A test resolver that enables this test suite to listen for notifications that mark when copy
+ * operations are done.
+ */
+ class TestContentResolver extends MockContentResolver {
+ private CountDownLatch mReadySignal;
+ private CountDownLatch mNotificationSignal;
+
+ public TestContentResolver() {
+ mReadySignal = new CountDownLatch(1);
+ }
+
+ /**
+ * Wait for the given number of files to be copied to destination. Times out after 1 sec.
+ */
+ public void waitForChanges(int count) throws Exception {
+ // Wait for no more than 1 second by default.
+ waitForChanges(count, 1000);
+ }
+
+ /**
+ * Wait for files to be copied to destination.
+ *
+ * @param count Number of files to wait for.
+ * @param timeOut Timeout in ms. TimeoutException will be thrown if this function times out.
+ */
+ public void waitForChanges(int count, int timeOut) throws Exception {
+ mNotificationSignal = new CountDownLatch(count);
+ // Signal that the test is now waiting for files.
+ mReadySignal.countDown();
+ if (!mNotificationSignal.await(timeOut, TimeUnit.MILLISECONDS)) {
+ throw new TimeoutException("Timed out waiting for files to be copied.");
+ }
+ }
+
+ @Override
+ public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
+ // Wait until the test is ready to receive file notifications.
+ try {
+ mReadySignal.await();
+ } catch (InterruptedException e) {
+ Log.d(TAG, "Interrupted while waiting for file copy readiness");
+ Thread.currentThread().interrupt();
+ }
+ if (DocumentsContract.isDocumentUri(mContext, uri)) {
+ Log.d(TAG, "Notification: " + uri);
+ // Watch for document URI change notifications - this signifies the end of a copy.
+ mNotificationSignal.countDown();
+ }
+ }
+ };
+
public CopyTest() {
super(CopyService.class);
}
- private static String TAG = "CopyTest";
- // This must match the authority for the StubProvider.
private static String AUTHORITY = "com.android.documentsui.stubprovider";
+ private static String DST = "sd1";
+ private static String SRC = "sd0";
+ private static String TAG = "CopyTest";
private List<RootInfo> mRoots;
private Context mContext;
- private ContentResolver mResolver;
+ private TestContentResolver mResolver;
private ContentProviderClient mClient;
- private NotificationManager mNotificationManager;
+ private StubProvider mStorage;
+ private Context mSystemContext;
@Override
protected void setUp() throws Exception {
super.setUp();
- setupTestContext();
- mResolver = mContext.getContentResolver();
+ setupTestContext();
mClient = mResolver.acquireContentProviderClient(AUTHORITY);
// Reset the stub provider's storage.
- mClient.call("clear", "", null);
+ mStorage.clearCacheAndBuildRoots();
mRoots = Lists.newArrayList();
Uri queryUri = DocumentsContract.buildRootsUri(AUTHORITY);
@@ -84,9 +135,7 @@ public class CopyTest extends ServiceTestCase<CopyService> {
try {
cursor = mClient.query(queryUri, null, null, null, null);
while (cursor.moveToNext()) {
- final RootInfo root = RootInfo.fromRootsCursor(AUTHORITY, cursor);
- final String id = root.rootId;
- mRoots.add(root);
+ mRoots.add(RootInfo.fromRootsCursor(AUTHORITY, cursor));
}
} finally {
IoUtils.closeQuietly(cursor);
@@ -100,68 +149,94 @@ public class CopyTest extends ServiceTestCase<CopyService> {
super.tearDown();
}
- public List<Uri> setupTestFiles() throws Exception {
- Uri rootUri = DocumentsContract.buildDocumentUri(AUTHORITY, mRoots.get(0).documentId);
- List<Uri> testFiles = Lists.newArrayList(
- DocumentsContract.createDocument(mClient, rootUri, "text/plain", "test0.txt"),
- DocumentsContract.createDocument(mClient, rootUri, "text/plain", "test1.txt"),
- DocumentsContract.createDocument(mClient, rootUri, "text/plain", "test2.txt")
- );
- String testContent[] = {
- "The five boxing wizards jump quickly",
- "The quick brown fox jumps over the lazy dog",
- "Jackdaws love my big sphinx of quartz"
- };
- for (int i = 0; i < testFiles.size(); ++i) {
- ParcelFileDescriptor pfd = null;
- OutputStream out = null;
- try {
- pfd = mClient.openFile(testFiles.get(i), "w");
- out = new ParcelFileDescriptor.AutoCloseOutputStream(pfd);
- out.write(testContent[i].getBytes());
- } finally {
- IoUtils.closeQuietly(out);
- }
- }
- return testFiles;
- }
-
/**
* Test copying a single file.
*/
public void testCopyFile() throws Exception {
- Uri testFile = setupTestFiles().get(0);
+ String srcPath = "/test0.txt";
+ Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain",
+ "The five boxing wizards jump quickly".getBytes());
+
+ assertDstFileCountEquals(0);
- // Just copy one file.
copyToDestination(Lists.newArrayList(testFile));
- // A call to NotificationManager.cancel marks the end of the copy operation.
- Mockito.verify(mNotificationManager, Mockito.timeout(1000)).cancel(Mockito.anyString(),
- Mockito.anyInt());
+ // 2 operations: file creation, then writing data.
+ mResolver.waitForChanges(2);
// Verify that one file was copied; check file contents.
assertDstFileCountEquals(1);
- assertCopied(testFile);
+ assertCopied(srcPath);
}
/**
* Test copying multiple files.
*/
public void testCopyMultipleFiles() throws Exception {
- List<Uri> testFiles = setupTestFiles();
+ String testContent[] = {
+ "The five boxing wizards jump quickly",
+ "The quick brown fox jumps over the lazy dog",
+ "Jackdaws love my big sphinx of quartz"
+ };
+ String srcPaths[] = {
+ "/test0.txt",
+ "/test1.txt",
+ "/test2.txt"
+ };
+ List<Uri> testFiles = Lists.newArrayList(
+ mStorage.createFile(SRC, srcPaths[0], "text/plain", testContent[0].getBytes()),
+ mStorage.createFile(SRC, srcPaths[1], "text/plain", testContent[1].getBytes()),
+ mStorage.createFile(SRC, srcPaths[2], "text/plain", testContent[2].getBytes()));
+
+ assertDstFileCountEquals(0);
+
// Copy all the test files.
copyToDestination(testFiles);
- // A call to NotificationManager.cancel marks the end of the copy operation.
- Mockito.verify(mNotificationManager, Mockito.timeout(1000)).cancel(Mockito.anyString(),
- Mockito.anyInt());
+ // 3 file creations, 3 file writes.
+ mResolver.waitForChanges(6);
assertDstFileCountEquals(3);
- for (Uri testFile : testFiles) {
- assertCopied(testFile);
+ for (String path : srcPaths) {
+ assertCopied(path);
}
}
+ public void testCopyEmptyDir() throws Exception {
+ String srcPath = "/emptyDir";
+ Uri testDir = mStorage.createFile(SRC, srcPath, DocumentsContract.Document.MIME_TYPE_DIR,
+ null);
+
+ assertDstFileCountEquals(0);
+
+ copyToDestination(Lists.newArrayList(testDir));
+
+ // Just 1 operation: Directory creation.
+ mResolver.waitForChanges(1);
+
+ assertDstFileCountEquals(1);
+
+ File dst = mStorage.getFile(DST, srcPath);
+ assertTrue(dst.isDirectory());
+ }
+
+ public void testReadErrors() throws Exception {
+ String srcPath = "/test0.txt";
+ Uri testFile = mStorage.createFile(SRC, srcPath, "text/plain",
+ "The five boxing wizards jump quickly".getBytes());
+
+ assertDstFileCountEquals(0);
+
+ mStorage.simulateReadErrors(true);
+
+ copyToDestination(Lists.newArrayList(testFile));
+
+ // 3 operations: file creation, writing, then deletion (due to failed copy).
+ mResolver.waitForChanges(3);
+
+ assertDstFileCountEquals(0);
+ }
+
/**
* Copies the given files to a pre-determined destination.
*
@@ -200,82 +275,55 @@ public class CopyTest extends ServiceTestCase<CopyService> {
assertEquals("Incorrect file count after copy", expected, count);
}
- /**
- * Verifies that the file pointed to by the given URI was correctly copied to the destination.
- */
- private void assertCopied(Uri src) throws Exception {
- Cursor cursor = null;
- String srcName = null;
- try {
- cursor = mClient.query(src, null, null, null, null);
- if (cursor.moveToFirst()) {
- srcName = getCursorString(cursor, Document.COLUMN_DISPLAY_NAME);
- }
- } finally {
- IoUtils.closeQuietly(cursor);
- }
- Uri dst = getDstFileUri(srcName);
+ private void assertCopied(String path) throws Exception {
+ File srcFile = mStorage.getFile(SRC, path);
+ File dstFile = mStorage.getFile(DST, path);
+ assertNotNull(dstFile);
- InputStream in0 = null;
- InputStream in1 = null;
+ FileInputStream src = null;
+ FileInputStream dst = null;
try {
- in0 = new ParcelFileDescriptor.AutoCloseInputStream(mClient.openFile(src, "r"));
- in1 = new ParcelFileDescriptor.AutoCloseInputStream(mClient.openFile(dst, "r"));
-
- byte[] buffer0 = Streams.readFully(in0);
- byte[] buffer1 = Streams.readFully(in1);
-
- MoreAsserts.assertEquals(buffer0, buffer1);
- } finally {
- IoUtils.closeQuietly(in0);
- IoUtils.closeQuietly(in1);
- }
- }
+ src = new FileInputStream(srcFile);
+ dst = new FileInputStream(dstFile);
+ byte[] srcbuf = Streams.readFully(src);
+ byte[] dstbuf = Streams.readFully(dst);
- /**
- * Generates a file URI from a given filename. This assumes the file already exists in the
- * destination root.
- */
- private Uri getDstFileUri(String filename) throws RemoteException {
- final Uri dstFileQuery = DocumentsContract.buildChildDocumentsUri(AUTHORITY,
- mRoots.get(1).documentId);
- Cursor cursor = null;
- try {
- // StubProvider doesn't seem to support query strings; filter the results manually.
- cursor = mClient.query(dstFileQuery, null, null, null, null);
- while (cursor.moveToNext()) {
- if (filename.equals(getCursorString(cursor, Document.COLUMN_DISPLAY_NAME))) {
- return DocumentsContract.buildDocumentUri(AUTHORITY,
- getCursorString(cursor, Document.COLUMN_DOCUMENT_ID));
- }
- }
+ MoreAsserts.assertEquals(srcbuf, dstbuf);
} finally {
- IoUtils.closeQuietly(cursor);
+ IoUtils.closeQuietly(src);
+ IoUtils.closeQuietly(dst);
}
- return null;
}
/**
* Sets up a ContextWrapper that substitutes a stub NotificationManager. This allows the test to
* listen for notification events, to gauge copy progress.
+ *
+ * @throws FileNotFoundException
*/
- private void setupTestContext() {
- mContext = getSystemContext();
- System.setProperty("dexmaker.dexcache", mContext.getCacheDir().getPath());
+ private void setupTestContext() throws FileNotFoundException {
+ mSystemContext = getSystemContext();
- mNotificationManager = Mockito.spy((NotificationManager) mContext
- .getSystemService(Context.NOTIFICATION_SERVICE));
-
- // Insert a stub NotificationManager that enables us to listen for when copying is complete.
- setContext(new ContextWrapper(mContext) {
+ // Set up the context with the test content resolver.
+ mResolver = new TestContentResolver();
+ mContext = new ContextWrapper(mSystemContext) {
@Override
- public Object getSystemService(String name) {
- if (Context.NOTIFICATION_SERVICE.equals(name)) {
- return mNotificationManager;
- } else {
- return super.getSystemService(name);
- }
+ public ContentResolver getContentResolver() {
+ return mResolver;
}
- });
+ };
+ setContext(mContext);
+
+ // Create a local stub provider and add it to the content resolver.
+ ProviderInfo info = new ProviderInfo();
+ info.authority = AUTHORITY;
+ info.exported = true;
+ info.grantUriPermissions = true;
+ info.readPermission = android.Manifest.permission.MANAGE_DOCUMENTS;
+ info.writePermission = android.Manifest.permission.MANAGE_DOCUMENTS;
+
+ mStorage = new StubProvider();
+ mStorage.attachInfo(mContext, info);
+ mResolver.addProvider(AUTHORITY, mStorage);
}
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
index 438f6cd..8cef433 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/StubProvider.java
@@ -21,9 +21,10 @@ import android.content.SharedPreferences;
import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
-import android.database.MatrixCursor.RowBuilder;
import android.database.MatrixCursor;
+import android.database.MatrixCursor.RowBuilder;
import android.graphics.Point;
+import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.FileUtils;
@@ -32,15 +33,16 @@ import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import android.provider.DocumentsProvider;
+import android.support.annotation.VisibleForTesting;
import android.util.Log;
import com.google.android.collect.Maps;
import libcore.io.IoUtils;
-import java.io.FileOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -70,6 +72,7 @@ public class StubProvider extends DocumentsProvider {
private String mAuthority;
private SharedPreferences mPrefs;
private Map<String, RootInfo> mRoots;
+ private boolean mSimulateReadErrors;
@Override
public void attachInfo(Context context, ProviderInfo info) {
@@ -83,7 +86,8 @@ public class StubProvider extends DocumentsProvider {
return true;
}
- private void clearCacheAndBuildRoots() {
+ @VisibleForTesting
+ public void clearCacheAndBuildRoots() {
final File cacheDir = getContext().getCacheDir();
removeRecursively(cacheDir);
mStorage.clear();
@@ -164,7 +168,7 @@ public class StubProvider extends DocumentsProvider {
} else {
try {
if (!file.createNewFile()) {
- throw new FileNotFoundException();
+ throw new IllegalStateException("The file " + file.getPath() + " already exists");
}
} catch (IOException e) {
throw new FileNotFoundException();
@@ -173,6 +177,10 @@ public class StubProvider extends DocumentsProvider {
final StubDocument document = new StubDocument(file, mimeType, parentDocument);
notifyParentChanged(document.parentId);
+ getContext().getContentResolver().notifyChange(
+ DocumentsContract.buildDocumentUri(mAuthority, document.documentId),
+ null, false);
+
return document.documentId;
}
@@ -187,6 +195,9 @@ public class StubProvider extends DocumentsProvider {
document.rootInfo.size -= fileSize;
}
notifyParentChanged(document.parentId);
+ getContext().getContentResolver().notifyChange(
+ DocumentsContract.buildDocumentUri(mAuthority, document.documentId),
+ null, false);
}
@Override
@@ -226,7 +237,17 @@ public class StubProvider extends DocumentsProvider {
throw new FileNotFoundException();
if ("r".equals(mode)) {
- return ParcelFileDescriptor.open(document.file, ParcelFileDescriptor.MODE_READ_ONLY);
+ ParcelFileDescriptor pfd = ParcelFileDescriptor.open(document.file,
+ ParcelFileDescriptor.MODE_READ_ONLY);
+ if (mSimulateReadErrors) {
+ pfd = new ParcelFileDescriptor(pfd) {
+ @Override
+ public void checkError() throws IOException {
+ throw new IOException("Test error");
+ }
+ };
+ }
+ return pfd;
}
if ("w".equals(mode)) {
return startWrite(document);
@@ -235,6 +256,11 @@ public class StubProvider extends DocumentsProvider {
throw new FileNotFoundException();
}
+ @VisibleForTesting
+ public void simulateReadErrors(boolean b) {
+ mSimulateReadErrors = b;
+ }
+
@Override
public AssetFileDescriptor openDocumentThumbnail(
String docId, Point sizeHint, CancellationSignal signal) throws FileNotFoundException {
@@ -281,11 +307,15 @@ public class StubProvider extends DocumentsProvider {
}
}
} catch (IOException e) {
+ Log.e(TAG, "Error on close", e);
closePipeWithErrorSilently(readPipe, e.getMessage());
} finally {
IoUtils.closeQuietly(inputStream);
IoUtils.closeQuietly(outputStream);
notifyParentChanged(document.parentId);
+ getContext().getContentResolver().notifyChange(
+ DocumentsContract.buildDocumentUri(mAuthority, document.documentId),
+ null, false);
}
}
}.start();
@@ -302,7 +332,6 @@ public class StubProvider extends DocumentsProvider {
@Override
public Bundle call(String method, String arg, Bundle extras) {
- Log.d(TAG, "call: " + method + arg);
switch (method) {
case "clear":
clearCacheAndBuildRoots();
@@ -376,30 +405,51 @@ public class StubProvider extends DocumentsProvider {
}
}
- public File createFile(String rootId, File parent, String mimeType, String name)
- throws IOException {
- StubDocument parentDoc = null;
+ @VisibleForTesting
+ public Uri createFile(String rootId, String path, String mimeType, byte[] content)
+ throws FileNotFoundException, IOException {
+ StubDocument root = mRoots.get(rootId).rootDocument;
+ if (root == null) {
+ throw new FileNotFoundException("No roots with the ID " + rootId + " were found");
+ }
+ File file = new File(root.file, path.substring(1));
+ StubDocument parent = mStorage.get(getDocumentIdForFile(file.getParentFile()));
if (parent == null) {
- // Use the root dir as the parent, if one wasn't specified.
- parentDoc = mRoots.get(rootId).rootDocument;
- } else {
- // Verify that the parent exists and is a directory.
- parentDoc = mStorage.get(getDocumentIdForFile(parent));
- if (parentDoc == null) {
- throw new IllegalArgumentException("Parent file not found.");
+ parent = mStorage.get(createFile(rootId, file.getParentFile().getPath(),
+ DocumentsContract.Document.MIME_TYPE_DIR, null));
+ }
+
+ if (DocumentsContract.Document.MIME_TYPE_DIR.equals(mimeType)) {
+ if (!file.mkdirs()) {
+ throw new FileNotFoundException("Couldn't create directory " + file.getPath());
}
- if (!Document.MIME_TYPE_DIR.equals(parentDoc.mimeType)) {
- throw new IllegalArgumentException("Parent file must be a directory.");
+ } else {
+ if (!file.createNewFile()) {
+ throw new FileNotFoundException("Couldn't create file " + file.getPath());
}
+ // Add content to the file.
+ FileOutputStream fout = new FileOutputStream(file);
+ fout.write(content);
+ fout.close();
}
- File file = new File(parentDoc.file, name);
- if (Document.MIME_TYPE_DIR.equals(mimeType)) {
- file.mkdir();
- } else {
- file.createNewFile();
+ final StubDocument document = new StubDocument(file, mimeType, parent);
+ return DocumentsContract.buildDocumentUri(mAuthority, document.documentId);
+ }
+
+ @VisibleForTesting
+ public File getFile(String rootId, String path) throws FileNotFoundException {
+ StubDocument root = mRoots.get(rootId).rootDocument;
+ if (root == null) {
+ throw new FileNotFoundException("No roots with the ID " + rootId + " were found");
+ }
+ // Convert the path string into a path that's relative to the root.
+ File needle = new File(root.file, path.substring(1));
+
+ StubDocument found = mStorage.get(getDocumentIdForFile(needle));
+ if (found == null) {
+ return null;
}
- new StubDocument(file, mimeType, parentDoc);
- return file;
+ return found.file;
}
final class RootInfo {
diff --git a/packages/Keyguard/res/values-sq-rAL/strings.xml b/packages/Keyguard/res/values-sq-rAL/strings.xml
index d356588..f3943ea 100644
--- a/packages/Keyguard/res/values-sq-rAL/strings.xml
+++ b/packages/Keyguard/res/values-sq-rAL/strings.xml
@@ -108,6 +108,6 @@
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kodi u pranua!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nuk ka shërbim."</string>
<string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Butoni i metodës së ndërrimit të hyrjeve."</string>
- <string name="airplane_mode" msgid="3122107900897202805">"Modaliteti i aeroplanit"</string>
+ <string name="airplane_mode" msgid="3122107900897202805">"Modaliteti \"në aeroplan\""</string>
<string name="fingerprint_not_recognized" msgid="2690661881608146617">"Nuk njihet"</string>
</resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index 25b1875..1cabcdf 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -18,6 +18,7 @@ package com.android.keyguard;
import android.content.Context;
import android.content.Intent;
+import android.content.res.Configuration;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -104,6 +105,12 @@ public class EmergencyButton extends Button {
updateEmergencyCallButton();
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateEmergencyCallButton();
+ }
+
/**
* Shows the emergency dialer or returns the user to the existing call.
*/
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index ae4baad..4d89a8d 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -260,7 +260,6 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe
if (DEBUG) Log.d(TAG, "reportFailedPatternAttempt: #" + failedAttempts);
SecurityMode mode = mSecurityModel.getSecurityMode();
- final boolean usingPattern = mode == KeyguardSecurityModel.SecurityMode.Pattern;
final int currentUser = KeyguardUpdateMonitor.getCurrentUser();
final DevicePolicyManager dpm = mLockPatternUtils.getDevicePolicyManager();
final int failedAttemptsBeforeWipe =
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index b8d9053..c7b7628 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -65,6 +65,7 @@ import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
import com.google.android.collect.Lists;
@@ -139,7 +140,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private BatteryStatus mBatteryStatus;
// Password attempts
- private int mFailedAttempts = 0;
+ private SparseIntArray mFailedAttempts = new SparseIntArray();
private boolean mClockVisible;
@@ -1260,28 +1261,20 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
return mDeviceProvisioned;
}
- public int getFailedUnlockAttempts() {
- return mFailedAttempts;
- }
-
public void clearFailedUnlockAttempts() {
- mFailedAttempts = 0;
+ mFailedAttempts.delete(sCurrentUser);
}
- public void clearFingerprintRecognized() {
- mUserFingerprintAuthenticated.clear();
+ public int getFailedUnlockAttempts() {
+ return mFailedAttempts.get(sCurrentUser, 0);
}
public void reportFailedUnlockAttempt() {
- mFailedAttempts++;
- }
-
- public boolean isClockVisible() {
- return mClockVisible;
+ mFailedAttempts.put(sCurrentUser, getFailedUnlockAttempts() + 1);
}
- public int getPhoneState() {
- return mPhoneState;
+ public void clearFingerprintRecognized() {
+ mUserFingerprintAuthenticated.clear();
}
public boolean isSimPinVoiceSecure() {
diff --git a/packages/PrintSpooler/res/values-sq-rAL/strings.xml b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
index 01eb719..0fbde0e 100644
--- a/packages/PrintSpooler/res/values-sq-rAL/strings.xml
+++ b/packages/PrintSpooler/res/values-sq-rAL/strings.xml
@@ -66,8 +66,8 @@
<string name="failed_notification_title_template" msgid="2256217208186530973">"Printeri ndeshi në gabim gjatë punës: <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<string name="blocked_notification_title_template" msgid="1175435827331588646">"Printeri bllokoi <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string>
<plurals name="composite_notification_title_template" formatted="false" msgid="6940956968211733780">
- <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> punë printimi</item>
- <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> punë printimi</item>
+ <item quantity="other"><xliff:g id="PRINT_JOB_NAME_1">%1$d</xliff:g> punë për printim</item>
+ <item quantity="one"><xliff:g id="PRINT_JOB_NAME_0">%1$d</xliff:g> punë për printim</item>
</plurals>
<string name="cancel" msgid="4373674107267141885">"Anulo"</string>
<string name="restart" msgid="2472034227037808749">"Rifillo"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 6876222..4082bf5 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -72,6 +72,9 @@
<!-- Status message of Wi-Fi when network has matching passpoint credentials. [CHAR LIMIT=NONE] -->
<string name="available_via_passpoint">Available via %1$s</string>
+ <!-- Summary for Connected wifi network without internet -->
+ <string name="wifi_connected_no_internet">Connected, no Internet</string>
+
<!-- Bluetooth settings. Message when a device is disconnected -->
<string name="bluetooth_disconnected">Disconnected</string>
<!-- Bluetooth settings. Message when disconnecting from a device -->
@@ -108,8 +111,10 @@
<string name="bluetooth_profile_pbap_summary">Use for contact sharing</string>
<!-- Bluetooth settings. The user-visible string that is used whenever referring to the PAN profile (sharing this device's Internet connection). [CHAR LIMIT=40] -->
<string name="bluetooth_profile_pan_nap">Internet connection sharing</string>
- <!-- Bluetooth settings. The user-visible string that is used whenever referring to the map profile. -->
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the map profile. -->
<string name="bluetooth_profile_map">Message Access</string>
+ <!-- Bluetooth settings. The user-visible string that is used whenever referring to the SAP profile (sharing SIM card). -->
+ <string name="bluetooth_profile_sap">SIM Access</string>
<!-- Bluetooth settings. Connection options screen. The summary for the A2DP checkbox preference when A2DP is connected. -->
<string name="bluetooth_a2dp_profile_summary_connected">Connected to media audio</string>
@@ -119,6 +124,8 @@
<string name="bluetooth_opp_profile_summary_connected">Connected to file transfer server</string>
<!-- Bluetooth settings. Connection options screen. The summary for the map checkbox preference when map is connected. -->
<string name="bluetooth_map_profile_summary_connected">Connected to map</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the sap checkbox preference when SAP is connected. -->
+ <string name="bluetooth_sap_profile_summary_connected">Connected to SAP</string>
<!-- Bluetooth settings. Connection options screen. The summary for the OPP checkbox preference when OPP is not connected. -->
<string name="bluetooth_opp_profile_summary_not_connected">Not connected to file transfer server</string>
<!-- Bluetooth settings. Connection options screen. The summary for the HID checkbox preference when HID is connected. -->
@@ -134,6 +141,8 @@
<string name="bluetooth_pan_profile_summary_use_for">Use for Internet access</string>
<!-- Bluetooth settings. Connection options screen. The summary for the map checkbox preference that describes how checking it will set the map profile as preferred. -->
<string name="bluetooth_map_profile_summary_use_for">Use for map</string>
+ <!-- Bluetooth settings. Connection options screen. The summary for the sap checkbox preference that describes how checking it will set the sap profile as preferred. -->
+ <string name="bluetooth_sap_profile_summary_use_for">Use for SIM access</string>
<!-- Bluetooth settings. Connection options screen. The summary for the A2DP checkbox preference that describes how checking it will set the A2DP profile as preferred. -->
<string name="bluetooth_a2dp_profile_summary_use_for">Use for media audio</string>
<!-- Bluetooth settings. Connection options screen. The summary for the headset checkbox preference that describes how checking it will set the headset profile as preferred. -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index dd2368f..7534b8e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -67,10 +67,6 @@ public final class CachedBluetoothDevice implements Comparable<CachedBluetoothDe
private boolean mVisible;
- private int mPhonebookPermissionChoice;
-
- private int mMessagePermissionChoice;
-
private int mMessageRejectionCount;
private final Collection<Callback> mCallbacks = new ArrayList<Callback>();
@@ -556,6 +552,7 @@ public final class CachedBluetoothDevice implements Comparable<CachedBluetoothDe
mConnectAfterPairing = false; // cancel auto-connect
setPhonebookPermissionChoice(ACCESS_UNKNOWN);
setMessagePermissionChoice(ACCESS_UNKNOWN);
+ setSimPermissionChoice(ACCESS_UNKNOWN);
mMessageRejectionCount = 0;
saveMessageRejectionCount();
}
@@ -732,6 +729,26 @@ public final class CachedBluetoothDevice implements Comparable<CachedBluetoothDe
mDevice.setMessageAccessPermission(permission);
}
+ public int getSimPermissionChoice() {
+ int permission = mDevice.getSimAccessPermission();
+ if (permission == BluetoothDevice.ACCESS_ALLOWED) {
+ return ACCESS_ALLOWED;
+ } else if (permission == BluetoothDevice.ACCESS_REJECTED) {
+ return ACCESS_REJECTED;
+ }
+ return ACCESS_UNKNOWN;
+ }
+
+ void setSimPermissionChoice(int permissionChoice) {
+ int permission = BluetoothDevice.ACCESS_UNKNOWN;
+ if (permissionChoice == ACCESS_ALLOWED) {
+ permission = BluetoothDevice.ACCESS_ALLOWED;
+ } else if (permissionChoice == ACCESS_REJECTED) {
+ permission = BluetoothDevice.ACCESS_REJECTED;
+ }
+ mDevice.setSimAccessPermission(permission);
+ }
+
// Migrates data from old data store (in Settings app's shared preferences) to new (in Bluetooth
// app's shared preferences).
private void migrateMessagePermissionChoice() {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
new file mode 100644
index 0000000..25c53e6
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/SapProfile.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.bluetooth;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSap;
+import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothUuid;
+import android.content.Context;
+import android.os.ParcelUuid;
+import android.util.Log;
+
+import com.android.settingslib.R;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * SapProfile handles Bluetooth SAP profile.
+ */
+final class SapProfile implements LocalBluetoothProfile {
+ private static final String TAG = "SapProfile";
+ private static boolean V = true;
+
+ private BluetoothSap mService;
+ private boolean mIsProfileReady;
+
+ private final LocalBluetoothAdapter mLocalAdapter;
+ private final CachedBluetoothDeviceManager mDeviceManager;
+ private final LocalBluetoothProfileManager mProfileManager;
+
+ static final ParcelUuid[] UUIDS = {
+ BluetoothUuid.SAP,
+ };
+
+ static final String NAME = "SAP";
+
+ // Order of this profile in device profiles list
+ private static final int ORDINAL = 10;
+
+ // These callbacks run on the main thread.
+ private final class SapServiceListener
+ implements BluetoothProfile.ServiceListener {
+
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (V) Log.d(TAG,"Bluetooth service connected");
+ mService = (BluetoothSap) proxy;
+ // We just bound to the service, so refresh the UI for any connected SAP devices.
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ while (!deviceList.isEmpty()) {
+ BluetoothDevice nextDevice = deviceList.remove(0);
+ CachedBluetoothDevice device = mDeviceManager.findDevice(nextDevice);
+ // we may add a new device here, but generally this should not happen
+ if (device == null) {
+ Log.w(TAG, "SapProfile found new device: " + nextDevice);
+ device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);
+ }
+ device.onProfileStateChanged(SapProfile.this,
+ BluetoothProfile.STATE_CONNECTED);
+ device.refresh();
+ }
+
+ mProfileManager.callServiceConnectedListeners();
+ mIsProfileReady=true;
+ }
+
+ public void onServiceDisconnected(int profile) {
+ if (V) Log.d(TAG,"Bluetooth service disconnected");
+ mProfileManager.callServiceDisconnectedListeners();
+ mIsProfileReady=false;
+ }
+ }
+
+ public boolean isProfileReady() {
+ return mIsProfileReady;
+ }
+
+ SapProfile(Context context, LocalBluetoothAdapter adapter,
+ CachedBluetoothDeviceManager deviceManager,
+ LocalBluetoothProfileManager profileManager) {
+ mLocalAdapter = adapter;
+ mDeviceManager = deviceManager;
+ mProfileManager = profileManager;
+ mLocalAdapter.getProfileProxy(context, new SapServiceListener(),
+ BluetoothProfile.SAP);
+ }
+
+ public boolean isConnectable() {
+ return true;
+ }
+
+ public boolean isAutoConnectable() {
+ return true;
+ }
+
+ public boolean connect(BluetoothDevice device) {
+ if (mService == null) return false;
+ List<BluetoothDevice> sinks = mService.getConnectedDevices();
+ if (sinks != null) {
+ for (BluetoothDevice sink : sinks) {
+ mService.disconnect(sink);
+ }
+ }
+ return mService.connect(device);
+ }
+
+ public boolean disconnect(BluetoothDevice device) {
+ if (mService == null) return false;
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+ if (!deviceList.isEmpty() && deviceList.get(0).equals(device)) {
+ if (mService.getPriority(device) > BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ return mService.disconnect(device);
+ } else {
+ return false;
+ }
+ }
+
+ public int getConnectionStatus(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.STATE_DISCONNECTED;
+ List<BluetoothDevice> deviceList = mService.getConnectedDevices();
+
+ return !deviceList.isEmpty() && deviceList.get(0).equals(device)
+ ? mService.getConnectionState(device)
+ : BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ public boolean isPreferred(BluetoothDevice device) {
+ if (mService == null) return false;
+ return mService.getPriority(device) > BluetoothProfile.PRIORITY_OFF;
+ }
+
+ public int getPreferred(BluetoothDevice device) {
+ if (mService == null) return BluetoothProfile.PRIORITY_OFF;
+ return mService.getPriority(device);
+ }
+
+ public void setPreferred(BluetoothDevice device, boolean preferred) {
+ if (mService == null) return;
+ if (preferred) {
+ if (mService.getPriority(device) < BluetoothProfile.PRIORITY_ON) {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_ON);
+ }
+ } else {
+ mService.setPriority(device, BluetoothProfile.PRIORITY_OFF);
+ }
+ }
+
+ public List<BluetoothDevice> getConnectedDevices() {
+ if (mService == null) return new ArrayList<BluetoothDevice>(0);
+ return mService.getDevicesMatchingConnectionStates(
+ new int[] {BluetoothProfile.STATE_CONNECTED,
+ BluetoothProfile.STATE_CONNECTING,
+ BluetoothProfile.STATE_DISCONNECTING});
+ }
+
+ public String toString() {
+ return NAME;
+ }
+
+ public int getOrdinal() {
+ return ORDINAL;
+ }
+
+ public int getNameResource(BluetoothDevice device) {
+ return R.string.bluetooth_profile_sap;
+ }
+
+ public int getSummaryResourceForDevice(BluetoothDevice device) {
+ int state = getConnectionStatus(device);
+ switch (state) {
+ case BluetoothProfile.STATE_DISCONNECTED:
+ return R.string.bluetooth_sap_profile_summary_use_for;
+
+ case BluetoothProfile.STATE_CONNECTED:
+ return R.string.bluetooth_sap_profile_summary_connected;
+
+ default:
+ return Utils.getConnectionStateSummary(state);
+ }
+ }
+
+ public int getDrawableResource(BluetoothClass btClass) {
+ return R.drawable.ic_bt_cellphone;
+ }
+
+ protected void finalize() {
+ if (V) Log.d(TAG, "finalize()");
+ if (mService != null) {
+ try {
+ BluetoothAdapter.getDefaultAdapter().closeProfileProxy(BluetoothProfile.SAP,
+ mService);
+ mService = null;
+ }catch (Throwable t) {
+ Log.w(TAG, "Error cleaning up SAP proxy", t);
+ }
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
index 1cf7248..c81f22a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
+++ b/packages/SettingsLib/src/com/android/settingslib/deviceinfo/StorageMeasurement.java
@@ -32,7 +32,6 @@ import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageVolume;
@@ -349,6 +348,11 @@ public class StorageMeasurement {
final Message finished = mMeasurementHandler.obtainMessage(MeasurementHandler.MSG_COMPLETED,
details);
+ if (mVolume == null || !mVolume.isMountedReadable()) {
+ finished.sendToTarget();
+ return;
+ }
+
if (mSharedVolume != null && mSharedVolume.isMountedReadable()) {
final File basePath = mSharedVolume.getPathForUser(currentUser);
@@ -375,8 +379,10 @@ public class StorageMeasurement {
}
final File file = mVolume.getPath();
- details.totalSize = file.getTotalSpace();
- details.availSize = file.getFreeSpace();
+ if (file != null) {
+ details.totalSize = file.getTotalSpace();
+ details.availSize = file.getFreeSpace();
+ }
// Measure all apps hosted on this volume for all users
if (mVolume.getType() == VolumeInfo.TYPE_PRIVATE) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 2fde4f9..53e69e3 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -17,9 +17,13 @@
package com.android.settingslib.wifi;
import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkInfo.State;
+import android.net.wifi.IWifiManager;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiConfiguration.KeyMgmt;
@@ -27,6 +31,8 @@ import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.text.TextUtils;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.util.Log;
import android.util.LruCache;
@@ -700,6 +706,25 @@ public class AccessPoint implements Comparable<AccessPoint> {
}
}
+ // Case when there is wifi connected without internet connectivity.
+ final ConnectivityManager cm = (ConnectivityManager)
+ context.getSystemService(Context.CONNECTIVITY_SERVICE);
+ if (state == DetailedState.CONNECTED) {
+ IWifiManager wifiManager = IWifiManager.Stub.asInterface(
+ ServiceManager.getService(Context.WIFI_SERVICE));
+ Network nw;
+
+ try {
+ nw = wifiManager.getCurrentNetwork();
+ } catch (RemoteException e) {
+ nw = null;
+ }
+ NetworkCapabilities nc = cm.getNetworkCapabilities(nw);
+ if (nc != null && !nc.hasCapability(nc.NET_CAPABILITY_VALIDATED)) {
+ return context.getString(R.string.wifi_connected_no_internet);
+ }
+ }
+
String[] formats = context.getResources().getStringArray((ssid == null)
? R.array.wifi_status : R.array.wifi_status_with_ssid);
int index = state.ordinal();
diff --git a/packages/SettingsProvider/res/values-sq-rAL/defaults.xml b/packages/SettingsProvider/res/values-sq-rAL/defaults.xml
new file mode 100644
index 0000000..22443a5
--- /dev/null
+++ b/packages/SettingsProvider/res/values-sq-rAL/defaults.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/**
+ * Copyright (c) 2009, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ -->
+
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="def_device_name" msgid="6309317409634339402">"%1$s %2$s"</string>
+ <string name="def_device_name_simple" msgid="9037785625140748221">"%1$s"</string>
+</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index fee2593..723a4d4 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -362,20 +362,13 @@
<string name="monitoring_title" msgid="169206259253048106">"ਨੈਟਵਰਕ ਨਿਰੀਖਣ ਕਰ ਰਿਹਾ ਹੈ"</string>
<string name="disable_vpn" msgid="4435534311510272506">"VPN ਨੂੰ ਅਸਮਰੱਥ ਬਣਾਓ"</string>
<string name="disconnect_vpn" msgid="1324915059568548655">"VPN ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
- <!-- no translation found for monitoring_description_device_owned (5780988291898461883) -->
- <skip />
- <!-- no translation found for monitoring_description_profile_owned (8110044290898637925) -->
- <skip />
- <!-- no translation found for monitoring_description_device_and_profile_owned (1664428184778531249) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn (912328761766161919) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_device_owned (3090670777499161246) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_profile_owned (2224494839524715272) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_device_and_profile_owned (2198546817407897093) -->
- <skip />
+ <string name="monitoring_description_device_owned" msgid="5780988291898461883">"ਤੁਹਾਡੀ ਡਿਵਾਈਸ <xliff:g id="ORGANIZATION">%1$s</xliff:g> ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਬੰਧਕ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਸ, ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਨਾਲ ਸੰਬੰਧਿਤ ਡਾਟਾ ਅਤੇ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਦੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਜਾਣਕਾਰੀ ਦਾ ਨਿਰੀਖਣ ਅਤੇ ਉਸਨੂੰ ਵਿਵਸਥਿਤ ਕਰ ਸਕਦਾ ਹੈ। ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+ <string name="monitoring_description_profile_owned" msgid="8110044290898637925">"ਤੁਹਾਡੀ ਕੰਮ ਪ੍ਰੋਫਾਈਲ <xliff:g id="ORGANIZATION">%1$s</xliff:g>ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਬੰਧਕ ਤੁਹਾਡੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੈ, ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈਬਸਾਈਟਾਂ ਸਮੇਤ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣਾ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+ <string name="monitoring_description_device_and_profile_owned" msgid="1664428184778531249">"ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਇਸ ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>.\nਤੁਹਾਡੀ ਕੰਮਪ੍ਰੋਫਾਈਲ ਇਸ ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>.\n\nਤੁਹਾਡਾ ਪ੍ਰਬੰਧਕ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਅਤੇ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ ਜਿਸ ਵਿੱਚ ਸ਼ਾਮਲ ਹਨ ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈਬਸਾਈਟਾਂ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+ <string name="monitoring_description_vpn" msgid="912328761766161919">"ਤੁਸੀਂ ਇੱਕ ਐਪ ਨੂੰ ਇੱਕ VPN ਕਨੈਕਸ਼ਨ ਸੈਟ ਅਪ ਕਰਨ ਦੀ ਅਨੁਮਤੀ ਦਿੱਤੀ ਹੈ।\n\nਇਹ ਐਪ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਅਤੇ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ, ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈਬਸਾਈਟਾਂ ਸਮੇਤ।"</string>
+ <string name="monitoring_description_vpn_device_owned" msgid="3090670777499161246">"ਤੁਹਾਡੀ ਡਿਵਾਈਸ <xliff:g id="ORGANIZATION">%1$s</xliff:g>ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।\n\nਪ੍ਰਬੰਧਕ ਸੈਟਿੰਗਾਂ, ਕਾਰਪੋਰੇਟ ਪਹੁੰਚ, ਐਪਸ, ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਨਾਲ ਸੰਬੰਧਿਤ ਡਾਟਾ ਅਤੇ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਦੀ ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਜਾਣਕਾਰੀ ਦਾ ਨਿਰੀਖਣ ਅਤੇ ਉਸਨੂੰ ਵਿਵਸਥਿਤ ਕਰ ਸਕਦਾ ਹੈ।\n\nਤੁਸੀਂ ਇੱਕ VPN ਨਾਲ ਵੀ ਕਨੈਕਟ ਕੀਤਾ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਨਿੱਜੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ, ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਵੈਬਸਾਈਟਾਂ ਸਮੇਤ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।"</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="2224494839524715272">"ਤੁਹਾਡੀ ਕੰਮ ਪ੍ਰੋਫਾਈਲ <xliff:g id="ORGANIZATION">%1$s</xliff:g>ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।\n\nਤੁਹਾਡਾ ਪ੍ਰਬੰਧਕ ਤੁਹਾਡੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੈ, ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈਬਸਾਈਟਾਂ ਸਮੇਤ।\n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣਾ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।\n\nਤੁਸੀਂ ਇੱਕ VPN ਨਾਲ ਵੀ ਕਨੈਕਟ ਕੀਤਾ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ।"</string>
+ <string name="monitoring_description_vpn_device_and_profile_owned" msgid="2198546817407897093">"ਤੁਹਾਡੀ ਡਿਵਾਈਸ <xliff:g id="ORGANIZATION_0">%1$s</xliff:g>ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ।\nਤੁਹਾਡੀ ਕੰਮ ਪ੍ਰੋਫਾਈਲ ਇਸ ਵੱਲੋਂ ਵਿਵਸਥਿਤ ਕੀਤੀ ਜਾਂਦੀ ਹੈ:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>.\n\nਤੁਹਾਡਾ ਪ੍ਰਬੰਧਕ ਤੁਹਾਡੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰਨ ਵਿੱਚ ਸਮਰੱਥ ਹੈ ਜਿਸ ਵਿੱਚ ਸ਼ਾਮਲ ਹਨ ਈਮੇਲਾਂ, ਐਪਸ ਅਤੇ ਸੁਰੱਖਿਅਤ ਵੈਬਸਾਈਟਾਂ। \n\nਹੋਰ ਜਾਣਕਾਰੀ ਲਈ, ਆਪਣੇ ਪ੍ਰਬੰਧਕ ਨੂੰ ਸੰਪਰਕ ਕਰੋ।\n\nਤੁਸੀਂ ਇੱਕ VPN ਨਾਲ ਵੀ ਕਨੈਕਟ ਕੀਤਾ ਹੈ, ਜੋ ਤੁਹਾਡੀ ਨਿੱਜੀ ਨੈਟਵਰਕ ਗਤੀਵਿਧੀ ਦਾ ਨਿਰੀਖਣ ਕਰ ਸਕਦਾ ਹੈ"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"ਡਿਵਾਈਸ ਲੌਕ ਰਹੇਗੀ ਜਦੋਂ ਤੱਕ ਤੁਸੀਂ ਮੈਨੂਅਲੀ ਅਨਲੌਕ ਨਹੀਂ ਕਰਦੇ"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"ਤੇਜ਼ੀ ਨਾਲ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਕਰੋ"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"ਅਨਲੌਕ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ ਉਹਨਾਂ ਨੂੰ ਦੇਖੋ"</string>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index e70254c..38fdcfd 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -179,12 +179,12 @@
<string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"Modaliteti \"në aeroplan\" është i aktivizuar."</string>
<string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Modaliteti \"në aeroplan\" është i çaktivizuar."</string>
<string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Modaliteti \"në aeroplan\" është i aktivizuar."</string>
- <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\"Mos shqetëso\" i aktivizuar, vetëm me prioritet."</string>
- <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\"Mos shqetëso\" i aktivizuar, asnjë ndërprerje."</string>
- <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"\"Mos shqetëso\" i aktivizuar, vetëm alarmet."</string>
- <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\"Mos shqetëso\" i çaktivizuar."</string>
- <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Mos shqetëso\" i çaktivizuar."</string>
- <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Mos shqetëso\" i aktivizuar."</string>
+ <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"\"Mos shqetëso\" është i aktivizuar, vetëm me prioritet."</string>
+ <string name="accessibility_quick_settings_dnd_none_on" msgid="5910777408232088752">"\"Mos shqetëso\" është i aktivizuar, asnjë ndërprerje."</string>
+ <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"\"Mos shqetëso\" është i aktivizuar, vetëm alarmet."</string>
+ <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"\"Mos shqetëso\" është i çaktivizuar."</string>
+ <string name="accessibility_quick_settings_dnd_changed_off" msgid="898107593453022935">"\"Mos shqetëso\" është i çaktivizuar."</string>
+ <string name="accessibility_quick_settings_dnd_changed_on" msgid="4483780856613561039">"\"Mos shqetëso\" është i aktivizuar."</string>
<string name="accessibility_quick_settings_bluetooth_off" msgid="2133631372372064339">"\"Bluetooth-i\" është i çaktivizuar."</string>
<string name="accessibility_quick_settings_bluetooth_on" msgid="7681999166216621838">"\"Bluetooth-i\" është i aktivizuar."</string>
<string name="accessibility_quick_settings_bluetooth_connecting" msgid="6953242966685343855">"\"Bluetooth-i\" po lidhet."</string>
@@ -362,20 +362,13 @@
<string name="monitoring_title" msgid="169206259253048106">"Monitorimi i rrjetit"</string>
<string name="disable_vpn" msgid="4435534311510272506">"Çaktivizo VPN-në"</string>
<string name="disconnect_vpn" msgid="1324915059568548655">"Shkëput VPN-në"</string>
- <!-- no translation found for monitoring_description_device_owned (5780988291898461883) -->
- <skip />
- <!-- no translation found for monitoring_description_profile_owned (8110044290898637925) -->
- <skip />
- <!-- no translation found for monitoring_description_device_and_profile_owned (1664428184778531249) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn (912328761766161919) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_device_owned (3090670777499161246) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_profile_owned (2224494839524715272) -->
- <skip />
- <!-- no translation found for monitoring_description_vpn_device_and_profile_owned (2198546817407897093) -->
- <skip />
+ <string name="monitoring_description_device_owned" msgid="5780988291898461883">"Pajisja jote menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratori yt mund të monitorojë dhe të menaxhojë cilësimet, qasjen e korporatës, aplikacionet, të dhënat e lidhura me pajisjen tënde, si dhe informacionet e vendndodhjes së pajisjes tënde. Për më shumë informacione, kontakto me administratorin tënd."</string>
+ <string name="monitoring_description_profile_owned" msgid="8110044290898637925">"Profili yt i punës menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratori yt mund të monitorojë aktivitetin e rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e sigurta të uebit.\n\nPër më shumë informacione, kontakto me administratorin tënd."</string>
+ <string name="monitoring_description_device_and_profile_owned" msgid="1664428184778531249">"Pajisja jote menaxhohet nga:\n<xliff:g id="ORGANIZATION_0">%1$s</xliff:g>.\nProfili yt i punës menaxhohet nga:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>.\n\nAdministratori yt mund të monitorojë pajisjen tënde dhe aktivitetin e rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e sigurta të uebit.\n\nPër më shumë informacione, kontakto me administratorin."</string>
+ <string name="monitoring_description_vpn" msgid="912328761766161919">"I dhe leje një aplikacioni që të konfigurojë një lidhje VPN.\n\nKy aplikacion mund të monitorojë pajisjen tënde dhe aktivitetin e rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e sigurta të uebit."</string>
+ <string name="monitoring_description_vpn_device_owned" msgid="3090670777499161246">"Pajisja jote menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratori yt mund të monitorojë dhe të menaxhojë cilësimet, qasjen e korporatës, aplikacionet, të dhënat e lidhura me pajisjen dhe informacionet e vendndodhjes së pajisjes.\n\nJe i lidhur me një rrjet VPN që mund të monitorojë aktivitetin tënd të rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e uebit.\n\nPër më shumë informacione, kontakto me administratorin."</string>
+ <string name="monitoring_description_vpn_profile_owned" msgid="2224494839524715272">"Profili yt i punës menaxhohet nga <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nAdministratori yt mund të monitorojë aktivitetin tënd të rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e sigurta të uebit.\n\nPër më shumë informacione, kontakto me administratorin tënd.\n\nJe i lidhur po ashtu me një rrjet VPN që mund të monitorojë aktivitetin tënd të rrjetit."</string>
+ <string name="monitoring_description_vpn_device_and_profile_owned" msgid="2198546817407897093">"Pajisja jote menaxhohet nga <xliff:g id="ORGANIZATION_0">%1$s</xliff:g>.\nProfili yt i punës menaxhohet nga:\n<xliff:g id="ORGANIZATION_1">%2$s</xliff:g>.\n\nAdministratori yt mund të monitorojë aktivitetin tënd të rrjetit, duke përfshirë emailet, aplikacionet dhe sajtet e sigurta të uebit.\n\nPër më shumë informacione, kontakto me administratorin tënd.\n\nJe i lidhur po ashtu me një rrjet VPN që mund të monitorojë aktivitetin e rrjetit tënd personal"</string>
<string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Pajisje do të qëndrojë e kyçur derisa ta shkyçësh manualisht"</string>
<string name="hidden_notifications_title" msgid="7139628534207443290">"Merr njoftime më shpejt"</string>
<string name="hidden_notifications_text" msgid="2326409389088668981">"Shikoji para se t\'i shkyçësh"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 26c3b4e..588ec26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -238,6 +238,8 @@ public abstract class BaseStatusBar extends SystemUI implements
protected DismissView mDismissView;
protected EmptyShadeView mEmptyShadeView;
+ private NotificationClicker mNotificationClicker = new NotificationClicker();
+
@Override // NotificationData.Environment
public boolean isDeviceProvisioned() {
return mDeviceProvisioned;
@@ -1292,13 +1294,7 @@ public abstract class BaseStatusBar extends SystemUI implements
row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
}
- PendingIntent contentIntent = sbn.getNotification().contentIntent;
- if (contentIntent != null) {
- final View.OnClickListener listener = makeClicker(contentIntent, sbn.getKey());
- row.setOnClickListener(listener);
- } else {
- row.setOnClickListener(null);
- }
+ mNotificationClicker.register(row, sbn);
// set up the adaptive layout
View contentViewLocal = null;
@@ -1559,35 +1555,38 @@ public abstract class BaseStatusBar extends SystemUI implements
}
}
- public NotificationClicker makeClicker(PendingIntent intent, String notificationKey) {
- return new NotificationClicker(intent, notificationKey);
- }
+ private final class NotificationClicker implements View.OnClickListener {
+ public void onClick(final View v) {
+ if (!(v instanceof ExpandableNotificationRow)) {
+ Log.e(TAG, "NotificationClicker called on a view that is not a notification row.");
+ return;
+ }
- protected class NotificationClicker implements View.OnClickListener {
- private PendingIntent mIntent;
- private final String mNotificationKey;
+ final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+ final StatusBarNotification sbn = row.getStatusBarNotification();
+ if (sbn == null) {
+ Log.e(TAG, "NotificationClicker called on an unclickable notification,");
+ return;
+ }
- public NotificationClicker(PendingIntent intent, String notificationKey) {
- mIntent = intent;
- mNotificationKey = notificationKey;
- }
+ final PendingIntent intent = sbn.getNotification().contentIntent;
+ final String notificationKey = sbn.getKey();
- public void onClick(final View v) {
if (NOTIFICATION_CLICK_DEBUG) {
- Log.d(TAG, "Clicked on content of " + mNotificationKey);
+ Log.d(TAG, "Clicked on content of " + notificationKey);
}
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
- final boolean afterKeyguardGone = mIntent.isActivity()
- && PreviewInflater.wouldLaunchResolverActivity(mContext, mIntent.getIntent(),
+ final boolean afterKeyguardGone = intent.isActivity()
+ && PreviewInflater.wouldLaunchResolverActivity(mContext, intent.getIntent(),
mCurrentUserId);
dismissKeyguardThenExecute(new OnDismissAction() {
public boolean onDismiss() {
- if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(mNotificationKey)) {
+ if (mHeadsUpManager != null && mHeadsUpManager.isHeadsUp(notificationKey)) {
// Release the HUN notification to the shade.
//
// In most cases, when FLAG_AUTO_CANCEL is set, the notification will
// become canceled shortly by NoMan, but we can't assume that.
- mHeadsUpManager.releaseImmediately(mNotificationKey);
+ mHeadsUpManager.releaseImmediately(notificationKey);
}
new Thread() {
@Override
@@ -1606,9 +1605,9 @@ public abstract class BaseStatusBar extends SystemUI implements
} catch (RemoteException e) {
}
- if (mIntent != null) {
+ if (intent != null) {
try {
- mIntent.send();
+ intent.send();
} catch (PendingIntent.CanceledException e) {
// the stack trace isn't very helpful here.
// Just log the exception message.
@@ -1616,14 +1615,14 @@ public abstract class BaseStatusBar extends SystemUI implements
// TODO: Dismiss Keyguard.
}
- if (mIntent.isActivity()) {
+ if (intent.isActivity()) {
overrideActivityPendingAppTransition(keyguardShowing
&& !afterKeyguardGone);
}
}
try {
- mBarService.onNotificationClick(mNotificationKey);
+ mBarService.onNotificationClick(notificationKey);
} catch (RemoteException ex) {
// system process is dead if we're here.
}
@@ -1635,10 +1634,19 @@ public abstract class BaseStatusBar extends SystemUI implements
true /* force */, true /* delayed */);
visibilityChanged(false);
- return mIntent != null && mIntent.isActivity();
+ return intent != null && intent.isActivity();
}
}, afterKeyguardGone);
}
+
+ public void register(ExpandableNotificationRow row, StatusBarNotification sbn) {
+ final PendingIntent contentIntent = sbn.getNotification().contentIntent;
+ if (contentIntent != null) {
+ row.setOnClickListener(this);
+ } else {
+ row.setOnClickListener(null);
+ }
+ }
}
public void animateCollapsePanels(int flags, boolean force) {
@@ -2037,13 +2045,8 @@ public abstract class BaseStatusBar extends SystemUI implements
publicContentView.reapply(mContext, entry.getPublicContentView(), mOnClickHandler);
}
// update the contentIntent
- final PendingIntent contentIntent = notification.getNotification().contentIntent;
- if (contentIntent != null) {
- final View.OnClickListener listener = makeClicker(contentIntent, notification.getKey());
- entry.row.setOnClickListener(listener);
- } else {
- entry.row.setOnClickListener(null);
- }
+ mNotificationClicker.register(entry.row, notification);
+
entry.row.setStatusBarNotification(notification);
entry.row.notifyContentUpdated();
entry.row.resetHeight();