summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt30
-rw-r--r--api/system-current.txt36
-rw-r--r--core/java/android/accounts/AbstractAccountAuthenticator.java61
-rw-r--r--core/java/android/app/Activity.java25
-rw-r--r--core/java/android/app/ApplicationPackageManager.java10
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java504
-rw-r--r--core/java/android/app/usage/IUsageStatsManager.aidl1
-rw-r--r--core/java/android/app/usage/UsageStatsManager.java22
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java26
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl3
-rw-r--r--core/java/android/content/pm/PackageManager.java13
-rw-r--r--core/java/android/content/res/TypedArray.java23
-rw-r--r--core/java/android/os/IDeviceIdleController.aidl4
-rw-r--r--core/java/android/os/PowerManager.java8
-rw-r--r--core/java/android/os/PowerManagerInternal.java2
-rw-r--r--core/java/android/provider/ContactsContract.java15
-rw-r--r--core/java/android/provider/MediaStore.java40
-rw-r--r--core/java/android/service/media/CameraPrewarmService.java96
-rw-r--r--core/java/android/view/View.java6
-rw-r--r--core/java/android/view/WindowManager.java1
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java8
-rw-r--r--core/res/AndroidManifest.xml7
-rwxr-xr-xcore/res/res/values/symbols.xml5
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java13
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java115
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java38
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java201
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java203
-rw-r--r--services/core/java/com/android/server/accounts/TokenCache.java163
-rwxr-xr-xservices/core/java/com/android/server/am/ActiveServices.java2
-rw-r--r--services/core/java/com/android/server/camera/CameraService.java63
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java46
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java42
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java16
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java19
-rw-r--r--services/core/java/com/android/server/power/ShutdownThread.java2
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java1
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java25
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java4
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java22
-rw-r--r--telephony/java/android/telephony/PhoneNumberUtils.java18
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java7
-rw-r--r--test-runner/src/android/test/mock/MockPackageManager.java6
-rw-r--r--tests/CameraPrewarmTest/AndroidManifest.xml23
-rw-r--r--tests/CameraPrewarmTest/res/values/strings.xml2
-rw-r--r--tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java2
-rw-r--r--tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmService.java (renamed from tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java)20
-rw-r--r--tools/aapt/Bundle.h4
-rw-r--r--tools/aapt/Main.cpp5
-rw-r--r--tools/aapt/Resource.cpp2
-rw-r--r--tools/aapt/ResourceTable.cpp35
-rw-r--r--tools/aapt/ResourceTable.h6
65 files changed, 1665 insertions, 562 deletions
diff --git a/api/current.txt b/api/current.txt
index d38e75a642f7..85414953f8e0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2716,6 +2716,7 @@ package android.accounts {
method public final android.os.IBinder getIBinder();
method public abstract android.os.Bundle hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[]) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+ field public static final java.lang.String KEY_CUSTOM_TOKEN_EXPIRY = "android.accounts.expiry";
}
public class Account implements android.os.Parcelable {
@@ -3512,6 +3513,7 @@ package android.app {
method public deprecated void setTitleColor(int);
method public void setVisible(boolean);
method public final void setVolumeControlStream(int);
+ method public boolean shouldShowRequestPermissionRationale(java.lang.String);
method public boolean shouldUpRecreateTask(android.content.Intent);
method public final deprecated void showDialog(int);
method public final deprecated boolean showDialog(int, android.os.Bundle);
@@ -5802,6 +5804,7 @@ package android.app.admin {
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
+ field public static final java.lang.String ACTION_PROVISION_MANAGED_DEVICE = "android.app.action.PROVISION_MANAGED_DEVICE";
field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
field public static final java.lang.String ACTION_START_ENCRYPTION = "android.app.action.START_ENCRYPTION";
@@ -25840,6 +25843,15 @@ package android.provider {
field public static final android.net.Uri CONTENT_URI;
}
+ public static final class ContactsContract.ProviderStatus {
+ field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/provider_status";
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String STATUS = "status";
+ field public static final int STATUS_BUSY = 1; // 0x1
+ field public static final int STATUS_EMPTY = 2; // 0x2
+ field public static final int STATUS_NORMAL = 0; // 0x0
+ }
+
public static final class ContactsContract.QuickContact {
ctor public ContactsContract.QuickContact();
method public static void showQuickContact(android.content.Context, android.view.View, android.net.Uri, int, java.lang.String[]);
@@ -26131,8 +26143,6 @@ package android.provider {
method public static java.lang.String getVersion(android.content.Context);
field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
- field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_COOLDOWN = "android.media.action.STILL_IMAGE_CAMERA_COOLDOWN";
- field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM";
field public static final java.lang.String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
field public static final java.lang.String AUTHORITY = "media";
field public static final java.lang.String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
@@ -26160,6 +26170,7 @@ package android.provider {
field public static final java.lang.String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH = "android.media.action.VIDEO_PLAY_FROM_SEARCH";
field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia";
field public static final java.lang.String MEDIA_SCANNER_VOLUME = "volume";
+ field public static final java.lang.String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE = "android.media.still_image_camera_preview_service";
field public static final java.lang.String UNKNOWN_STRING = "<unknown>";
}
@@ -28718,6 +28729,13 @@ package android.service.dreams {
package android.service.media {
+ public abstract class CameraPrewarmService extends android.app.Service {
+ ctor public CameraPrewarmService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public abstract void onCooldown(boolean);
+ method public abstract void onPrewarm();
+ }
+
public abstract class MediaBrowserService extends android.app.Service {
ctor public MediaBrowserService();
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
@@ -30829,12 +30847,14 @@ package android.telephony {
public class PhoneNumberUtils {
ctor public PhoneNumberUtils();
- method public static void addPhoneTtsSpan(android.text.Spannable, int, int);
+ method public static void addTtsSpan(android.text.Spannable, int, int);
method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
method public static java.lang.String calledPartyBCDToString(byte[], int, int);
method public static boolean compare(java.lang.String, java.lang.String);
method public static boolean compare(android.content.Context, java.lang.String, java.lang.String);
method public static java.lang.String convertKeypadLettersToDigits(java.lang.String);
+ method public static android.text.style.TtsSpan createTtsSpan(java.lang.String);
+ method public static java.lang.CharSequence createTtsSpannable(java.lang.CharSequence);
method public static java.lang.String extractNetworkPortion(java.lang.String);
method public static java.lang.String extractPostDialPortion(java.lang.String);
method public static deprecated void formatJapaneseNumber(android.text.Editable);
@@ -30847,8 +30867,6 @@ package android.telephony {
method public static java.lang.String formatNumberToRFC3966(java.lang.String, java.lang.String);
method public static deprecated int getFormatTypeForLocale(java.util.Locale);
method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context);
- method public static android.text.style.TtsSpan getPhoneTtsSpan(java.lang.String);
- method public static java.lang.CharSequence getPhoneTtsSpannable(java.lang.CharSequence);
method public static java.lang.String getStrippedReversed(java.lang.String);
method public static final boolean is12Key(char);
method public static final boolean isDialable(char);
@@ -31155,7 +31173,6 @@ package android.telephony {
method public boolean setOperatorBrandOverride(java.lang.String);
method public boolean setPreferredNetworkTypeToGlobal();
method public boolean setVoiceMailNumber(java.lang.String, java.lang.String);
- field public static final java.lang.String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
field public static final int CALL_STATE_IDLE = 0; // 0x0
@@ -37390,7 +37407,6 @@ package android.view {
field public static final int TITLE_CHANGED = 64; // 0x40
field public static final int TYPE_ACCESSIBILITY_OVERLAY = 2032; // 0x7f0
field public static final int TYPE_APPLICATION = 2; // 0x2
- field public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = 1005; // 0x3ed
field public static final int TYPE_APPLICATION_ATTACHED_DIALOG = 1003; // 0x3eb
field public static final int TYPE_APPLICATION_MEDIA = 1001; // 0x3e9
field public static final int TYPE_APPLICATION_PANEL = 1000; // 0x3e8
diff --git a/api/system-current.txt b/api/system-current.txt
index 44d8c8ed7f14..fb7376ce036a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -71,6 +71,7 @@ package android {
field public static final java.lang.String CAPTURE_VIDEO_OUTPUT = "android.permission.CAPTURE_VIDEO_OUTPUT";
field public static final java.lang.String CHANGE_COMPONENT_ENABLED_STATE = "android.permission.CHANGE_COMPONENT_ENABLED_STATE";
field public static final java.lang.String CHANGE_CONFIGURATION = "android.permission.CHANGE_CONFIGURATION";
+ field public static final java.lang.String CHANGE_DEVICE_IDLE_TEMP_WHITELIST = "android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST";
field public static final java.lang.String CHANGE_NETWORK_STATE = "android.permission.CHANGE_NETWORK_STATE";
field public static final java.lang.String CHANGE_WIFI_MULTICAST_STATE = "android.permission.CHANGE_WIFI_MULTICAST_STATE";
field public static final java.lang.String CHANGE_WIFI_STATE = "android.permission.CHANGE_WIFI_STATE";
@@ -2797,6 +2798,7 @@ package android.accounts {
method public final android.os.IBinder getIBinder();
method public abstract android.os.Bundle hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[]) throws android.accounts.NetworkErrorException;
method public abstract android.os.Bundle updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+ field public static final java.lang.String KEY_CUSTOM_TOKEN_EXPIRY = "android.accounts.expiry";
}
public class Account implements android.os.Parcelable {
@@ -3597,6 +3599,7 @@ package android.app {
method public deprecated void setTitleColor(int);
method public void setVisible(boolean);
method public final void setVolumeControlStream(int);
+ method public boolean shouldShowRequestPermissionRationale(java.lang.String);
method public boolean shouldUpRecreateTask(android.content.Intent);
method public final deprecated void showDialog(int);
method public final deprecated boolean showDialog(int, android.os.Bundle);
@@ -5911,6 +5914,7 @@ package android.app.admin {
method public void wipeData(int);
field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
field public static final java.lang.String ACTION_MANAGED_PROFILE_PROVISIONED = "android.app.action.MANAGED_PROFILE_PROVISIONED";
+ field public static final java.lang.String ACTION_PROVISION_MANAGED_DEVICE = "android.app.action.PROVISION_MANAGED_DEVICE";
field public static final java.lang.String ACTION_PROVISION_MANAGED_PROFILE = "android.app.action.PROVISION_MANAGED_PROFILE";
field public static final java.lang.String ACTION_SEND_DEVICE_INITIALIZER_STATUS = "android.app.action.SEND_DEVICE_INITIALIZER_STATUS";
field public static final java.lang.String ACTION_SET_NEW_PASSWORD = "android.app.action.SET_NEW_PASSWORD";
@@ -6331,6 +6335,7 @@ package android.app.usage {
method public java.util.List<android.app.usage.ConfigurationStats> queryConfigurations(int, long, long);
method public android.app.usage.UsageEvents queryEvents(long, long);
method public java.util.List<android.app.usage.UsageStats> queryUsageStats(int, long, long);
+ method public void whitelistAppTemporarily(java.lang.String, long, android.os.UserHandle);
field public static final int INTERVAL_BEST = 4; // 0x4
field public static final int INTERVAL_DAILY = 0; // 0x0
field public static final int INTERVAL_MONTHLY = 2; // 0x2
@@ -6486,7 +6491,9 @@ package android.bluetooth {
method public static boolean checkBluetoothAddress(java.lang.String);
method public void closeProfileProxy(int, android.bluetooth.BluetoothProfile);
method public boolean disable();
+ method public boolean disableBLE();
method public boolean enable();
+ method public boolean enableBLE();
method public java.lang.String getAddress();
method public android.bluetooth.le.BluetoothLeAdvertiser getBluetoothLeAdvertiser();
method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
@@ -6502,6 +6509,7 @@ package android.bluetooth {
method public boolean isBleScanAlwaysAvailable();
method public boolean isDiscovering();
method public boolean isEnabled();
+ method public boolean isLeEnabled();
method public boolean isMultipleAdvertisementSupported();
method public boolean isOffloadedFilteringSupported();
method public boolean isOffloadedScanBatchingSupported();
@@ -6512,6 +6520,7 @@ package android.bluetooth {
method public deprecated boolean startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback);
method public deprecated boolean startLeScan(java.util.UUID[], android.bluetooth.BluetoothAdapter.LeScanCallback);
method public deprecated void stopLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback);
+ field public static final java.lang.String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
field public static final java.lang.String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
field public static final java.lang.String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
field public static final java.lang.String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
@@ -27763,6 +27772,15 @@ package android.provider {
field public static final android.net.Uri CONTENT_URI;
}
+ public static final class ContactsContract.ProviderStatus {
+ field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/provider_status";
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String STATUS = "status";
+ field public static final int STATUS_BUSY = 1; // 0x1
+ field public static final int STATUS_EMPTY = 2; // 0x2
+ field public static final int STATUS_NORMAL = 0; // 0x0
+ }
+
public static final class ContactsContract.QuickContact {
ctor public ContactsContract.QuickContact();
method public static void showQuickContact(android.content.Context, android.view.View, android.net.Uri, int, java.lang.String[]);
@@ -28054,8 +28072,6 @@ package android.provider {
method public static java.lang.String getVersion(android.content.Context);
field public static final java.lang.String ACTION_IMAGE_CAPTURE = "android.media.action.IMAGE_CAPTURE";
field public static final java.lang.String ACTION_IMAGE_CAPTURE_SECURE = "android.media.action.IMAGE_CAPTURE_SECURE";
- field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_COOLDOWN = "android.media.action.STILL_IMAGE_CAMERA_COOLDOWN";
- field public static final java.lang.String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM";
field public static final java.lang.String ACTION_VIDEO_CAPTURE = "android.media.action.VIDEO_CAPTURE";
field public static final java.lang.String AUTHORITY = "media";
field public static final java.lang.String EXTRA_DURATION_LIMIT = "android.intent.extra.durationLimit";
@@ -28083,6 +28099,7 @@ package android.provider {
field public static final java.lang.String INTENT_ACTION_VIDEO_PLAY_FROM_SEARCH = "android.media.action.VIDEO_PLAY_FROM_SEARCH";
field public static final java.lang.String MEDIA_IGNORE_FILENAME = ".nomedia";
field public static final java.lang.String MEDIA_SCANNER_VOLUME = "volume";
+ field public static final java.lang.String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE = "android.media.still_image_camera_preview_service";
field public static final java.lang.String UNKNOWN_STRING = "<unknown>";
}
@@ -30744,6 +30761,13 @@ package android.service.dreams {
package android.service.media {
+ public abstract class CameraPrewarmService extends android.app.Service {
+ ctor public CameraPrewarmService();
+ method public android.os.IBinder onBind(android.content.Intent);
+ method public abstract void onCooldown(boolean);
+ method public abstract void onPrewarm();
+ }
+
public abstract class MediaBrowserService extends android.app.Service {
ctor public MediaBrowserService();
method public void dump(java.io.FileDescriptor, java.io.PrintWriter, java.lang.String[]);
@@ -33038,12 +33062,14 @@ package android.telephony {
public class PhoneNumberUtils {
ctor public PhoneNumberUtils();
- method public static void addPhoneTtsSpan(android.text.Spannable, int, int);
+ method public static void addTtsSpan(android.text.Spannable, int, int);
method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
method public static java.lang.String calledPartyBCDToString(byte[], int, int);
method public static boolean compare(java.lang.String, java.lang.String);
method public static boolean compare(android.content.Context, java.lang.String, java.lang.String);
method public static java.lang.String convertKeypadLettersToDigits(java.lang.String);
+ method public static android.text.style.TtsSpan createTtsSpan(java.lang.String);
+ method public static java.lang.CharSequence createTtsSpannable(java.lang.CharSequence);
method public static java.lang.String extractNetworkPortion(java.lang.String);
method public static java.lang.String extractPostDialPortion(java.lang.String);
method public static deprecated void formatJapaneseNumber(android.text.Editable);
@@ -33056,8 +33082,6 @@ package android.telephony {
method public static java.lang.String formatNumberToRFC3966(java.lang.String, java.lang.String);
method public static deprecated int getFormatTypeForLocale(java.util.Locale);
method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context);
- method public static android.text.style.TtsSpan getPhoneTtsSpan(java.lang.String);
- method public static java.lang.CharSequence getPhoneTtsSpannable(java.lang.CharSequence);
method public static java.lang.String getStrippedReversed(java.lang.String);
method public static final boolean is12Key(char);
method public static final boolean isDialable(char);
@@ -33403,7 +33427,6 @@ package android.telephony {
method public int[] supplyPukReportResult(java.lang.String, java.lang.String);
method public void toggleRadioOnOff();
method public void updateServiceLocation();
- field public static final java.lang.String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
field public static final java.lang.String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
field public static final java.lang.String ACTION_RESPOND_VIA_MESSAGE = "android.intent.action.RESPOND_VIA_MESSAGE";
field public static final int CALL_STATE_IDLE = 0; // 0x0
@@ -39651,7 +39674,6 @@ package android.view {
field public static final int TITLE_CHANGED = 64; // 0x40
field public static final int TYPE_ACCESSIBILITY_OVERLAY = 2032; // 0x7f0
field public static final int TYPE_APPLICATION = 2; // 0x2
- field public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = 1005; // 0x3ed
field public static final int TYPE_APPLICATION_ATTACHED_DIALOG = 1003; // 0x3eb
field public static final int TYPE_APPLICATION_MEDIA = 1001; // 0x3e9
field public static final int TYPE_APPLICATION_PANEL = 1000; // 0x3e8
diff --git a/core/java/android/accounts/AbstractAccountAuthenticator.java b/core/java/android/accounts/AbstractAccountAuthenticator.java
index dbc9051f11b4..3e4a66dc127c 100644
--- a/core/java/android/accounts/AbstractAccountAuthenticator.java
+++ b/core/java/android/accounts/AbstractAccountAuthenticator.java
@@ -108,6 +108,14 @@ import java.util.Arrays;
public abstract class AbstractAccountAuthenticator {
private static final String TAG = "AccountAuthenticator";
+ /**
+ * Bundle key used for the {@code long} expiration time (in millis from the unix epoch) of the
+ * associated auth token.
+ *
+ * @see #getAuthToken
+ */
+ public static final String KEY_CUSTOM_TOKEN_EXPIRY = "android.accounts.expiry";
+
private final Context mContext;
public AbstractAccountAuthenticator(Context context) {
@@ -115,6 +123,7 @@ public abstract class AbstractAccountAuthenticator {
}
private class Transport extends IAccountAuthenticator.Stub {
+ @Override
public void addAccount(IAccountAuthenticatorResponse response, String accountType,
String authTokenType, String[] features, Bundle options)
throws RemoteException {
@@ -140,6 +149,7 @@ public abstract class AbstractAccountAuthenticator {
}
}
+ @Override
public void confirmCredentials(IAccountAuthenticatorResponse response,
Account account, Bundle options) throws RemoteException {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -162,6 +172,7 @@ public abstract class AbstractAccountAuthenticator {
}
}
+ @Override
public void getAuthTokenLabel(IAccountAuthenticatorResponse response,
String authTokenType)
throws RemoteException {
@@ -184,6 +195,7 @@ public abstract class AbstractAccountAuthenticator {
}
}
+ @Override
public void getAuthToken(IAccountAuthenticatorResponse response,
Account account, String authTokenType, Bundle loginOptions)
throws RemoteException {
@@ -209,6 +221,7 @@ public abstract class AbstractAccountAuthenticator {
}
}
+ @Override
public void updateCredentials(IAccountAuthenticatorResponse response, Account account,
String authTokenType, Bundle loginOptions) throws RemoteException {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -234,6 +247,7 @@ public abstract class AbstractAccountAuthenticator {
}
}
+ @Override
public void editProperties(IAccountAuthenticatorResponse response,
String accountType) throws RemoteException {
checkBinderPermission();
@@ -248,6 +262,7 @@ public abstract class AbstractAccountAuthenticator {
}
}
+ @Override
public void hasFeatures(IAccountAuthenticatorResponse response,
Account account, String[] features) throws RemoteException {
checkBinderPermission();
@@ -262,6 +277,7 @@ public abstract class AbstractAccountAuthenticator {
}
}
+ @Override
public void getAccountRemovalAllowed(IAccountAuthenticatorResponse response,
Account account) throws RemoteException {
checkBinderPermission();
@@ -276,6 +292,7 @@ public abstract class AbstractAccountAuthenticator {
}
}
+ @Override
public void getAccountCredentialsForCloning(IAccountAuthenticatorResponse response,
Account account) throws RemoteException {
checkBinderPermission();
@@ -291,6 +308,7 @@ public abstract class AbstractAccountAuthenticator {
}
}
+ @Override
public void addAccountFromCredentials(IAccountAuthenticatorResponse response,
Account account,
Bundle accountCredentials) throws RemoteException {
@@ -410,21 +428,42 @@ public abstract class AbstractAccountAuthenticator {
public abstract Bundle confirmCredentials(AccountAuthenticatorResponse response,
Account account, Bundle options)
throws NetworkErrorException;
+
/**
- * Gets the authtoken for an account.
+ * Gets an authtoken for an account.
+ *
+ * If not {@code null}, the resultant {@link Bundle} will contain different sets of keys
+ * depending on whether a token was successfully issued and, if not, whether one
+ * could be issued via some {@link android.app.Activity}.
+ * <p>
+ * If a token cannot be provided without some additional activity, the Bundle should contain
+ * {@link AccountManager#KEY_INTENT} with an associated {@link Intent}. On the other hand, if
+ * there is no such activity, then a Bundle containing
+ * {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} should be
+ * returned.
+ * <p>
+ * If a token can be successfully issued, the implementation should return the
+ * {@link AccountManager#KEY_ACCOUNT_NAME} and {@link AccountManager#KEY_ACCOUNT_TYPE} of the
+ * account associated with the token as well as the {@link AccountManager#KEY_AUTHTOKEN}. In
+ * addition {@link AbstractAccountAuthenticator} implementations that declare themselves
+ * {@code android:customTokens=true} may also provide a non-negative {@link
+ * #KEY_CUSTOM_TOKEN_EXPIRY} long value containing the expiration timestamp of the expiration
+ * time (in millis since the unix epoch).
+ * <p>
+ * Implementers should assume that tokens will be cached on the basis of account and
+ * authTokenType. The system may ignore the contents of the supplied options Bundle when
+ * determining to re-use a cached token. Furthermore, implementers should assume a supplied
+ * expiration time will be treated as non-binding advice.
+ * <p>
+ * Finally, note that for android:customTokens=false authenticators, tokens are cached
+ * indefinitely until some client calls {@link
+ * AccountManager#invalidateAuthToken(String,String)}.
+ *
* @param response to send the result back to the AccountManager, will never be null
* @param account the account whose credentials are to be retrieved, will never be null
* @param authTokenType the type of auth token to retrieve, will never be null
* @param options a Bundle of authenticator-specific options, may be null
- * @return a Bundle result or null if the result is to be returned via the response. The result
- * will contain either:
- * <ul>
- * <li> {@link AccountManager#KEY_INTENT}, or
- * <li> {@link AccountManager#KEY_ACCOUNT_NAME}, {@link AccountManager#KEY_ACCOUNT_TYPE},
- * and {@link AccountManager#KEY_AUTHTOKEN}, or
- * <li> {@link AccountManager#KEY_ERROR_CODE} and {@link AccountManager#KEY_ERROR_MESSAGE} to
- * indicate an error
- * </ul>
+ * @return a Bundle result or null if the result is to be returned via the response.
* @throws NetworkErrorException if the authenticator could not honor the request due to a
* network error
*/
@@ -518,6 +557,7 @@ public abstract class AbstractAccountAuthenticator {
public Bundle getAccountCredentialsForCloning(final AccountAuthenticatorResponse response,
final Account account) throws NetworkErrorException {
new Thread(new Runnable() {
+ @Override
public void run() {
Bundle result = new Bundle();
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
@@ -543,6 +583,7 @@ public abstract class AbstractAccountAuthenticator {
Account account,
Bundle accountCredentials) throws NetworkErrorException {
new Thread(new Runnable() {
+ @Override
public void run() {
Bundle result = new Bundle();
result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 49f509974fcd..966482d53d61 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -3746,6 +3746,7 @@ public class Activity extends ContextThemeWrapper
*
* @see #onRequestPermissionsResult(int, String[], int[])
* @see #checkSelfPermission(String)
+ * @see #shouldShowRequestPermissionRationale(String)
*/
public final void requestPermissions(@NonNull String[] permissions, int requestCode) {
Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions);
@@ -3770,6 +3771,30 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * Gets whether you should show UI with rationale for requesting a permission.
+ * You should do this only if you do not have the permission and the context in
+ * which the permission is requested does not clearly communicate to the user
+ * what would be the benefit from granting this permission.
+ * <p>
+ * For example, if you write a camera app, requesting the camera permission
+ * would be expected by the user and no rationale for why it is requested is
+ * needed. If however, the app needs location for tagging photos then a non-tech
+ * savvy user may wonder how location is related to taking photos. In this case
+ * you may choose to show UI with rationale of requesting this permission.
+ * </p>
+ *
+ * @param permission A permission your app wants to request.
+ * @return Whether you can show permission rationale UI.
+ *
+ * @see #checkSelfPermission(String)
+ * @see #requestPermissions(String[], int)
+ * @see #onRequestPermissionsResult(int, String[], int[])
+ */
+ public boolean shouldShowRequestPermissionRationale(String permission) {
+ return getPackageManager().shouldShowRequestPermissionRationale(permission);
+ }
+
+ /**
* Same as calling {@link #startActivityForResult(Intent, int, Bundle)}
* with no options.
*
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 04f643074592..41e3db834f48 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -486,6 +486,16 @@ final class ApplicationPackageManager extends PackageManager {
}
@Override
+ public boolean shouldShowRequestPermissionRationale(String permission) {
+ try {
+ return mPM.shouldShowRequestPermissionRationale(permission,
+ mContext.getPackageName(), mContext.getUserId());
+ } catch (RemoteException e) {
+ throw new RuntimeException("Package manager has died", e);
+ }
+ }
+
+ @Override
public int checkSignatures(String pkg1, String pkg2) {
try {
return mPM.checkSignatures(pkg1, pkg2);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 978b4bce2386..55eaf272ba77 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -16,6 +16,8 @@
package android.app.admin;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.annotation.SystemApi;
@@ -76,7 +78,7 @@ import java.util.List;
* <h3>Developer Guides</h3>
* <p>For more information about managing policies for device administration, read the
* <a href="{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a>
- * developer guide.</p>
+ * developer guide.
* </div>
*/
public class DevicePolicyManager {
@@ -122,15 +124,45 @@ public class DevicePolicyManager {
*
* <p> If provisioning fails, the managedProfile is removed so the device returns to its
* previous state.
- *
- * <p>Input: Nothing.</p>
- * <p>Output: Nothing</p>
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_PROVISION_MANAGED_PROFILE
= "android.app.action.PROVISION_MANAGED_PROFILE";
/**
+ * Activity action: Starts the provisioning flow which sets up a managed device.
+ * Must be started with {@link android.app.Activity#startActivityForResult(Intent, int)}.
+ *
+ * <p> During device owner provisioning a device admin app is set as the owner of the device.
+ * A device owner has full control over the device. The device owner can not be modified by the
+ * user.
+ *
+ * <p> A typical use case would be a device that is owned by a company, but used by either an
+ * employee or client.
+ *
+ * <p> An intent with this action can be sent only on an unprovisioned device.
+ * It is possible to check if the device is provisioned or not by looking at
+ * {@link android.provider.Settings.Global#DEVICE_PROVISIONED}
+ *
+ * The intent contains the following extras:
+ * <ul>
+ * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}</li>
+ * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED}, optional</li>
+ * </ul>
+ *
+ * <p> When device owner provisioning has completed, an intent of the type
+ * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcast to the
+ * device owner.
+ *
+ * <p> If provisioning fails, the device is factory reset.
+ *
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_PROVISION_MANAGED_DEVICE
+ = "android.app.action.PROVISION_MANAGED_DEVICE";
+
+ /**
* A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
* a mobile device management application that starts managed profile provisioning to pass data
* to itself on the managed profile when provisioning completes. The mobile device management
@@ -155,7 +187,7 @@ public class DevicePolicyManager {
* message containing an NFC record with MIME type {@link #MIME_TYPE_PROVISIONING_NFC}.
*
* <p> When this extra is set, the application must have exactly one device admin receiver.
- * This receiver will be set as the profile or device owner and active admin.</p>
+ * This receiver will be set as the profile or device owner and active admin.
* @see DeviceAdminReceiver
* @deprecated Use {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}. This extra is still
@@ -170,11 +202,13 @@ public class DevicePolicyManager {
* application that will be set as the profile owner or device owner and active admin.
*
* <p>If an application starts provisioning directly via an intent with action
- * {@link #ACTION_PROVISION_MANAGED_PROFILE} the package name of this component has to match the
- * package name of the application that started provisioning.
+ * {@link #ACTION_PROVISION_MANAGED_PROFILE} or
+ * {@link #ACTION_PROVISION_MANAGED_DEVICE} the package name of this
+ * component has to match the package name of the application that started provisioning.
*
* <p>This component is set as device owner and active admin when device owner provisioning is
- * started by an NFC message containing an NFC record with MIME type
+ * started by an intent with action {@link #ACTION_PROVISION_MANAGED_DEVICE} or by an NFC
+ * message containing an NFC record with MIME type
* {@link #MIME_TYPE_PROVISIONING_NFC_V2}. For the NFC record, the component name should be
* flattened to a string, via {@link ComponentName#flattenToShortString()}.
*
@@ -212,10 +246,10 @@ public class DevicePolicyManager {
/**
* A Boolean extra that can be used by the mobile device management application to skip the
- * disabling of system apps during provisioning when set to <code>true</code>.
+ * disabling of system apps during provisioning when set to {@code true}.
*
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
- * provisioning via an NFC bump.
+ * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} or an intent with action
+ * {@link #ACTION_PROVISION_MANAGED_DEVICE} that starts device owner provisioning.
*/
public static final String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED =
"android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
@@ -415,8 +449,8 @@ public class DevicePolicyManager {
* A boolean extra indicating whether device encryption can be skipped as part of Device Owner
* provisioning.
*
- * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
- * provisioning via an NFC bump.
+ * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} or an intent with action
+ * {@link #ACTION_PROVISION_MANAGED_DEVICE} that starts device owner provisioning.
*/
public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION =
"android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
@@ -610,8 +644,7 @@ public class DevicePolicyManager {
*
* <p>During device owner provisioning a device admin app is set as the owner of the device.
* A device owner has full control over the device. The device owner can not be modified by the
- * user and the only way of resetting the device is if the device owner app calls a factory
- * reset.
+ * user.
*
* <p> A typical use case would be a device that is owned by a company, but used by either an
* employee or client.
@@ -644,9 +677,6 @@ public class DevicePolicyManager {
*
* <p>
* If provisioning fails, the device is factory reset.
- *
- * <p>Input: Nothing.</p>
- * <p>Output: Nothing</p>
*/
public static final String MIME_TYPE_PROVISIONING_NFC_V2
= "application/com.android.managedprovisioning.v2";
@@ -847,18 +877,18 @@ public class DevicePolicyManager {
* Return true if the given administrator component is currently
* active (enabled) in the system.
*/
- public boolean isAdminActive(ComponentName who) {
- return isAdminActiveAsUser(who, UserHandle.myUserId());
+ public boolean isAdminActive(@NonNull ComponentName admin) {
+ return isAdminActiveAsUser(admin, UserHandle.myUserId());
}
/**
* @see #isAdminActive(ComponentName)
* @hide
*/
- public boolean isAdminActiveAsUser(ComponentName who, int userId) {
+ public boolean isAdminActiveAsUser(@NonNull ComponentName admin, int userId) {
if (mService != null) {
try {
- return mService.isAdminActive(who, userId);
+ return mService.isAdminActive(admin, userId);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -870,10 +900,10 @@ public class DevicePolicyManager {
* for the user.
* @hide
*/
- public boolean isRemovingAdmin(ComponentName who, int userId) {
+ public boolean isRemovingAdmin(@NonNull ComponentName admin, int userId) {
if (mService != null) {
try {
- return mService.isRemovingAdmin(who, userId);
+ return mService.isRemovingAdmin(admin, userId);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -883,8 +913,8 @@ public class DevicePolicyManager {
/**
- * Return a list of all currently active device administrator's component
- * names. Note that if there are no administrators than null may be
+ * Return a list of all currently active device administrators' component
+ * names. If there are no administrators {@code null} may be
* returned.
*/
public List<ComponentName> getActiveAdmins() {
@@ -928,10 +958,10 @@ public class DevicePolicyManager {
* try to remove someone else's component, a security exception will be
* thrown.
*/
- public void removeActiveAdmin(ComponentName who) {
+ public void removeActiveAdmin(@NonNull ComponentName admin) {
if (mService != null) {
try {
- mService.removeActiveAdmin(who, UserHandle.myUserId());
+ mService.removeActiveAdmin(admin, UserHandle.myUserId());
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -940,14 +970,14 @@ public class DevicePolicyManager {
/**
* Returns true if an administrator has been granted a particular device policy. This can
- * be used to check if the administrator was activated under an earlier set of policies,
+ * be used to check whether the administrator was activated under an earlier set of policies,
* but requires additional policies after an upgrade.
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with. Must be
* an active administrator, or an exception will be thrown.
* @param usesPolicy Which uses-policy to check, as defined in {@link DeviceAdminInfo}.
*/
- public boolean hasGrantedPolicy(ComponentName admin, int usesPolicy) {
+ public boolean hasGrantedPolicy(@NonNull ComponentName admin, int usesPolicy) {
if (mService != null) {
try {
return mService.hasGrantedPolicy(admin, usesPolicy, UserHandle.myUserId());
@@ -1048,7 +1078,7 @@ public class DevicePolicyManager {
* {@link #PASSWORD_QUALITY_ALPHABETIC}, {@link #PASSWORD_QUALITY_ALPHANUMERIC}
* or {@link #PASSWORD_QUALITY_COMPLEX}.
*/
- public void setPasswordQuality(ComponentName admin, int quality) {
+ public void setPasswordQuality(@NonNull ComponentName admin, int quality) {
if (mService != null) {
try {
mService.setPasswordQuality(admin, quality);
@@ -1061,15 +1091,15 @@ public class DevicePolicyManager {
/**
* Retrieve the current minimum password quality for all admins of this user
* and its profiles or a particular one.
- * @param admin The name of the admin component to check, or null to aggregate
+ * @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
*/
- public int getPasswordQuality(ComponentName admin) {
+ public int getPasswordQuality(@Nullable ComponentName admin) {
return getPasswordQuality(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordQuality(ComponentName admin, int userHandle) {
+ public int getPasswordQuality(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordQuality(admin, userHandle);
@@ -1101,7 +1131,7 @@ public class DevicePolicyManager {
* @param length The new desired minimum password length. A value of 0
* means there is no restriction.
*/
- public void setPasswordMinimumLength(ComponentName admin, int length) {
+ public void setPasswordMinimumLength(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumLength(admin, length);
@@ -1114,15 +1144,15 @@ public class DevicePolicyManager {
/**
* Retrieve the current minimum password length for all admins of this
* user and its profiles or a particular one.
- * @param admin The name of the admin component to check, or null to aggregate
+ * @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
*/
- public int getPasswordMinimumLength(ComponentName admin) {
+ public int getPasswordMinimumLength(@Nullable ComponentName admin) {
return getPasswordMinimumLength(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumLength(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumLength(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumLength(admin, userHandle);
@@ -1155,7 +1185,7 @@ public class DevicePolicyManager {
* required in the password. A value of 0 means there is no
* restriction.
*/
- public void setPasswordMinimumUpperCase(ComponentName admin, int length) {
+ public void setPasswordMinimumUpperCase(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumUpperCase(admin, length);
@@ -1173,17 +1203,17 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of upper case letters required in the
* password.
*/
- public int getPasswordMinimumUpperCase(ComponentName admin) {
+ public int getPasswordMinimumUpperCase(@Nullable ComponentName admin) {
return getPasswordMinimumUpperCase(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumUpperCase(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumUpperCase(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumUpperCase(admin, userHandle);
@@ -1216,7 +1246,7 @@ public class DevicePolicyManager {
* required in the password. A value of 0 means there is no
* restriction.
*/
- public void setPasswordMinimumLowerCase(ComponentName admin, int length) {
+ public void setPasswordMinimumLowerCase(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumLowerCase(admin, length);
@@ -1234,17 +1264,17 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of lower case letters required in the
* password.
*/
- public int getPasswordMinimumLowerCase(ComponentName admin) {
+ public int getPasswordMinimumLowerCase(@Nullable ComponentName admin) {
return getPasswordMinimumLowerCase(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumLowerCase(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumLowerCase(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumLowerCase(admin, userHandle);
@@ -1276,7 +1306,7 @@ public class DevicePolicyManager {
* @param length The new desired minimum number of letters required in the
* password. A value of 0 means there is no restriction.
*/
- public void setPasswordMinimumLetters(ComponentName admin, int length) {
+ public void setPasswordMinimumLetters(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumLetters(admin, length);
@@ -1293,16 +1323,16 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of letters required in the password.
*/
- public int getPasswordMinimumLetters(ComponentName admin) {
+ public int getPasswordMinimumLetters(@Nullable ComponentName admin) {
return getPasswordMinimumLetters(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumLetters(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumLetters(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumLetters(admin, userHandle);
@@ -1334,7 +1364,7 @@ public class DevicePolicyManager {
* @param length The new desired minimum number of numerical digits required
* in the password. A value of 0 means there is no restriction.
*/
- public void setPasswordMinimumNumeric(ComponentName admin, int length) {
+ public void setPasswordMinimumNumeric(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumNumeric(admin, length);
@@ -1352,16 +1382,16 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of numerical digits required in the password.
*/
- public int getPasswordMinimumNumeric(ComponentName admin) {
+ public int getPasswordMinimumNumeric(@Nullable ComponentName admin) {
return getPasswordMinimumNumeric(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumNumeric(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumNumeric(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumNumeric(admin, userHandle);
@@ -1393,7 +1423,7 @@ public class DevicePolicyManager {
* @param length The new desired minimum number of symbols required in the
* password. A value of 0 means there is no restriction.
*/
- public void setPasswordMinimumSymbols(ComponentName admin, int length) {
+ public void setPasswordMinimumSymbols(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumSymbols(admin, length);
@@ -1410,16 +1440,16 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of symbols required in the password.
*/
- public int getPasswordMinimumSymbols(ComponentName admin) {
+ public int getPasswordMinimumSymbols(@Nullable ComponentName admin) {
return getPasswordMinimumSymbols(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumSymbols(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumSymbols(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumSymbols(admin, userHandle);
@@ -1451,7 +1481,7 @@ public class DevicePolicyManager {
* @param length The new desired minimum number of letters required in the
* password. A value of 0 means there is no restriction.
*/
- public void setPasswordMinimumNonLetter(ComponentName admin, int length) {
+ public void setPasswordMinimumNonLetter(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordMinimumNonLetter(admin, length);
@@ -1469,16 +1499,16 @@ public class DevicePolicyManager {
* and only applies when the password quality is
* {@link #PASSWORD_QUALITY_COMPLEX}.
*
- * @param admin The name of the admin component to check, or null to
+ * @param admin The name of the admin component to check, or {@code null} to
* aggregate all admins.
* @return The minimum number of letters required in the password.
*/
- public int getPasswordMinimumNonLetter(ComponentName admin) {
+ public int getPasswordMinimumNonLetter(@Nullable ComponentName admin) {
return getPasswordMinimumNonLetter(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordMinimumNonLetter(ComponentName admin, int userHandle) {
+ public int getPasswordMinimumNonLetter(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordMinimumNonLetter(admin, userHandle);
@@ -1511,7 +1541,7 @@ public class DevicePolicyManager {
* @param length The new desired length of password history. A value of 0
* means there is no restriction.
*/
- public void setPasswordHistoryLength(ComponentName admin, int length) {
+ public void setPasswordHistoryLength(@NonNull ComponentName admin, int length) {
if (mService != null) {
try {
mService.setPasswordHistoryLength(admin, length);
@@ -1543,7 +1573,7 @@ public class DevicePolicyManager {
* @param timeout The limit (in ms) that a password can remain in effect. A value of 0
* means there is no restriction (unlimited).
*/
- public void setPasswordExpirationTimeout(ComponentName admin, long timeout) {
+ public void setPasswordExpirationTimeout(@NonNull ComponentName admin, long timeout) {
if (mService != null) {
try {
mService.setPasswordExpirationTimeout(admin, timeout);
@@ -1557,12 +1587,12 @@ public class DevicePolicyManager {
* Get the password expiration timeout for the given admin. The expiration timeout is the
* recurring expiration timeout provided in the call to
* {@link #setPasswordExpirationTimeout(ComponentName, long)} for the given admin or the
- * aggregate of all policy administrators if admin is null.
+ * aggregate of all policy administrators if {@code admin} is null.
*
- * @param admin The name of the admin component to check, or null to aggregate all admins.
+ * @param admin The name of the admin component to check, or {@code null} to aggregate all admins.
* @return The timeout for the given admin or the minimum of all timeouts
*/
- public long getPasswordExpirationTimeout(ComponentName admin) {
+ public long getPasswordExpirationTimeout(@Nullable ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordExpirationTimeout(admin, UserHandle.myUserId());
@@ -1580,10 +1610,10 @@ public class DevicePolicyManager {
* If admin is null, then a composite of all expiration timeouts is returned
* - which will be the minimum of all timeouts.
*
- * @param admin The name of the admin component to check, or null to aggregate all admins.
+ * @param admin The name of the admin component to check, or {@code null} to aggregate all admins.
* @return The password expiration time, in ms.
*/
- public long getPasswordExpiration(ComponentName admin) {
+ public long getPasswordExpiration(@Nullable ComponentName admin) {
if (mService != null) {
try {
return mService.getPasswordExpiration(admin, UserHandle.myUserId());
@@ -1597,16 +1627,16 @@ public class DevicePolicyManager {
/**
* Retrieve the current password history length for all admins of this
* user and its profiles or a particular one.
- * @param admin The name of the admin component to check, or null to aggregate
+ * @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
* @return The length of the password history
*/
- public int getPasswordHistoryLength(ComponentName admin) {
+ public int getPasswordHistoryLength(@Nullable ComponentName admin) {
return getPasswordHistoryLength(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getPasswordHistoryLength(ComponentName admin, int userHandle) {
+ public int getPasswordHistoryLength(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getPasswordHistoryLength(admin, userHandle);
@@ -1705,7 +1735,7 @@ public class DevicePolicyManager {
* @param num The number of failed password attempts at which point the
* device will wipe its data.
*/
- public void setMaximumFailedPasswordsForWipe(ComponentName admin, int num) {
+ public void setMaximumFailedPasswordsForWipe(@NonNull ComponentName admin, int num) {
if (mService != null) {
try {
mService.setMaximumFailedPasswordsForWipe(admin, num);
@@ -1719,15 +1749,15 @@ public class DevicePolicyManager {
* Retrieve the current maximum number of login attempts that are allowed
* before the device wipes itself, for all admins of this user and its profiles
* or a particular one.
- * @param admin The name of the admin component to check, or null to aggregate
+ * @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
*/
- public int getMaximumFailedPasswordsForWipe(ComponentName admin) {
+ public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin) {
return getMaximumFailedPasswordsForWipe(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getMaximumFailedPasswordsForWipe(ComponentName admin, int userHandle) {
+ public int getMaximumFailedPasswordsForWipe(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getMaximumFailedPasswordsForWipe(admin, userHandle);
@@ -1824,7 +1854,7 @@ public class DevicePolicyManager {
* @param timeMs The new desired maximum time to lock in milliseconds.
* A value of 0 means there is no restriction.
*/
- public void setMaximumTimeToLock(ComponentName admin, long timeMs) {
+ public void setMaximumTimeToLock(@NonNull ComponentName admin, long timeMs) {
if (mService != null) {
try {
mService.setMaximumTimeToLock(admin, timeMs);
@@ -1837,17 +1867,17 @@ public class DevicePolicyManager {
/**
* Retrieve the current maximum time to unlock for all admins of this user
* and its profiles or a particular one.
- * @param admin The name of the admin component to check, or null to aggregate
+ * @param admin The name of the admin component to check, or {@code null} to aggregate
* all admins.
* @return time in milliseconds for the given admin or the minimum value (strictest) of
* all admins if admin is null. Returns 0 if there are no restrictions.
*/
- public long getMaximumTimeToLock(ComponentName admin) {
+ public long getMaximumTimeToLock(@Nullable ComponentName admin) {
return getMaximumTimeToLock(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public long getMaximumTimeToLock(ComponentName admin, int userHandle) {
+ public long getMaximumTimeToLock(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getMaximumTimeToLock(admin, userHandle);
@@ -1922,21 +1952,20 @@ public class DevicePolicyManager {
* this method; if it has not, a security exception will be thrown.
* Only the first device admin can set the proxy. If a second admin attempts
* to set the proxy, the {@link ComponentName} of the admin originally setting the
- * proxy will be returned. If successful in setting the proxy, null will
+ * proxy will be returned. If successful in setting the proxy, {@code null} will
* be returned.
* The method can be called repeatedly by the device admin alrady setting the
* proxy to update the proxy and exclusion list.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated
- * with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param proxySpec the global proxy desired. Must be an HTTP Proxy.
* Pass Proxy.NO_PROXY to reset the proxy.
* @param exclusionList a list of domains to be excluded from the global proxy.
- * @return returns null if the proxy was successfully set, or a {@link ComponentName}
- * of the device admin that sets thew proxy otherwise.
+ * @return {@code null} if the proxy was successfully set, or otherwise a {@link ComponentName}
+ * of the device admin that sets the proxy.
* @hide
*/
- public ComponentName setGlobalProxy(ComponentName admin, Proxy proxySpec,
+ public ComponentName setGlobalProxy(@NonNull ComponentName admin, Proxy proxySpec,
List<String> exclusionList ) {
if (proxySpec == null) {
throw new NullPointerException();
@@ -2001,7 +2030,8 @@ public class DevicePolicyManager {
* @param proxyInfo The a {@link ProxyInfo} object defining the new global
* HTTP proxy. A {@code null} value will clear the global HTTP proxy.
*/
- public void setRecommendedGlobalProxy(ComponentName admin, ProxyInfo proxyInfo) {
+ public void setRecommendedGlobalProxy(@NonNull ComponentName admin, @Nullable ProxyInfo
+ proxyInfo) {
if (mService != null) {
try {
mService.setRecommendedGlobalProxy(admin, proxyInfo);
@@ -2013,8 +2043,8 @@ public class DevicePolicyManager {
/**
* Returns the component name setting the global proxy.
- * @return ComponentName object of the device admin that set the global proxy, or
- * null if no admin has set the proxy.
+ * @return ComponentName object of the device admin that set the global proxy, or {@code null}
+ * if no admin has set the proxy.
* @hide
*/
public ComponentName getGlobalProxyAdmin() {
@@ -2147,7 +2177,7 @@ public class DevicePolicyManager {
* {@link #ENCRYPTION_STATUS_ACTIVE}. This is the value of the requests; Use
* {@link #getStorageEncryptionStatus()} to query the actual device state.
*/
- public int setStorageEncryption(ComponentName admin, boolean encrypt) {
+ public int setStorageEncryption(@NonNull ComponentName admin, boolean encrypt) {
if (mService != null) {
try {
return mService.setStorageEncryption(admin, encrypt);
@@ -2167,7 +2197,7 @@ public class DevicePolicyManager {
* administrators.
* @return true if the admin(s) are requesting encryption, false if not.
*/
- public boolean getStorageEncryption(ComponentName admin) {
+ public boolean getStorageEncryption(@Nullable ComponentName admin) {
if (mService != null) {
try {
return mService.getStorageEncryption(admin, UserHandle.myUserId());
@@ -2216,14 +2246,14 @@ public class DevicePolicyManager {
/**
* Installs the given certificate as a user CA.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
* @param certBuffer encoded form of the certificate to install.
*
* @return false if the certBuffer cannot be parsed or installation is
* interrupted, true otherwise.
*/
- public boolean installCaCert(ComponentName admin, byte[] certBuffer) {
+ public boolean installCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
if (mService != null) {
try {
return mService.installCaCert(admin, certBuffer);
@@ -2237,11 +2267,11 @@ public class DevicePolicyManager {
/**
* Uninstalls the given certificate from trusted user CAs, if present.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
* @param certBuffer encoded form of the certificate to remove.
*/
- public void uninstallCaCert(ComponentName admin, byte[] certBuffer) {
+ public void uninstallCaCert(@Nullable ComponentName admin, byte[] certBuffer) {
if (mService != null) {
try {
final String alias = getCaCertAlias(certBuffer);
@@ -2259,11 +2289,11 @@ public class DevicePolicyManager {
* If a user has installed any certificates by other means than device policy these will be
* included too.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
* @return a List of byte[] arrays, each encoding one user CA certificate.
*/
- public List<byte[]> getInstalledCaCerts(ComponentName admin) {
+ public List<byte[]> getInstalledCaCerts(@Nullable ComponentName admin) {
List<byte[]> certs = new ArrayList<byte[]>();
if (mService != null) {
try {
@@ -2287,10 +2317,10 @@ public class DevicePolicyManager {
* Uninstalls all custom trusted CA certificates from the profile. Certificates installed by
* means other than device policy will also be removed, except for system CA certificates.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
*/
- public void uninstallAllUserCaCerts(ComponentName admin) {
+ public void uninstallAllUserCaCerts(@Nullable ComponentName admin) {
if (mService != null) {
for (String alias : new TrustedCertificateStore().userAliases()) {
try {
@@ -2305,11 +2335,11 @@ public class DevicePolicyManager {
/**
* Returns whether this certificate is installed as a trusted CA.
*
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
* @param certBuffer encoded form of the certificate to look up.
*/
- public boolean hasCaCertInstalled(ComponentName admin, byte[] certBuffer) {
+ public boolean hasCaCertInstalled(@Nullable ComponentName admin, byte[] certBuffer) {
if (mService != null) {
try {
mService.enforceCanManageCaCerts(admin);
@@ -2327,21 +2357,21 @@ public class DevicePolicyManager {
* Called by a device or profile owner to install a certificate and private key pair. The
* keypair will be visible to all apps within the profile.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with. Use
- * <code>null</code> if calling from a delegated certificate installer.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if calling from a delegated certificate installer.
* @param privKey The private key to install.
* @param cert The certificate to install.
* @param alias The private key alias under which to install the certificate. If a certificate
* with that alias already exists, it will be overwritten.
* @return {@code true} if the keys were installed, {@code false} otherwise.
*/
- public boolean installKeyPair(ComponentName who, PrivateKey privKey, Certificate cert,
+ public boolean installKeyPair(@Nullable ComponentName admin, PrivateKey privKey, Certificate cert,
String alias) {
try {
final byte[] pemCert = Credentials.convertToPem(cert);
final byte[] pkcs8Key = KeyFactory.getInstance(privKey.getAlgorithm())
.getKeySpec(privKey, PKCS8EncodedKeySpec.class).getEncoded();
- return mService.installKeyPair(who, pkcs8Key, pemCert, alias);
+ return mService.installKeyPair(admin, pkcs8Key, pemCert, alias);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
@@ -2353,7 +2383,7 @@ public class DevicePolicyManager {
}
/**
- * Returns the alias of a given CA certificate in the certificate store, or null if it
+ * @return the alias of a given CA certificate in the certificate store, or {@code null} if it
* doesn't exist.
*/
private static String getCaCertAlias(byte[] certBuffer) throws CertificateException {
@@ -2373,15 +2403,15 @@ public class DevicePolicyManager {
* it is later cleared by calling this method with a null value or uninstallling the certificate
* installer.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param installerPackage The package name of the certificate installer which will be given
- * access. If <code>null</code> is given the current package will be cleared.
+ * access. If {@code null} is given the current package will be cleared.
*/
- public void setCertInstallerPackage(ComponentName who, String installerPackage)
- throws SecurityException {
+ public void setCertInstallerPackage(@NonNull ComponentName admin, @Nullable String
+ installerPackage) throws SecurityException {
if (mService != null) {
try {
- mService.setCertInstallerPackage(who, installerPackage);
+ mService.setCertInstallerPackage(admin, installerPackage);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -2392,14 +2422,14 @@ public class DevicePolicyManager {
* Called by a profile owner or device owner to retrieve the certificate installer for the
* current user. null if none is set.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with.
- * @return The package name of the current delegated certificate installer. <code>null</code>
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+ * @return The package name of the current delegated certificate installer, or {@code null}
* if none is set.
*/
- public String getCertInstallerPackage(ComponentName who) throws SecurityException {
+ public String getCertInstallerPackage(@NonNull ComponentName admin) throws SecurityException {
if (mService != null) {
try {
- return mService.getCertInstallerPackage(who);
+ return mService.getCertInstallerPackage(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -2419,7 +2449,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled Whether or not the camera should be disabled.
*/
- public void setCameraDisabled(ComponentName admin, boolean disabled) {
+ public void setCameraDisabled(@NonNull ComponentName admin, boolean disabled) {
if (mService != null) {
try {
mService.setCameraDisabled(admin, disabled);
@@ -2432,15 +2462,15 @@ public class DevicePolicyManager {
/**
* Determine whether or not the device's cameras have been disabled for this user,
* either by the current admin, if specified, or all admins.
- * @param admin The name of the admin component to check, or null to check if any admins
+ * @param admin The name of the admin component to check, or {@code null} to check whether any admins
* have disabled the camera
*/
- public boolean getCameraDisabled(ComponentName admin) {
+ public boolean getCameraDisabled(@Nullable ComponentName admin) {
return getCameraDisabled(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public boolean getCameraDisabled(ComponentName admin, int userHandle) {
+ public boolean getCameraDisabled(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getCameraDisabled(admin, userHandle);
@@ -2463,7 +2493,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled Whether screen capture is disabled or not.
*/
- public void setScreenCaptureDisabled(ComponentName admin, boolean disabled) {
+ public void setScreenCaptureDisabled(@NonNull ComponentName admin, boolean disabled) {
if (mService != null) {
try {
mService.setScreenCaptureDisabled(admin, disabled);
@@ -2476,15 +2506,15 @@ public class DevicePolicyManager {
/**
* Determine whether or not screen capture has been disabled by the current
* admin, if specified, or all admins.
- * @param admin The name of the admin component to check, or null to check if any admins
+ * @param admin The name of the admin component to check, or {@code null} to check whether any admins
* have disabled screen capture.
*/
- public boolean getScreenCaptureDisabled(ComponentName admin) {
+ public boolean getScreenCaptureDisabled(@Nullable ComponentName admin) {
return getScreenCaptureDisabled(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public boolean getScreenCaptureDisabled(ComponentName admin, int userHandle) {
+ public boolean getScreenCaptureDisabled(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getScreenCaptureDisabled(admin, userHandle);
@@ -2507,7 +2537,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param required Whether auto time is set required or not.
*/
- public void setAutoTimeRequired(ComponentName admin, boolean required) {
+ public void setAutoTimeRequired(@NonNull ComponentName admin, boolean required) {
if (mService != null) {
try {
mService.setAutoTimeRequired(admin, required);
@@ -2561,7 +2591,7 @@ public class DevicePolicyManager {
* {@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS}, {@link #KEYGUARD_DISABLE_FINGERPRINT},
* {@link #KEYGUARD_DISABLE_FEATURES_ALL}
*/
- public void setKeyguardDisabledFeatures(ComponentName admin, int which) {
+ public void setKeyguardDisabledFeatures(@NonNull ComponentName admin, int which) {
if (mService != null) {
try {
mService.setKeyguardDisabledFeatures(admin, which);
@@ -2574,17 +2604,17 @@ public class DevicePolicyManager {
/**
* Determine whether or not features have been disabled in keyguard either by the current
* admin, if specified, or all admins.
- * @param admin The name of the admin component to check, or null to check if any admins
+ * @param admin The name of the admin component to check, or {@code null} to check whether any admins
* have disabled features in keyguard.
* @return bitfield of flags. See {@link #setKeyguardDisabledFeatures(ComponentName, int)}
* for a list.
*/
- public int getKeyguardDisabledFeatures(ComponentName admin) {
+ public int getKeyguardDisabledFeatures(@Nullable ComponentName admin) {
return getKeyguardDisabledFeatures(admin, UserHandle.myUserId());
}
/** @hide per-user version */
- public int getKeyguardDisabledFeatures(ComponentName admin, int userHandle) {
+ public int getKeyguardDisabledFeatures(@Nullable ComponentName admin, int userHandle) {
if (mService != null) {
try {
return mService.getKeyguardDisabledFeatures(admin, userHandle);
@@ -2598,7 +2628,8 @@ public class DevicePolicyManager {
/**
* @hide
*/
- public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing, int userHandle) {
+ public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing,
+ int userHandle) {
if (mService != null) {
try {
mService.setActiveAdmin(policyReceiver, refreshing, userHandle);
@@ -2611,15 +2642,15 @@ public class DevicePolicyManager {
/**
* @hide
*/
- public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) {
+ public void setActiveAdmin(@NonNull ComponentName policyReceiver, boolean refreshing) {
setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId());
}
/**
- * Returns the DeviceAdminInfo as defined by the administrator's package info & meta-data
+ * Returns the DeviceAdminInfo as defined by the administrator's package info &amp; meta-data
* @hide
*/
- public DeviceAdminInfo getAdminInfo(ComponentName cn) {
+ public DeviceAdminInfo getAdminInfo(@NonNull ComponentName cn) {
ActivityInfo ai;
try {
ai = mContext.getPackageManager().getReceiverInfo(cn,
@@ -2646,7 +2677,7 @@ public class DevicePolicyManager {
/**
* @hide
*/
- public void getRemoveWarning(ComponentName admin, RemoteCallback result) {
+ public void getRemoveWarning(@Nullable ComponentName admin, RemoteCallback result) {
if (mService != null) {
try {
mService.getRemoveWarning(admin, result, UserHandle.myUserId());
@@ -2740,10 +2771,10 @@ public class DevicePolicyManager {
/**
* Used to determine if a particular package has been registered as a Device Owner app.
* A device owner app is a special device admin that cannot be deactivated by the user, once
- * activated as a device admin. It also cannot be uninstalled. To check if a particular
+ * activated as a device admin. It also cannot be uninstalled. To check whether a particular
* package is currently registered as the device owner app, pass in the package name from
* {@link Context#getPackageName()} to this method.<p/>This is useful for device
- * admin apps that want to check if they are also registered as the device owner app. The
+ * admin apps that want to check whether they are also registered as the device owner app. The
* exact mechanism by which a device admin app is registered as a device owner app is defined by
* the setup process.
* @param packageName the package name of the app, to compare with the registered device owner
@@ -2820,19 +2851,20 @@ public class DevicePolicyManager {
* MANAGE_DEVICE_ADMINS permission before the device is provisioned or by a device owner app. A
* device initializer app is granted device owner privileges during device initialization and
* profile owner privileges during secondary user initialization.
- * @param who Which {@link DeviceAdminReceiver} this request is associated with, or null if not
- * called by the device owner.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with, or
+ * {@code null} if not called by the device owner.
* @param initializer Which {@link DeviceAdminReceiver} to make device initializer.
* @return whether the component was successfully registered as the device initializer.
* @throws IllegalArgumentException if the componentname is null or invalid
* @throws IllegalStateException if the caller is not device owner or the device has
* already been provisioned or a device initializer already exists.
*/
- public boolean setDeviceInitializer(ComponentName who, ComponentName initializer)
+ public boolean setDeviceInitializer(@Nullable ComponentName admin,
+ @NonNull ComponentName initializer)
throws IllegalArgumentException, IllegalStateException {
if (mService != null) {
try {
- return mService.setDeviceInitializer(who, initializer);
+ return mService.setDeviceInitializer(admin, initializer);
} catch (RemoteException re) {
Log.w(TAG, "Failed to set device initializer");
}
@@ -2863,12 +2895,12 @@ public class DevicePolicyManager {
* subsequently created users. This method can be called by either the device owner or device
* initializer itself. The caller must be an active administrator.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
*/
- public void clearDeviceInitializerApp(ComponentName who) {
+ public void clearDeviceInitializerApp(@NonNull ComponentName admin) {
if (mService != null) {
try {
- mService.clearDeviceInitializer(who);
+ mService.clearDeviceInitializer(admin);
} catch (RemoteException re) {
Log.w(TAG, "Failed to clear device initializer");
}
@@ -2927,7 +2959,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @return whether the user is now enabled.
*/
- public boolean setUserEnabled(ComponentName admin) {
+ public boolean setUserEnabled(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.setUserEnabled(admin);
@@ -2955,7 +2987,7 @@ public class DevicePolicyManager {
* the user has already been set up.
*/
@SystemApi
- public boolean setActiveProfileOwner(ComponentName admin, @Deprecated String ownerName)
+ public boolean setActiveProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName)
throws IllegalArgumentException {
if (mService != null) {
try {
@@ -2980,7 +3012,7 @@ public class DevicePolicyManager {
* @return
*/
@SystemApi
- public void clearProfileOwner(ComponentName admin) {
+ public void clearProfileOwner(@NonNull ComponentName admin) {
if (mService != null) {
try {
mService.clearProfileOwner(admin);
@@ -2992,14 +3024,14 @@ public class DevicePolicyManager {
/**
* @hide
- * Checks if the user was already setup.
+ * Checks whether the user was already setup.
*/
public boolean hasUserSetupCompleted() {
if (mService != null) {
try {
return mService.hasUserSetupCompleted();
} catch (RemoteException re) {
- Log.w(TAG, "Failed to check if user setup has completed");
+ Log.w(TAG, "Failed to check whether user setup has completed");
}
}
return true;
@@ -3021,7 +3053,7 @@ public class DevicePolicyManager {
* @throws IllegalArgumentException if admin is null, the package isn't installed, or the
* preconditions mentioned are not met.
*/
- public boolean setProfileOwner(ComponentName admin, @Deprecated String ownerName,
+ public boolean setProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName,
int userHandle) throws IllegalArgumentException {
if (admin == null) {
throw new NullPointerException("admin cannot be null");
@@ -3048,7 +3080,7 @@ public class DevicePolicyManager {
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
*/
- public void setProfileEnabled(ComponentName admin) {
+ public void setProfileEnabled(@NonNull ComponentName admin) {
if (mService != null) {
try {
mService.setProfileEnabled(admin);
@@ -3066,12 +3098,13 @@ public class DevicePolicyManager {
* @see #isProfileOwnerApp
* @see #isDeviceOwnerApp
*
+ * @param admin Which {@link DeviceAdminReceiver} this request is associate with.
* @param profileName The name of the profile.
*/
- public void setProfileName(ComponentName who, String profileName) {
+ public void setProfileName(@NonNull ComponentName admin, String profileName) {
if (mService != null) {
try {
- mService.setProfileName(who, profileName);
+ mService.setProfileName(admin, profileName);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -3102,7 +3135,7 @@ public class DevicePolicyManager {
/**
* @hide
- * @return the packageName of the owner of the given user profile or null if no profile
+ * @return the packageName of the owner of the given user profile or {@code null} if no profile
* owner has been set for that user.
* @throws IllegalArgumentException if the userId is invalid.
*/
@@ -3130,8 +3163,8 @@ public class DevicePolicyManager {
/**
* @hide
- * @return the human readable name of the organisation associated with this DPM or null if
- * one is not set.
+ * @return the human readable name of the organisation associated with this DPM or {@code null}
+ * if one is not set.
* @throws IllegalArgumentException if the userId is invalid.
*/
public String getProfileOwnerName() throws IllegalArgumentException {
@@ -3185,8 +3218,8 @@ public class DevicePolicyManager {
* @param filter The IntentFilter for which a default handler is added.
* @param activity The Activity that is added as default intent handler.
*/
- public void addPersistentPreferredActivity(ComponentName admin, IntentFilter filter,
- ComponentName activity) {
+ public void addPersistentPreferredActivity(@NonNull ComponentName admin, IntentFilter filter,
+ @NonNull ComponentName activity) {
if (mService != null) {
try {
mService.addPersistentPreferredActivity(admin, filter, activity);
@@ -3206,7 +3239,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageName The name of the package for which preferences are removed.
*/
- public void clearPackagePersistentPreferredActivities(ComponentName admin,
+ public void clearPackagePersistentPreferredActivities(@NonNull ComponentName admin,
String packageName) {
if (mService != null) {
try {
@@ -3241,7 +3274,7 @@ public class DevicePolicyManager {
*
* @see UserManager#KEY_RESTRICTIONS_PENDING
*/
- public void setApplicationRestrictions(ComponentName admin, String packageName,
+ public void setApplicationRestrictions(@NonNull ComponentName admin, String packageName,
Bundle settings) {
if (mService != null) {
try {
@@ -3271,8 +3304,8 @@ public class DevicePolicyManager {
* then it's up to the TrustAgent itself to aggregate the values from all device admins.
* <p>Consult documentation for the specific TrustAgent to determine legal options parameters.
*/
- public void setTrustAgentConfiguration(ComponentName admin, ComponentName target,
- PersistableBundle configuration) {
+ public void setTrustAgentConfiguration(@NonNull ComponentName admin,
+ @NonNull ComponentName target, PersistableBundle configuration) {
if (mService != null) {
try {
mService.setTrustAgentConfiguration(admin, target, configuration);
@@ -3296,14 +3329,14 @@ public class DevicePolicyManager {
* @param agent Which component to get enabled features for.
* @return configuration for the given trust agent.
*/
- public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
- ComponentName agent) {
+ public List<PersistableBundle> getTrustAgentConfiguration(@Nullable ComponentName admin,
+ @NonNull ComponentName agent) {
return getTrustAgentConfiguration(admin, agent, UserHandle.myUserId());
}
/** @hide per-user version */
- public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
- ComponentName agent, int userHandle) {
+ public List<PersistableBundle> getTrustAgentConfiguration(@Nullable ComponentName admin,
+ @NonNull ComponentName agent, int userHandle) {
if (mService != null) {
try {
return mService.getTrustAgentConfiguration(admin, agent, userHandle);
@@ -3321,13 +3354,13 @@ public class DevicePolicyManager {
* <p>The calling device admin must be a profile owner. If it is not, a
* security exception will be thrown.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param disabled If true caller-Id information in the managed profile is not displayed.
*/
- public void setCrossProfileCallerIdDisabled(ComponentName who, boolean disabled) {
+ public void setCrossProfileCallerIdDisabled(@NonNull ComponentName admin, boolean disabled) {
if (mService != null) {
try {
- mService.setCrossProfileCallerIdDisabled(who, disabled);
+ mService.setCrossProfileCallerIdDisabled(admin, disabled);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -3341,12 +3374,12 @@ public class DevicePolicyManager {
* <p>The calling device admin must be a profile owner. If it is not, a
* security exception will be thrown.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with.
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
*/
- public boolean getCrossProfileCallerIdDisabled(ComponentName who) {
+ public boolean getCrossProfileCallerIdDisabled(@NonNull ComponentName admin) {
if (mService != null) {
try {
- return mService.getCrossProfileCallerIdDisabled(who);
+ return mService.getCrossProfileCallerIdDisabled(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -3396,15 +3429,15 @@ public class DevicePolicyManager {
* <p>
* This API works on managed profile only.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
* @param disabled If true, bluetooth devices cannot access enterprise
* contacts.
*/
- public void setBluetoothContactSharingDisabled(ComponentName who, boolean disabled) {
+ public void setBluetoothContactSharingDisabled(@NonNull ComponentName admin, boolean disabled) {
if (mService != null) {
try {
- mService.setBluetoothContactSharingDisabled(who, disabled);
+ mService.setBluetoothContactSharingDisabled(admin, disabled);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -3420,13 +3453,13 @@ public class DevicePolicyManager {
* <p>
* This API works on managed profile only.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated
* with.
*/
- public boolean getBluetoothContactSharingDisabled(ComponentName who) {
+ public boolean getBluetoothContactSharingDisabled(@NonNull ComponentName admin) {
if (mService != null) {
try {
- return mService.getBluetoothContactSharingDisabled(who);
+ return mService.getBluetoothContactSharingDisabled(admin);
} catch (RemoteException e) {
Log.w(TAG, "Failed talking with device policy service", e);
}
@@ -3465,7 +3498,7 @@ public class DevicePolicyManager {
* @param flags {@link DevicePolicyManager#FLAG_MANAGED_CAN_ACCESS_PARENT} and
* {@link DevicePolicyManager#FLAG_PARENT_CAN_ACCESS_MANAGED} are supported.
*/
- public void addCrossProfileIntentFilter(ComponentName admin, IntentFilter filter, int flags) {
+ public void addCrossProfileIntentFilter(@NonNull ComponentName admin, IntentFilter filter, int flags) {
if (mService != null) {
try {
mService.addCrossProfileIntentFilter(admin, filter, flags);
@@ -3481,7 +3514,7 @@ public class DevicePolicyManager {
* Only removes those that have been set by the profile owner.
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
*/
- public void clearCrossProfileIntentFilters(ComponentName admin) {
+ public void clearCrossProfileIntentFilters(@NonNull ComponentName admin) {
if (mService != null) {
try {
mService.clearCrossProfileIntentFilters(admin);
@@ -3512,7 +3545,7 @@ public class DevicePolicyManager {
* @return true if setting the restriction succeeded. It fail if there is
* one or more non-system accessibility services enabled, that are not in the list.
*/
- public boolean setPermittedAccessibilityServices(ComponentName admin,
+ public boolean setPermittedAccessibilityServices(@NonNull ComponentName admin,
List<String> packageNames) {
if (mService != null) {
try {
@@ -3533,7 +3566,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @return List of accessiblity service package names.
*/
- public List<String> getPermittedAccessibilityServices(ComponentName admin) {
+ public List<String> getPermittedAccessibilityServices(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.getPermittedAccessibilityServices(admin);
@@ -3591,7 +3624,7 @@ public class DevicePolicyManager {
* one or more non-system input methods currently enabled that are not in
* the packageNames list.
*/
- public boolean setPermittedInputMethods(ComponentName admin, List<String> packageNames) {
+ public boolean setPermittedInputMethods(@NonNull ComponentName admin, List<String> packageNames) {
if (mService != null) {
try {
return mService.setPermittedInputMethods(admin, packageNames);
@@ -3612,7 +3645,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @return List of input method package names.
*/
- public List<String> getPermittedInputMethods(ComponentName admin) {
+ public List<String> getPermittedInputMethods(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.getPermittedInputMethods(admin);
@@ -3655,9 +3688,10 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param name the user's name
* @see UserHandle
- * @return the UserHandle object for the created user, or null if the user could not be created.
+ * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
+ * user could not be created.
*/
- public UserHandle createUser(ComponentName admin, String name) {
+ public UserHandle createUser(@NonNull ComponentName admin, String name) {
try {
return mService.createUser(admin, name);
} catch (RemoteException re) {
@@ -3688,10 +3722,11 @@ public class DevicePolicyManager {
* @param adminExtras Extras that will be passed to onEnable of the admin receiver
* on the new user.
* @see UserHandle
- * @return the UserHandle object for the created user, or null if the user could not be created.
+ * @return the {@link android.os.UserHandle} object for the created user, or {@code null} if the
+ * user could not be created.
*/
- public UserHandle createAndInitializeUser(ComponentName admin, String name, String ownerName,
- ComponentName profileOwnerComponent, Bundle adminExtras) {
+ public UserHandle createAndInitializeUser(@NonNull ComponentName admin, String name,
+ String ownerName, @NonNull ComponentName profileOwnerComponent, Bundle adminExtras) {
try {
return mService.createAndInitializeUser(admin, name, ownerName, profileOwnerComponent,
adminExtras);
@@ -3709,7 +3744,7 @@ public class DevicePolicyManager {
* @param userHandle the user to remove.
* @return {@code true} if the user was removed, {@code false} otherwise.
*/
- public boolean removeUser(ComponentName admin, UserHandle userHandle) {
+ public boolean removeUser(@NonNull ComponentName admin, UserHandle userHandle) {
try {
return mService.removeUser(admin, userHandle);
} catch (RemoteException re) {
@@ -3727,7 +3762,7 @@ public class DevicePolicyManager {
*
* @see Intent#ACTION_USER_FOREGROUND
*/
- public boolean switchUser(ComponentName admin, UserHandle userHandle) {
+ public boolean switchUser(@NonNull ComponentName admin, @Nullable UserHandle userHandle) {
try {
return mService.switchUser(admin, userHandle);
} catch (RemoteException re) {
@@ -3749,7 +3784,7 @@ public class DevicePolicyManager {
* {@link DevicePolicyManager#setApplicationRestrictions} was called, or an empty {@link Bundle}
* if no restrictions have been set.
*/
- public Bundle getApplicationRestrictions(ComponentName admin, String packageName) {
+ public Bundle getApplicationRestrictions(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.getApplicationRestrictions(admin, packageName);
@@ -3771,7 +3806,7 @@ public class DevicePolicyManager {
* @param key The key of the restriction. See the constants in
* {@link android.os.UserManager} for the list of keys.
*/
- public void addUserRestriction(ComponentName admin, String key) {
+ public void addUserRestriction(@NonNull ComponentName admin, String key) {
if (mService != null) {
try {
mService.setUserRestriction(admin, key, true);
@@ -3792,7 +3827,7 @@ public class DevicePolicyManager {
* @param key The key of the restriction. See the constants in
* {@link android.os.UserManager} for the list of keys.
*/
- public void clearUserRestriction(ComponentName admin, String key) {
+ public void clearUserRestriction(@NonNull ComponentName admin, String key) {
if (mService != null) {
try {
mService.setUserRestriction(admin, key, false);
@@ -3812,7 +3847,7 @@ public class DevicePolicyManager {
* unhidden.
* @return boolean Whether the hidden setting of the package was successfully updated.
*/
- public boolean setApplicationHidden(ComponentName admin, String packageName,
+ public boolean setApplicationHidden(@NonNull ComponentName admin, String packageName,
boolean hidden) {
if (mService != null) {
try {
@@ -3831,7 +3866,7 @@ public class DevicePolicyManager {
* @param packageName The name of the package to retrieve the hidden status of.
* @return boolean {@code true} if the package is hidden, {@code false} otherwise.
*/
- public boolean isApplicationHidden(ComponentName admin, String packageName) {
+ public boolean isApplicationHidden(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.isApplicationHidden(admin, packageName);
@@ -3849,7 +3884,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageName The package to be re-enabled in the current profile.
*/
- public void enableSystemApp(ComponentName admin, String packageName) {
+ public void enableSystemApp(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
mService.enableSystemApp(admin, packageName);
@@ -3868,7 +3903,7 @@ public class DevicePolicyManager {
* intent will be re-enabled in the current profile.
* @return int The number of activities that matched the intent and were installed.
*/
- public int enableSystemApp(ComponentName admin, Intent intent) {
+ public int enableSystemApp(@NonNull ComponentName admin, Intent intent) {
if (mService != null) {
try {
return mService.enableSystemAppWithIntent(admin, intent);
@@ -3894,7 +3929,7 @@ public class DevicePolicyManager {
* @param disabled The boolean indicating that account management will be disabled (true) or
* enabled (false).
*/
- public void setAccountManagementDisabled(ComponentName admin, String accountType,
+ public void setAccountManagementDisabled(@NonNull ComponentName admin, String accountType,
boolean disabled) {
if (mService != null) {
try {
@@ -3950,7 +3985,7 @@ public class DevicePolicyManager {
* @see DeviceAdminReceiver#onLockTaskModeExiting(Context, Intent)
* @see UserManager#DISALLOW_CREATE_WINDOWS
*/
- public void setLockTaskPackages(ComponentName admin, String[] packages)
+ public void setLockTaskPackages(@NonNull ComponentName admin, String[] packages)
throws SecurityException {
if (mService != null) {
try {
@@ -3967,7 +4002,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @hide
*/
- public String[] getLockTaskPackages(ComponentName admin) {
+ public String[] getLockTaskPackages(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.getLockTaskPackages(admin);
@@ -4024,7 +4059,7 @@ public class DevicePolicyManager {
* @param setting The name of the setting to update.
* @param value The value to update the setting to.
*/
- public void setGlobalSetting(ComponentName admin, String setting, String value) {
+ public void setGlobalSetting(@NonNull ComponentName admin, String setting, String value) {
if (mService != null) {
try {
mService.setGlobalSetting(admin, setting, value);
@@ -4052,7 +4087,7 @@ public class DevicePolicyManager {
* @param setting The name of the setting to update.
* @param value The value to update the setting to.
*/
- public void setSecureSetting(ComponentName admin, String setting, String value) {
+ public void setSecureSetting(@NonNull ComponentName admin, String setting, String value) {
if (mService != null) {
try {
mService.setSecureSetting(admin, setting, value);
@@ -4072,7 +4107,8 @@ public class DevicePolicyManager {
* {@link RestrictionsReceiver}. If this param is null,
* it removes the restrictions provider previously assigned.
*/
- public void setRestrictionsProvider(ComponentName admin, ComponentName provider) {
+ public void setRestrictionsProvider(@NonNull ComponentName admin,
+ @Nullable ComponentName provider) {
if (mService != null) {
try {
mService.setRestrictionsProvider(admin, provider);
@@ -4088,7 +4124,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param on {@code true} to mute master volume, {@code false} to turn mute off.
*/
- public void setMasterVolumeMuted(ComponentName admin, boolean on) {
+ public void setMasterVolumeMuted(@NonNull ComponentName admin, boolean on) {
if (mService != null) {
try {
mService.setMasterVolumeMuted(admin, on);
@@ -4104,7 +4140,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @return {@code true} if master volume is muted, {@code false} if it's not.
*/
- public boolean isMasterVolumeMuted(ComponentName admin) {
+ public boolean isMasterVolumeMuted(@NonNull ComponentName admin) {
if (mService != null) {
try {
return mService.isMasterVolumeMuted(admin);
@@ -4123,7 +4159,7 @@ public class DevicePolicyManager {
* @param packageName package to change.
* @param uninstallBlocked true if the user shouldn't be able to uninstall the package.
*/
- public void setUninstallBlocked(ComponentName admin, String packageName,
+ public void setUninstallBlocked(@NonNull ComponentName admin, String packageName,
boolean uninstallBlocked) {
if (mService != null) {
try {
@@ -4139,16 +4175,16 @@ public class DevicePolicyManager {
* Requires the caller to be the profile owner if checking a specific admin's policy.
* <p>
* <strong>Note:</strong> Starting from {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}, the
- * behavior of this API is changed such that passing <code>null</code> as the <code>admin</code>
+ * behavior of this API is changed such that passing {@code null} as the {@code admin}
* parameter will return if any admin has blocked the uninstallation. Before L MR1, passing
- * <code>null</code> will cause a NullPointerException to be raised.
+ * {@code null} will cause a NullPointerException to be raised.
*
- * @param admin The name of the admin component whose blocking policy will be checked, or null
- * to check if any admin has blocked the uninstallation.
+ * @param admin The name of the admin component whose blocking policy will be checked, or
+ * {@code null} to check whether any admin has blocked the uninstallation.
* @param packageName package to check.
* @return true if uninstallation is blocked.
*/
- public boolean isUninstallBlocked(ComponentName admin, String packageName) {
+ public boolean isUninstallBlocked(@Nullable ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.isUninstallBlocked(admin, packageName);
@@ -4168,7 +4204,6 @@ public class DevicePolicyManager {
* provides a different widget type.
* <p>
* <strong>Note:</strong> By default no widget provider package is white-listed.
- * </p>
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageName The package from which widget providers are white-listed.
@@ -4177,7 +4212,7 @@ public class DevicePolicyManager {
* @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String)
* @see #getCrossProfileWidgetProviders(android.content.ComponentName)
*/
- public boolean addCrossProfileWidgetProvider(ComponentName admin, String packageName) {
+ public boolean addCrossProfileWidgetProvider(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.addCrossProfileWidgetProvider(admin, packageName);
@@ -4195,7 +4230,6 @@ public class DevicePolicyManager {
* android.content.ComponentName, String)}.
* <p>
* <strong>Note:</strong> By default no widget provider package is white-listed.
- * </p>
*
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param packageName The package from which widget providers are no longer
@@ -4205,7 +4239,7 @@ public class DevicePolicyManager {
* @see #addCrossProfileWidgetProvider(android.content.ComponentName, String)
* @see #getCrossProfileWidgetProviders(android.content.ComponentName)
*/
- public boolean removeCrossProfileWidgetProvider(ComponentName admin, String packageName) {
+ public boolean removeCrossProfileWidgetProvider(@NonNull ComponentName admin, String packageName) {
if (mService != null) {
try {
return mService.removeCrossProfileWidgetProvider(admin, packageName);
@@ -4226,7 +4260,7 @@ public class DevicePolicyManager {
* @see #addCrossProfileWidgetProvider(android.content.ComponentName, String)
* @see #removeCrossProfileWidgetProvider(android.content.ComponentName, String)
*/
- public List<String> getCrossProfileWidgetProviders(ComponentName admin) {
+ public List<String> getCrossProfileWidgetProviders(@NonNull ComponentName admin) {
if (mService != null) {
try {
List<String> providers = mService.getCrossProfileWidgetProviders(admin);
@@ -4246,7 +4280,7 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param icon the bitmap to set as the photo.
*/
- public void setUserIcon(ComponentName admin, Bitmap icon) {
+ public void setUserIcon(@NonNull ComponentName admin, Bitmap icon) {
try {
mService.setUserIcon(admin, icon);
} catch (RemoteException re) {
@@ -4273,16 +4307,17 @@ public class DevicePolicyManager {
* Called by device owners to set a local system update policy. When a new policy is set,
* {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcasted.
*
- * @param who Which {@link DeviceAdminReceiver} this request is associated with. All components
- * in the device owner package can set system update policies and the most recent policy takes
+ * @param admin Which {@link DeviceAdminReceiver} this request is associated with. All
+ * components in the device owner package can set system update policies and the
+ * most recent policy takes
* effect.
- * @param policy the new policy, or null to clear the current policy.
+ * @param policy the new policy, or {@code null} to clear the current policy.
* @see SystemUpdatePolicy
*/
- public void setSystemUpdatePolicy(ComponentName who, SystemUpdatePolicy policy) {
+ public void setSystemUpdatePolicy(@NonNull ComponentName admin, SystemUpdatePolicy policy) {
if (mService != null) {
try {
- mService.setSystemUpdatePolicy(who, policy);
+ mService.setSystemUpdatePolicy(admin, policy);
} catch (RemoteException re) {
Log.w(TAG, "Error calling setSystemUpdatePolicy", re);
}
@@ -4292,7 +4327,7 @@ public class DevicePolicyManager {
/**
* Retrieve a local system update policy set previously by {@link #setSystemUpdatePolicy}.
*
- * @return The current policy object, or null if no policy is set.
+ * @return The current policy object, or {@code null} if no policy is set.
*/
public SystemUpdatePolicy getSystemUpdatePolicy() {
if (mService != null) {
@@ -4319,7 +4354,7 @@ public class DevicePolicyManager {
* @return {@code false} if attempting to disable the keyguard while a lock password was in
* place. {@code true} otherwise.
*/
- public boolean setKeyguardDisabled(ComponentName admin, boolean disabled) {
+ public boolean setKeyguardDisabled(@NonNull ComponentName admin, boolean disabled) {
try {
return mService.setKeyguardDisabled(admin, disabled);
} catch (RemoteException re) {
@@ -4339,7 +4374,7 @@ public class DevicePolicyManager {
* @return {@code false} if attempting to disable the status bar failed.
* {@code true} otherwise.
*/
- public boolean setStatusBarDisabled(ComponentName admin, boolean disabled) {
+ public boolean setStatusBarDisabled(@NonNull ComponentName admin, boolean disabled) {
try {
return mService.setStatusBarDisabled(admin, disabled);
} catch (RemoteException re) {
@@ -4377,7 +4412,8 @@ public class DevicePolicyManager {
* @param admin Which {@link DeviceAdminReceiver} this request is associated with.
* @param activity The Activity to be started by default during user setup.
*/
- public void setPreferredSetupActivity(ComponentName admin, ComponentName activity) {
+ public void setPreferredSetupActivity(@NonNull ComponentName admin,
+ @NonNull ComponentName activity) {
try {
mService.setPreferredSetupActivity(admin, activity);
} catch (RemoteException re) {
@@ -4395,7 +4431,7 @@ public class DevicePolicyManager {
* @param policy One of the policy constants {@link #PERMISSION_POLICY_PROMPT},
* {@link #PERMISSION_POLICY_AUTO_GRANT} and {@link #PERMISSION_POLICY_AUTO_DENY}.
*/
- public void setPermissionPolicy(ComponentName admin, int policy) {
+ public void setPermissionPolicy(@NonNull ComponentName admin, int policy) {
try {
mService.setPermissionPolicy(admin, policy);
} catch (RemoteException re) {
@@ -4409,7 +4445,7 @@ public class DevicePolicyManager {
* @param admin Which profile or device owner this request is associated with.
* @return the current policy for future permission requests.
*/
- public int getPermissionPolicy(ComponentName admin) {
+ public int getPermissionPolicy(@NonNull ComponentName admin) {
try {
return mService.getPermissionPolicy(admin);
} catch (RemoteException re) {
@@ -4439,7 +4475,7 @@ public class DevicePolicyManager {
* @see #PERMISSION_GRANT_STATE_DEFAULT
* @see #PERMISSION_GRANT_STATE_GRANTED
*/
- public boolean setPermissionGrantState(ComponentName admin, String packageName,
+ public boolean setPermissionGrantState(@NonNull ComponentName admin, String packageName,
String permission, int grantState) {
try {
return mService.setPermissionGrantState(admin, packageName, permission, grantState);
@@ -4466,7 +4502,7 @@ public class DevicePolicyManager {
* @see #setPermissionGrantState(ComponentName, String, String, int)
* @see PackageManager#checkPermission(String, String)
*/
- public int getPermissionGrantState(ComponentName admin, String packageName,
+ public int getPermissionGrantState(@NonNull ComponentName admin, String packageName,
String permission) {
try {
return mService.getPermissionGrantState(admin, packageName, permission);
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 254408a830fc..a9328bce0612 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -32,4 +32,5 @@ interface IUsageStatsManager {
UsageEvents queryEvents(long beginTime, long endTime, String callingPackage);
void setAppInactive(String packageName, boolean inactive, int userId);
boolean isAppInactive(String packageName, int userId);
+ void whitelistAppTemporarily(String packageName, long duration, int userId);
}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 34699d8012c2..c74b0f2d8e43 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -16,6 +16,7 @@
package android.app.usage;
+import android.annotation.SystemApi;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.RemoteException;
@@ -245,4 +246,25 @@ public final class UsageStatsManager {
// fall through
}
}
+
+ /**
+ * {@hide}
+ * Temporarily whitelist the specified app for a short duration. This is to allow an app
+ * receiving a high priority message to be able to access the network and acquire wakelocks
+ * even if the device is in power-save mode or the app is currently considered inactive.
+ * The caller must hold the CHANGE_DEVICE_IDLE_TEMP_WHITELIST permission.
+ * @param packageName The package name of the app to whitelist.
+ * @param duration Duration to whitelist the app for, in milliseconds. It is recommended that
+ * this be limited to 10s of seconds. Requested duration will be clamped to a few minutes.
+ * @param user The user for whom the package should be whitelisted. Passing in a user that is
+ * not the same as the caller's process will require the INTERACT_ACROSS_USERS permission.
+ * @see #isAppInactive(String)
+ */
+ @SystemApi
+ public void whitelistAppTemporarily(String packageName, long duration, UserHandle user) {
+ try {
+ mService.whitelistAppTemporarily(packageName, duration, user.getIdentifier());
+ } catch (RemoteException re) {
+ }
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index b22b914686db..8107a97e9d84 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -410,6 +410,7 @@ public final class BluetoothAdapter {
* Broadcast Action: The Bluetooth adapter state has changed in LE only mode.
* @hide
*/
+ @SystemApi
public static final String ACTION_BLE_STATE_CHANGED =
"android.bluetooth.adapter.action.BLE_STATE_CHANGED";
@@ -620,17 +621,18 @@ public final class BluetoothAdapter {
* @return true if the local Bluetooth LE adapter is turned on
* @hide
*/
- public boolean isLeEnabled() {
- final int state = getLeState();
- if (state == BluetoothAdapter.STATE_ON) {
- if (DBG) Log.d (TAG, "STATE_ON");
- } else if (state == BluetoothAdapter.STATE_BLE_ON) {
- if (DBG) Log.d (TAG, "STATE_BLE_ON");
- } else {
- if (DBG) Log.d (TAG, "STATE_OFF");
- return false;
- }
- return true;
+ @SystemApi
+ public boolean isLeEnabled() {
+ final int state = getLeState();
+ if (state == BluetoothAdapter.STATE_ON) {
+ if (DBG) Log.d (TAG, "STATE_ON");
+ } else if (state == BluetoothAdapter.STATE_BLE_ON) {
+ if (DBG) Log.d (TAG, "STATE_BLE_ON");
+ } else {
+ if (DBG) Log.d (TAG, "STATE_OFF");
+ return false;
+ }
+ return true;
}
/**
@@ -680,6 +682,7 @@ public final class BluetoothAdapter {
* immediate error
* @hide
*/
+ @SystemApi
public boolean disableBLE() {
if (!isBleScanAlwaysAvailable()) return false;
@@ -742,6 +745,7 @@ public final class BluetoothAdapter {
* immediate error
* @hide
*/
+ @SystemApi
public boolean enableBLE() {
if (!isBleScanAlwaysAvailable()) return false;
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index ddff7821cdcb..00b8c71fde32 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -105,6 +105,9 @@ interface IPackageManager {
void updatePermissionFlags(String permissionName, String packageName, int flagMask,
int flagValues, int userId);
+ boolean shouldShowRequestPermissionRationale(String permissionName,
+ String packageName, int userId);
+
boolean isProtectedBroadcast(String actionName);
int checkSignatures(String pkg1, String pkg2);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 2ca030635ef5..45245e4af95d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -2539,6 +2539,19 @@ public abstract class PackageManager {
@NonNull UserHandle user);
/**
+ * Gets whether you should show UI with rationale for requesting a permission.
+ * You should do this only if you do not have the permission and the context in
+ * which the permission is requested does not clearly communicate to the user
+ * what would be the benefit from grating this permission.
+ *
+ * @param permission A permission your app wants to request.
+ * @return Whether you can show permission rationale UI.
+ *
+ * @hide
+ */
+ public abstract boolean shouldShowRequestPermissionRationale(String permission);
+
+ /**
* Returns an {@link android.content.Intent} suitable for passing to
* {@link android.app.Activity#startActivityForResult(android.content.Intent, int)}
* which prompts the user to grant permissions to this application.
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index f0c3f2d2884b..8bcd5d14e0f2 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -160,7 +160,6 @@ public class TypedArray {
final TypedValue v = mValue;
if (getValueAt(index, v)) {
- StrictMode.noteResourceMismatch(v);
return v.coerceToString();
}
@@ -183,24 +182,6 @@ public class TypedArray {
*/
@Nullable
public String getString(int index) {
- return getString(index, true);
- }
-
- /**
- * Returns a string representation of the value at the given index,
- * optionally throwing a resource mismatch strict mode violation if the
- * value must be coerced to a string.
- *
- * @param index the index of the attribute to retrieve
- * @param strict {@code true} to throw a strict mode violation for string
- * coercion, {@code false} otherwise
- * @return a string representation of the value at the given index, or
- * {@code null} if the resource could not be coerced to a string
- * @see StrictMode#noteResourceMismatch(Object)
- * @hide Used internally for view attribute inspection.
- */
- @Nullable
- public String getString(int index, boolean strict) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
@@ -216,9 +197,6 @@ public class TypedArray {
final TypedValue v = mValue;
if (getValueAt(index, v)) {
- if (strict) {
- StrictMode.noteResourceMismatch(v);
- }
final CharSequence cs = v.coerceToString();
return cs != null ? cs.toString() : null;
}
@@ -292,7 +270,6 @@ public class TypedArray {
final TypedValue v = mValue;
if (getValueAt(index, v)) {
- StrictMode.noteResourceMismatch(v);
final CharSequence cs = v.coerceToString();
return cs != null ? cs.toString() : null;
}
diff --git a/core/java/android/os/IDeviceIdleController.aidl b/core/java/android/os/IDeviceIdleController.aidl
index 602bfea6fac6..268295dc40c0 100644
--- a/core/java/android/os/IDeviceIdleController.aidl
+++ b/core/java/android/os/IDeviceIdleController.aidl
@@ -16,6 +16,8 @@
package android.os;
+import android.os.UserHandle;
+
/** @hide */
interface IDeviceIdleController {
void addPowerSaveWhitelistApp(String name);
@@ -23,5 +25,7 @@ interface IDeviceIdleController {
String[] getSystemPowerWhitelist();
String[] getFullPowerWhitelist();
int[] getAppIdWhitelist();
+ int[] getAppIdTempWhitelist();
boolean isPowerSaveWhitelistApp(String name);
+ void addPowerSaveTempWhitelistApp(String name, long duration, int userId);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 1d9d7d2191ae..8b18f32c5e76 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -928,6 +928,14 @@ public final class PowerManager {
= "android.os.action.POWER_SAVE_WHITELIST_CHANGED";
/**
+ * @hide Intent that is broadcast when the set of temporarily whitelisted apps has changed.
+ * This broadcast is only sent to registered receivers.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED
+ = "android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED";
+
+ /**
* Intent that is broadcast when the state of {@link #isPowerSaveMode()} is about to change.
* This broadcast is only sent to registered receivers.
*
diff --git a/core/java/android/os/PowerManagerInternal.java b/core/java/android/os/PowerManagerInternal.java
index e5232858207d..e742f989c500 100644
--- a/core/java/android/os/PowerManagerInternal.java
+++ b/core/java/android/os/PowerManagerInternal.java
@@ -137,6 +137,8 @@ public abstract class PowerManagerInternal {
public abstract void setDeviceIdleWhitelist(int[] appids);
+ public abstract void setDeviceIdleTempWhitelist(int[] appids);
+
public abstract void updateUidProcState(int uid, int procState);
public abstract void uidGone(int uid);
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 76a5f9672121..df2e5f932456 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -7930,8 +7930,6 @@ public final class ContactsContract {
/**
* API for inquiring about the general status of the provider.
- *
- * @hide
*/
public static final class ProviderStatus {
@@ -7965,21 +7963,16 @@ public final class ContactsContract {
public static final int STATUS_NORMAL = 0;
/**
- * The status used when the provider is in the process of upgrading. Contacts
- * are temporarily unaccessible.
- */
- public static final int STATUS_UPGRADING = 1;
-
- /**
- * The status used during a locale change.
+ * The provider won't respond to queries. It is in the middle of a long running task, such
+ * as a database upgrade or locale change.
*/
- public static final int STATUS_CHANGING_LOCALE = 3;
+ public static final int STATUS_BUSY = 1;
/**
* The status that indicates that there are no accounts and no contacts
* on the device.
*/
- public static final int STATUS_NO_ACCOUNTS_NO_CONTACTS = 4;
+ public static final int STATUS_EMPTY = 2;
}
/**
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 7565654b7ae7..51dbdee3a23e 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -22,6 +22,7 @@ import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteException;
@@ -33,6 +34,7 @@ import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
+import android.service.media.CameraPrewarmService;
import android.util.Log;
import java.io.FileInputStream;
@@ -226,33 +228,24 @@ public final class MediaStore {
public static final String INTENT_ACTION_STILL_IMAGE_CAMERA = "android.media.action.STILL_IMAGE_CAMERA";
/**
- * The name of the Intent action used to indicate that a camera launch might be imminent. This
- * broadcast should be targeted to the package that is receiving
- * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or
- * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE}, depending on the context. If such
- * intent would launch the resolver activity, this broadcast should not be sent at all.
+ * Name under which an activity handling {@link #INTENT_ACTION_STILL_IMAGE_CAMERA} or
+ * {@link #INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE} publishes the service name for its prewarm
+ * service.
* <p>
- * A receiver of this broadcast should do the absolute minimum amount of work to initialize the
- * camera in order to reduce startup time in likely case that shortly after an actual camera
- * launch intent would be sent.
+ * This meta-data should reference the fully qualified class name of the prewarm service
+ * extending {@link CameraPrewarmService}.
* <p>
- * In case the actual intent will not be fired, the target package will receive
- * {@link #ACTION_STILL_IMAGE_CAMERA_COOLDOWN}. However, it is recommended that the receiver
- * also implements a timeout to close the camera after receiving this intent, as there is no
- * guarantee that {@link #ACTION_STILL_IMAGE_CAMERA_COOLDOWN} will be delivered.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_STILL_IMAGE_CAMERA_PREWARM = "android.media.action.STILL_IMAGE_CAMERA_PREWARM";
-
- /**
- * The name of the Intent action used to indicate that an imminent camera launch has been
- * cancelled by the user. This broadcast should be targeted to the package that has received
- * {@link #ACTION_STILL_IMAGE_CAMERA_PREWARM}.
+ * The prewarm service will get bound and receive a prewarm signal
+ * {@link CameraPrewarmService#onPrewarm()} when a camera launch intent fire might be imminent.
+ * An application implementing a prewarm service should do the absolute minimum amount of work
+ * to initialize the camera in order to reduce startup time in likely case that shortly after a
+ * camera launch intent would be sent.
* <p>
- * A receiver of this broadcast should close the camera immediately.
+ * If the camera launch intent gets fired shortly after, the service will be unbound
+ * asynchronously, without receiving
*/
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_STILL_IMAGE_CAMERA_COOLDOWN = "android.media.action.STILL_IMAGE_CAMERA_COOLDOWN";
+ public static final String META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE =
+ "android.media.still_image_camera_preview_service";
/**
* The name of the Intent action used to launch a camera in still image mode
@@ -2268,5 +2261,4 @@ public final class MediaStore {
}
return null;
}
-
}
diff --git a/core/java/android/service/media/CameraPrewarmService.java b/core/java/android/service/media/CameraPrewarmService.java
new file mode 100644
index 000000000000..335b00a50879
--- /dev/null
+++ b/core/java/android/service/media/CameraPrewarmService.java
@@ -0,0 +1,96 @@
+/*
+ * 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 android.service.media;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+
+/**
+ * Extend this class to implement a camera prewarm service. See
+ * {@link android.provider.MediaStore#META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE}.
+ */
+public abstract class CameraPrewarmService extends Service {
+
+ /**
+ * Intent action to bind the service as a prewarm service.
+ * @hide
+ */
+ public static final String ACTION_PREWARM =
+ "android.service.media.CameraPrewarmService.ACTION_PREWARM";
+
+ /**
+ * Message sent by the client indicating that the camera intent has been fired.
+ * @hide
+ */
+ public static final int MSG_CAMERA_FIRED = 1;
+
+ private final Handler mHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_CAMERA_FIRED:
+ mCameraIntentFired = true;
+ break;
+ default:
+ super.handleMessage(msg);
+ }
+ }
+ };
+ private boolean mCameraIntentFired;
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ if (ACTION_PREWARM.equals(intent.getAction())) {
+ onPrewarm();
+ return new Messenger(mHandler).getBinder();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean onUnbind(Intent intent) {
+ if (ACTION_PREWARM.equals(intent.getAction())) {
+ onCooldown(mCameraIntentFired);
+ }
+ return false;
+ }
+
+ /**
+ * Called when the camera should be prewarmed.
+ */
+ public abstract void onPrewarm();
+
+ /**
+ * Called when prewarm phase is done, either because the camera launch intent has been fired
+ * at this point or prewarm is no longer needed. A client should close the camera
+ * immediately in the latter case.
+ * <p>
+ * In case the camera launch intent has been fired, there is no guarantee about the ordering
+ * of these two events. Cooldown might happen either before or after the activity has been
+ * created that handles the camera intent.
+ *
+ * @param cameraIntentFired Indicates whether the intent to launch the camera has been
+ * fired.
+ */
+ public abstract void onCooldown(boolean cameraIntentFired);
+}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3e621b11f9ec..cfd504d3f5b4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -4510,7 +4510,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
attributes[i] = resourceName;
- attributes[i + 1] = t.getString(index, false);
+ attributes[i + 1] = t.getString(index);
i += 2;
}
@@ -6351,7 +6351,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
View next = rootView.findViewInsideOutShouldExist(this,
mAccessibilityTraversalBeforeId);
- if (next != null) {
+ if (next != null && next.includeForAccessibility()) {
info.setTraversalBefore(next);
}
}
@@ -6363,7 +6363,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
View next = rootView.findViewInsideOutShouldExist(this,
mAccessibilityTraversalAfterId);
- if (next != null) {
+ if (next != null && next.includeForAccessibility()) {
info.setTraversalAfter(next);
}
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index f0c86e52d4a3..45bc1df33469 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -309,6 +309,7 @@ public interface WindowManager extends ViewManager {
* Window type: a above sub-panel on top of an application window and it's
* sub-panel windows. These windows are displayed on top of their attached window
* and any {@link #TYPE_APPLICATION_SUB_PANEL} panels.
+ * @hide
*/
public static final int TYPE_APPLICATION_ABOVE_SUB_PANEL = FIRST_SUB_WINDOW + 5;
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 22c068083bfc..14065b18f3f2 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -289,6 +289,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private Rect mTempRect;
private Rect mOutsets = new Rect();
+ private boolean mIsStartingWindow;
+
static class WindowManagerHolder {
static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
ServiceManager.getService("window"));
@@ -3891,7 +3893,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// A pending invalidation will typically be resolved before the posted message
// would run normally in order to satisfy instance state restoration.
PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, false);
- if (!isDestroyed() && (st == null || st.menu == null)) {
+ if (!isDestroyed() && (st == null || st.menu == null) && !mIsStartingWindow) {
invalidatePanelMenu(FEATURE_ACTION_BAR);
}
} else {
@@ -4966,4 +4968,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mDecor.updateColorViews(null, false /* animate */);
}
}
+
+ public void setIsStartingWindow(boolean isStartingWindow) {
+ mIsStartingWindow = isStartingWindow;
+ }
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c7753654d230..439affe26ead 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -81,6 +81,7 @@
<protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
<protected-broadcast android:name="android.os.action.DEVICE_IDLE_MODE_CHANGED" />
<protected-broadcast android:name="android.os.action.POWER_SAVE_WHITELIST_CHANGED" />
+ <protected-broadcast android:name="android.os.action.POWER_SAVE_TEMP_WHITELIST_CHANGED" />
<protected-broadcast android:name="android.os.action.SCREEN_BRIGHTNESS_BOOST_CHANGED" />
@@ -2136,6 +2137,12 @@
<permission android:name="android.permission.CHANGE_APP_IDLE_STATE"
android:protectionLevel="signature" />
+ <!-- @hide @SystemApi Allows an application to temporarily whitelist an inactive app to
+ access the network and acquire wakelocks.
+ <p>Not for use by third-party applications. -->
+ <permission android:name="android.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST"
+ android:protectionLevel="system|signature" />
+
<!-- @SystemApi Allows an application to collect battery statistics -->
<permission android:name="android.permission.BATTERY_STATS"
android:protectionLevel="signature|system|development" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 93fcb2f5437e..45dad8d4fe76 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1785,16 +1785,11 @@
<java-symbol type="string" name="smv_process" />
<java-symbol type="string" name="tethered_notification_message" />
<java-symbol type="string" name="tethered_notification_title" />
- <java-symbol type="string" name="throttle_warning_notification_message" />
- <java-symbol type="string" name="throttle_warning_notification_title" />
- <java-symbol type="string" name="throttled_notification_message" />
- <java-symbol type="string" name="throttled_notification_title" />
<java-symbol type="string" name="usb_accessory_notification_title" />
<java-symbol type="string" name="usb_cd_installer_notification_title" />
<java-symbol type="string" name="usb_mtp_notification_title" />
<java-symbol type="string" name="usb_charging_notification_title" />
<java-symbol type="string" name="usb_notification_message" />
- <java-symbol type="string" name="use_physical_keyboard" />
<java-symbol type="string" name="usb_ptp_notification_title" />
<java-symbol type="string" name="usb_midi_notification_title" />
<java-symbol type="string" name="vpn_text" />
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 2cf30ba83e5c..cd4b24a9e178 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -60,6 +60,7 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback {
protected ViewMediatorCallback mViewMediatorCallback;
protected LockPatternUtils mLockPatternUtils;
private OnDismissAction mDismissAction;
+ private Runnable mCancelAction;
private final KeyguardUpdateMonitorCallback mUpdateCallback =
new KeyguardUpdateMonitorCallback() {
@@ -126,8 +127,17 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback {
*
* @param action
*/
- public void setOnDismissAction(OnDismissAction action) {
+ public void setOnDismissAction(OnDismissAction action, Runnable cancelAction) {
+ if (mCancelAction != null) {
+ mCancelAction.run();
+ mCancelAction = null;
+ }
mDismissAction = action;
+ mCancelAction = cancelAction;
+ }
+
+ public void cancelDismissAction() {
+ setOnDismissAction(null, null);
}
@Override
@@ -197,6 +207,7 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback {
if (mDismissAction != null) {
deferKeyguardDone = mDismissAction.onDismiss();
mDismissAction = null;
+ mCancelAction = null;
}
if (mViewMediatorCallback != null) {
if (deferKeyguardDone) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
index e3d2a9942763..0380e217b97b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
@@ -217,4 +217,8 @@ public final class LocalBluetoothAdapter {
syncBluetoothState();
}
}
+
+ public BluetoothDevice getRemoteDevice(String address) {
+ return mAdapter.getRemoteDevice(address);
+ }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index f32493375e9e..cf3b7c873d59 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -357,17 +357,19 @@ public class WifiTracker {
}
private void updateNetworkInfo(NetworkInfo networkInfo) {
- /* sticky broadcasts can call this when wifi is disabled */
- if (!mWifiManager.isWifiEnabled()) {
- mScanner.pause();
- return;
- }
+ if (mScanner != null) {
+ /* sticky broadcasts can call this when wifi is disabled */
+ if (!mWifiManager.isWifiEnabled()) {
+ mScanner.pause();
+ return;
+ }
- if (networkInfo != null &&
- networkInfo.getDetailedState() == DetailedState.OBTAINING_IPADDR) {
- mScanner.pause();
- } else {
- mScanner.resume();
+ if (networkInfo != null &&
+ networkInfo.getDetailedState() == DetailedState.OBTAINING_IPADDR) {
+ mScanner.pause();
+ } else {
+ mScanner.resume();
+ }
}
mLastInfo = mWifiManager.getConnectionInfo();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index bc4210598bc8..0dcc0b9944eb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -33,6 +33,7 @@ import android.content.pm.UserInfo;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Bundle;
+import android.os.DeadObjectException;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -381,14 +382,17 @@ public class KeyguardViewMediator extends SystemUI {
+ ",state=" + simState + ")");
}
- try {
- int size = mKeyguardStateCallbacks.size();
- boolean simPinSecure = mUpdateMonitor.isSimPinSecure();
- for (int i = 0; i < size; i++) {
+ int size = mKeyguardStateCallbacks.size();
+ boolean simPinSecure = mUpdateMonitor.isSimPinSecure();
+ for (int i = size - 1; i >= 0; i--) {
+ try {
mKeyguardStateCallbacks.get(i).onSimSecureStateChanged(simPinSecure);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onSimSecureStateChanged", e);
+ if (e instanceof DeadObjectException) {
+ mKeyguardStateCallbacks.remove(i);
+ }
}
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onSimSecureStateChanged", e);
}
switch (simState) {
@@ -551,6 +555,7 @@ public class KeyguardViewMediator extends SystemUI {
// Assume keyguard is showing (unless it's disabled) until we know for sure...
setShowingLocked(!shouldWaitForProvisioning() && !mLockPatternUtils.isLockScreenDisabled(
KeyguardUpdateMonitor.getCurrentUser()));
+ updateInputRestrictedLocked();
mTrustManager.reportKeyguardShowingChanged();
mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,
@@ -954,13 +959,16 @@ public class KeyguardViewMediator extends SystemUI {
boolean inputRestricted = isInputRestricted();
if (mInputRestricted != inputRestricted) {
mInputRestricted = inputRestricted;
- try {
- int size = mKeyguardStateCallbacks.size();
- for (int i = 0; i < size; i++) {
+ int size = mKeyguardStateCallbacks.size();
+ for (int i = size - 1; i >= 0; i--) {
+ try {
mKeyguardStateCallbacks.get(i).onInputRestrictedStateChanged(inputRestricted);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onDeviceProvisioned", e);
+ if (e instanceof DeadObjectException) {
+ mKeyguardStateCallbacks.remove(i);
+ }
}
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onDeviceProvisioned", e);
}
}
}
@@ -1544,13 +1552,16 @@ public class KeyguardViewMediator extends SystemUI {
private void setShowingLocked(boolean showing) {
if (showing != mShowing) {
mShowing = showing;
- try {
- int size = mKeyguardStateCallbacks.size();
- for (int i = 0; i < size; i++) {
+ int size = mKeyguardStateCallbacks.size();
+ for (int i = size - 1; i >= 0; i--) {
+ try {
mKeyguardStateCallbacks.get(i).onShowingStateChanged(showing);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to call onShowingStateChanged", e);
+ if (e instanceof DeadObjectException) {
+ mKeyguardStateCallbacks.remove(i);
+ }
}
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onShowingStateChanged", e);
}
updateInputRestrictedLocked();
mTrustManager.reportKeyguardShowingChanged();
@@ -1565,7 +1576,7 @@ public class KeyguardViewMediator extends SystemUI {
callback.onShowingStateChanged(mShowing);
callback.onInputRestrictedStateChanged(mInputRestricted);
} catch (RemoteException e) {
- Slog.w(TAG, "Failed to call onShowingStateChanged or onSimSecureStateChanged", e);
+ Slog.w(TAG, "Failed to call onShowingStateChanged or onSimSecureStateChanged or onInputRestrictedStateChanged", e);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 6d0236587e5b..9e3cf37dd6a3 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -180,7 +180,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
.setColor(r.getColor(com.android.internal.R.color.system_notification_accent_color));
mNotificationStyle = new Notification.BigPictureStyle()
- .bigPicture(picture);
+ .bigPicture(picture.createAshmemBitmap());
mNotificationBuilder.setStyle(mNotificationStyle);
// For "public" situations we want to show all the same info but
@@ -203,7 +203,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
// On the tablet, the large icon makes the notification appear as if it is clickable (and
// on small devices, the large icon is not shown) so defer showing the large icon until
// we compose the final post-save notification below.
- mNotificationBuilder.setLargeIcon(icon);
+ mNotificationBuilder.setLargeIcon(icon.createAshmemBitmap());
// But we still don't set it for the expanded view, allowing the smallIcon to show here.
mNotificationStyle.bigLargeIcon((Bitmap) null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
index ee5eb38621e3..9ef320bc3fd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarter.java
@@ -24,6 +24,11 @@ import android.content.Intent;
* Keyguard.
*/
public interface ActivityStarter {
- public void startActivity(Intent intent, boolean dismissShade);
+ void startActivity(Intent intent, boolean dismissShade);
+ void startActivity(Intent intent, boolean dismissShade, Callback callback);
void preventNextAnimation();
+
+ interface Callback {
+ void onActivityStarted(int resultCode);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
index 8bffdc91e79b..64735eec4074 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardAffordanceHelper.java
@@ -160,7 +160,7 @@ public class KeyguardAffordanceHelper {
} else {
mTouchSlopExeeded = false;
}
- mCallback.onSwipingStarted(targetView == mLeftIcon);
+ mCallback.onSwipingStarted(targetView == mRightIcon);
mSwipingInProgress = true;
mTargetedView = targetView;
mInitialTouchX = x;
@@ -550,7 +550,7 @@ public class KeyguardAffordanceHelper {
float getMaxTranslationDistance();
- void onSwipingStarted(boolean isRightwardMotion);
+ void onSwipingStarted(boolean rightIcon);
void onSwipingAborted();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index adee5a8ae6fb..3258a9f93201 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -16,12 +16,17 @@
package com.android.systemui.statusbar.phone;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
+import android.app.Application;
import android.app.admin.DevicePolicyManager;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration;
@@ -29,9 +34,13 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.MediaStore;
+import android.service.media.CameraPrewarmService;
import android.telecom.TelecomManager;
import android.util.AttributeSet;
import android.util.Log;
@@ -100,7 +109,23 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
private PhoneStatusBar mPhoneStatusBar;
private final Interpolator mLinearOutSlowInInterpolator;
- private boolean mPrewarmSent;
+ private boolean mPrewarmBound;
+ private Messenger mPrewarmMessenger;
+ private final ServiceConnection mPrewarmConnection = new ServiceConnection() {
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mPrewarmMessenger = new Messenger(service);
+ mPrewarmBound = true;
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mPrewarmBound = false;
+ mPrewarmMessenger = null;
+ }
+ };
+
private boolean mLeftIsVoiceAssist;
private AssistManager mAssistManager;
@@ -343,37 +368,44 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
mLockPatternUtils.requireCredentialEntry(KeyguardUpdateMonitor.getCurrentUser());
}
- public void prewarmCamera() {
+ public void bindCameraPrewarmService() {
Intent intent = getCameraIntent();
- String targetPackage = PreviewInflater.getTargetPackage(mContext, intent,
+ ActivityInfo targetInfo = PreviewInflater.getTargetActivityInfo(mContext, intent,
KeyguardUpdateMonitor.getCurrentUser());
- if (targetPackage != null) {
- Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_PREWARM);
- prewarm.setPackage(targetPackage);
- mPrewarmSent = true;
- mContext.sendBroadcast(prewarm);
+ if (targetInfo != null) {
+ String clazz = targetInfo.metaData.getString(
+ MediaStore.META_DATA_STILL_IMAGE_CAMERA_PREWARM_SERVICE);
+ if (clazz != null) {
+ Intent serviceIntent = new Intent();
+ serviceIntent.setClassName(targetInfo.packageName, clazz);
+ serviceIntent.setAction(CameraPrewarmService.ACTION_PREWARM);
+ try {
+ getContext().bindServiceAsUser(serviceIntent, mPrewarmConnection,
+ Context.BIND_AUTO_CREATE, new UserHandle(UserHandle.USER_CURRENT));
+ } catch (SecurityException e) {
+ Log.w(TAG, "Unable to bind to prewarm service package=" + targetInfo.packageName
+ + " class=" + clazz, e);
+ }
+ }
}
}
- public void maybeCooldownCamera() {
- if (!mPrewarmSent) {
- return;
- }
- mPrewarmSent = false;
- Intent intent = getCameraIntent();
- String targetPackage = PreviewInflater.getTargetPackage(mContext, intent,
- KeyguardUpdateMonitor.getCurrentUser());
- if (targetPackage != null) {
- Intent prewarm = new Intent(MediaStore.ACTION_STILL_IMAGE_CAMERA_COOLDOWN);
- prewarm.setPackage(targetPackage);
- mContext.sendBroadcast(prewarm);
+ public void unbindCameraPrewarmService(boolean launched) {
+ if (mPrewarmBound) {
+ if (launched) {
+ try {
+ mPrewarmMessenger.send(Message.obtain(null /* handler */,
+ CameraPrewarmService.MSG_CAMERA_FIRED));
+ } catch (RemoteException e) {
+ Log.w(TAG, "Error sending camera fired message", e);
+ }
+ }
+ mContext.unbindService(mPrewarmConnection);
+ mPrewarmBound = false;
}
}
public void launchCamera() {
-
- // Reset prewarm state.
- mPrewarmSent = false;
final Intent intent = getCameraIntent();
boolean wouldLaunchResolverActivity = PreviewInflater.wouldLaunchResolverActivity(
mContext, intent, KeyguardUpdateMonitor.getCurrentUser());
@@ -381,18 +413,47 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
AsyncTask.execute(new Runnable() {
@Override
public void run() {
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+ int result = ActivityManager.START_CANCELED;
+ try {
+ result = ActivityManagerNative.getDefault().startActivityAsUser(
+ null, getContext().getBasePackageName(),
+ intent,
+ intent.resolveTypeIfNeeded(getContext().getContentResolver()),
+ null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null,
+ UserHandle.CURRENT.getIdentifier());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Unable to start camera activity", e);
+ }
mActivityStarter.preventNextAnimation();
+ final boolean launched = isSuccessfulLaunch(result);
+ post(new Runnable() {
+ @Override
+ public void run() {
+ unbindCameraPrewarmService(launched);
+ }
+ });
}
});
} else {
// We need to delay starting the activity because ResolverActivity finishes itself if
// launched behind lockscreen.
- mActivityStarter.startActivity(intent, false /* dismissShade */);
+ mActivityStarter.startActivity(intent, false /* dismissShade */,
+ new ActivityStarter.Callback() {
+ @Override
+ public void onActivityStarted(int resultCode) {
+ unbindCameraPrewarmService(isSuccessfulLaunch(resultCode));
+ }
+ });
}
}
+ private static boolean isSuccessfulLaunch(int result) {
+ return result == ActivityManager.START_SUCCESS
+ || result == ActivityManager.START_DELIVERED_TO_TOP
+ || result == ActivityManager.START_TASK_TO_FRONT;
+ }
+
public void launchLeftAffordance() {
if (mLeftIsVoiceAssist) {
launchVoiceAssist();
@@ -412,8 +473,8 @@ public class KeyguardBottomAreaView extends FrameLayout implements View.OnClickL
if (mPhoneStatusBar.isKeyguardCurrentlySecure()) {
AsyncTask.execute(runnable);
} else {
- mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, false /* dismissShade */,
- false /* afterKeyguardGone */);
+ mPhoneStatusBar.executeRunnableDismissingKeyguard(runnable, null /* cancelAction */,
+ false /* dismissShade */, false /* afterKeyguardGone */);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 262d955957fe..3d57d54ef822 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -95,16 +95,16 @@ public class KeyguardBouncer {
mShowingSoon = false;
}
- public void showWithDismissAction(OnDismissAction r) {
+ public void showWithDismissAction(OnDismissAction r, Runnable cancelAction) {
ensureView();
- mKeyguardView.setOnDismissAction(r);
+ mKeyguardView.setOnDismissAction(r, cancelAction);
show(false /* resetSecuritySelection */);
}
public void hide(boolean destroyView) {
cancelShowRunnable();
if (mKeyguardView != null) {
- mKeyguardView.setOnDismissAction(null);
+ mKeyguardView.cancelDismissAction();
mKeyguardView.cleanUp();
}
if (destroyView) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 5d48190dbf99..2fe98bb5748d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1934,12 +1934,12 @@ public class NotificationPanelView extends PanelView implements
}
@Override
- public void onSwipingStarted(boolean isRightwardMotion) {
- boolean start = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? isRightwardMotion
- : !isRightwardMotion;
- if (!start) {
+ public void onSwipingStarted(boolean rightIcon) {
+ boolean camera = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? !rightIcon
+ : rightIcon;
+ if (camera) {
mSecureCameraLaunchManager.onSwipingStarted();
- mKeyguardBottomArea.prewarmCamera();
+ mKeyguardBottomArea.bindCameraPrewarmService();
}
requestDisallowInterceptTouchEvent(true);
mOnlyAffordanceInThisMotion = true;
@@ -1948,7 +1948,7 @@ public class NotificationPanelView extends PanelView implements
@Override
public void onSwipingAborted() {
- mKeyguardBottomArea.maybeCooldownCamera();
+ mKeyguardBottomArea.unbindCameraPrewarmService(false /* launched */);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 5ff4ddbd8847..bc957438b721 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1830,6 +1830,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
@Override
+ public void startActivity(Intent intent, boolean dismissShade, Callback callback) {
+ startActivityDismissingKeyguard(intent, false, dismissShade, callback);
+ }
+
+ @Override
public void preventNextAnimation() {
overrideActivityPendingAppTransition(true /* keyguardShowing */);
}
@@ -2711,7 +2716,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
- final boolean dismissShade) {
+ boolean dismissShade) {
+ startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, null /* callback */);
+ }
+
+ public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
+ final boolean dismissShade, final Callback callback) {
if (onlyProvisioned && !isDeviceProvisioned()) return;
final boolean afterKeyguardGone = PreviewInflater.wouldLaunchResolverActivity(
@@ -2721,16 +2731,35 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public void run() {
intent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
- mContext.startActivityAsUser(
- intent, new UserHandle(UserHandle.USER_CURRENT));
+ int result = ActivityManager.START_CANCELED;
+ try {
+ result = ActivityManagerNative.getDefault().startActivityAsUser(
+ null, mContext.getBasePackageName(),
+ intent,
+ intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null,
+ UserHandle.CURRENT.getIdentifier());
+ } catch (RemoteException e) {
+ Log.w(TAG, "Unable to start activity", e);
+ }
overrideActivityPendingAppTransition(
keyguardShowing && !afterKeyguardGone);
+ if (callback != null) {
+ callback.onActivityStarted(result);
+ }
}
};
- executeRunnableDismissingKeyguard(runnable, dismissShade, afterKeyguardGone);
+ Runnable cancelRunnable = new Runnable() {
+ @Override
+ public void run() {
+ callback.onActivityStarted(ActivityManager.START_CANCELED);
+ }
+ };
+ executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShade, afterKeyguardGone);
}
public void executeRunnableDismissingKeyguard(final Runnable runnable,
+ final Runnable cancelAction,
final boolean dismissShade,
final boolean afterKeyguardGone) {
final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
@@ -2757,7 +2786,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
return true;
}
- }, afterKeyguardGone);
+ }, cancelAction, afterKeyguardGone);
}
private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -2817,10 +2846,15 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
@Override
- protected void dismissKeyguardThenExecute(final OnDismissAction action,
+ protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
+ dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
+ }
+
+ private void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
boolean afterKeyguardGone) {
if (mStatusBarKeyguardViewManager.isShowing()) {
- mStatusBarKeyguardViewManager.dismissWithAction(action, afterKeyguardGone);
+ mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
+ afterKeyguardGone);
} else {
action.onDismiss();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 0caf51af9807..6cb890a28191 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -126,10 +126,11 @@ public class StatusBarKeyguardViewManager {
updateStates();
}
- public void dismissWithAction(OnDismissAction r, boolean afterKeyguardGone) {
+ public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
+ boolean afterKeyguardGone) {
if (mShowing) {
if (!afterKeyguardGone) {
- mBouncer.showWithDismissAction(r);
+ mBouncer.showWithDismissAction(r, cancelAction);
} else {
mBouncer.show(false /* resetSecuritySelection */);
mAfterKeyguardGoneAction = r;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index cfc95bfba372..686e24c1655d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -272,7 +272,7 @@ public class MobileSignalController extends SignalController<
}
private boolean isCarrierNetworkChangeActive() {
- return !hasService() && mCurrentState.carrierNetworkChangeMode;
+ return mCurrentState.carrierNetworkChangeMode;
}
public void handleBroadcast(Intent intent) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
index 4269c1956832..93d0ec362ade 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/PreviewInflater.java
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.policy;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
@@ -138,14 +139,14 @@ public class PreviewInflater {
public static boolean wouldLaunchResolverActivity(Context ctx, Intent intent,
int currentUserId) {
- return getTargetPackage(ctx, intent, currentUserId) == null;
+ return getTargetActivityInfo(ctx, intent, currentUserId) == null;
}
/**
- * @return the target package of the intent it resolves to a specific package or {@code null} if
- * it resolved to the resolver activity
+ * @return the target activity info of the intent it resolves to a specific package or
+ * {@code null} if it resolved to the resolver activity
*/
- public static String getTargetPackage(Context ctx, Intent intent,
+ public static ActivityInfo getTargetActivityInfo(Context ctx, Intent intent,
int currentUserId) {
PackageManager packageManager = ctx.getPackageManager();
final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
@@ -158,7 +159,7 @@ public class PreviewInflater {
if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) {
return null;
} else {
- return resolved.activityInfo.packageName;
+ return resolved.activityInfo;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index dd6f272404a5..2df19803b6e6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -391,35 +391,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
}
- public void testCarrierNetworkChange_carrierNetworkChangeWhileConnected() {
- int strength = SignalStrength.SIGNAL_STRENGTH_GREAT;
-
- setupDefaultSignal();
- setLevel(strength);
-
- // API call is made
- setCarrierNetworkChange(true /* enabled */);
-
- // Boolean value is set, but we still have a signal, should be showing normal
- verifyLastMobileDataIndicators(true /* visible */,
- TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */,
- DEFAULT_ICON /* typeIcon */);
-
- // Lose voice but still have data
- setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
- verifyLastMobileDataIndicators(true /* visible */,
- TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */,
- DEFAULT_ICON /* typeIcon */);
-
- // Voice but no data
- setVoiceRegState(ServiceState.STATE_IN_SERVICE);
- setDataRegState(ServiceState.STATE_OUT_OF_SERVICE);
- verifyLastMobileDataIndicators(true /* visible */,
- TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */,
- DEFAULT_ICON /* typeIcon */);
- }
-
- public void testCarrierNetworkChange_carrierNetworkChangeWhileDisconnected() {
+ public void testCarrierNetworkChange_carrierNetworkChange() {
int strength = SignalStrength.SIGNAL_STRENGTH_GREAT;
setupDefaultSignal();
@@ -430,20 +402,16 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
TelephonyIcons.TELEPHONY_SIGNAL_STRENGTH[1][strength] /* strengthIcon */,
DEFAULT_ICON /* typeIcon */);
- // API call is made and all connectivity lost
+ // API call is made
setCarrierNetworkChange(true /* enabled */);
- setVoiceRegState(ServiceState.STATE_OUT_OF_SERVICE);
- setDataRegState(ServiceState.STATE_OUT_OF_SERVICE);
- // Out of service and carrier network change is true, show special indicator
+ // Carrier network change is true, show special indicator
verifyLastMobileDataIndicators(true /* visible */,
TelephonyIcons.TELEPHONY_CARRIER_NETWORK_CHANGE[0][0] /* strengthIcon */,
0 /* typeIcon */);
// Revert back
setCarrierNetworkChange(false /* enabled */);
- setVoiceRegState(ServiceState.STATE_IN_SERVICE);
- setDataRegState(ServiceState.STATE_IN_SERVICE);
// Verify back in previous state
verifyLastMobileDataIndicators(true /* visible */,
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 9b7b2d3c8da4..e9759c3e8744 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -16,14 +16,19 @@
package com.android.server;
+import android.Manifest;
+import android.app.ActivityManagerNative;
import android.app.AlarmManager;
+import android.app.AppGlobals;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
@@ -47,7 +52,9 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.Xml;
import android.view.Display;
@@ -55,6 +62,7 @@ import android.view.Display;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.AtomicFile;
import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
@@ -72,6 +80,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
/**
* Keeps track of device idleness and drives low power mode based on that.
@@ -79,7 +88,8 @@ import java.nio.charset.StandardCharsets;
public class DeviceIdleController extends SystemService {
private static final String TAG = "DeviceIdleController";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final boolean DEBUG = false;
+ private static final boolean COMPRESS_TIME = false;
public static final String SERVICE_NAME = "deviceidle";
@@ -94,29 +104,31 @@ public class DeviceIdleController extends SystemService {
* immediately after going inactive just because we don't want to be continually running
* the significant motion sensor whenever the screen is off.
*/
- private static final long DEFAULT_INACTIVE_TIMEOUT = !DEBUG ? 30*60*1000L
- : 2 * 60 * 1000L;
+ private static final long DEFAULT_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 30*60*1000L
+ : 3 * 60 * 1000L;
/**
* This is the time, after seeing motion, that we wait after becoming inactive from
* that until we start looking for motion again.
*/
- private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = !DEBUG ? 10*60*1000L
+ private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 10*60*1000L
: 60 * 1000L;
/**
* This is the time, after the inactive timeout elapses, that we will wait looking
* for significant motion until we truly consider the device to be idle.
*/
- private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = !DEBUG ? 30*60*1000L
- : 2 * 60 * 1000L;
+ private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = !COMPRESS_TIME ? 30*60*1000L
+ : 3 * 60 * 1000L;
/**
* This is the initial time, after being idle, that we will allow ourself to be back
* in the IDLE_PENDING state allowing the system to run normally until we return to idle.
*/
- private static final long DEFAULT_IDLE_PENDING_TIMEOUT = 5*60*1000L;
+ private static final long DEFAULT_IDLE_PENDING_TIMEOUT = !COMPRESS_TIME ? 5*60*1000L
+ : 30 * 1000L;
/**
* Maximum pending idle timeout (time spent running) we will be allowed to use.
*/
- private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = 10*60*1000L;
+ private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = !COMPRESS_TIME ? 10*60*1000L
+ : 60 * 1000L;
/**
* Scaling factor to apply to current pending idle timeout each time we cycle through
* that state.
@@ -126,13 +138,13 @@ public class DeviceIdleController extends SystemService {
* This is the initial time that we want to sit in the idle state before waking up
* again to return to pending idle and allowing normal work to run.
*/
- private static final long DEFAULT_IDLE_TIMEOUT = !DEBUG ? 60*60*1000L
- : 5 * 60 * 1000L;
+ private static final long DEFAULT_IDLE_TIMEOUT = !COMPRESS_TIME ? 60*60*1000L
+ : 6 * 60 * 1000L;
/**
* Maximum idle duration we will be allowed to use.
*/
- private static final long DEFAULT_MAX_IDLE_TIMEOUT = !DEBUG ? 6*60*60*1000L
- : 10 * 60 * 1000L;
+ private static final long DEFAULT_MAX_IDLE_TIMEOUT = !COMPRESS_TIME ? 6*60*60*1000L
+ : 30 * 60 * 1000L;
/**
* Scaling factor to apply to current idle timeout each time we cycle through that state.
*/
@@ -141,8 +153,13 @@ public class DeviceIdleController extends SystemService {
* This is the minimum time we will allow until the next upcoming alarm for us to
* actually go in to idle mode.
*/
- private static final long DEFAULT_MIN_TIME_TO_ALARM = !DEBUG ? 60*60*1000L
- : 5 * 60 * 1000L;
+ private static final long DEFAULT_MIN_TIME_TO_ALARM = !COMPRESS_TIME ? 60*60*1000L
+ : 6 * 60 * 1000L;
+
+ /**
+ * Max amount of time to temporarily whitelist an app when it receives a high priority tickle.
+ */
+ private static final long MAX_TEMP_APP_WHITELIST_DURATION = 5 * 60 * 1000L;
private AlarmManager mAlarmManager;
private IBatteryStats mBatteryStats;
@@ -210,6 +227,17 @@ public class DeviceIdleController extends SystemService {
*/
private int[] mPowerSaveWhitelistAppIdArray = new int[0];
+ /**
+ * List of end times for UIDs that are temporarily marked as being allowed to access
+ * the network and acquire wakelocks. Times are in milliseconds.
+ */
+ private SparseLongArray mTempWhitelistAppIdEndTimes = new SparseLongArray();
+
+ /**
+ * Current app IDs of temporarily whitelist apps for high-priority messages.
+ */
+ private int[] mTempWhitelistAppIdArray = new int[0];
+
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
@@ -252,6 +280,7 @@ public class DeviceIdleController extends SystemService {
static final int MSG_REPORT_IDLE_ON = 2;
static final int MSG_REPORT_IDLE_OFF = 3;
static final int MSG_REPORT_ACTIVE = 4;
+ static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 5;
final class MyHandler extends Handler {
MyHandler(Looper looper) {
@@ -294,6 +323,10 @@ public class DeviceIdleController extends SystemService {
getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
}
} break;
+ case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
+ int uid = msg.arg1;
+ checkTempAppWhitelistTimeout(uid);
+ } break;
}
}
}
@@ -325,10 +358,39 @@ public class DeviceIdleController extends SystemService {
return getAppIdWhitelistInternal();
}
+ @Override public int[] getAppIdTempWhitelist() {
+ return getAppIdTempWhitelistInternal();
+ }
+
@Override public boolean isPowerSaveWhitelistApp(String name) {
return isPowerSaveWhitelistAppInternal(name);
}
+ @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
+ int userId) throws RemoteException {
+ getContext().enforceCallingPermission(
+ Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
+ "No permission to change device idle whitelist");
+ userId = ActivityManagerNative.getDefault().handleIncomingUser(
+ Binder.getCallingPid(),
+ Binder.getCallingUid(),
+ userId,
+ /*allowAll=*/ false,
+ /*requireFull=*/ false,
+ "addAppBrieflyToWhitelist", null);
+ final long token = Binder.clearCallingIdentity();
+ try {
+ PackageInfo pi = AppGlobals.getPackageManager()
+ .getPackageInfo(packageName, 0, userId);
+ if (pi == null) return;
+ DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(packageName,
+ duration, userId);
+ } catch (RemoteException re) {
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
@Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
DeviceIdleController.this.dump(fd, pw, args);
}
@@ -481,6 +543,70 @@ public class DeviceIdleController extends SystemService {
}
}
+ public int[] getAppIdTempWhitelistInternal() {
+ synchronized (this) {
+ return mTempWhitelistAppIdArray;
+ }
+ }
+
+ /**
+ * Adds an app to the temporary whitelist and resets the endTime for granting the
+ * app an exemption to access network and acquire wakelocks.
+ */
+ public void addPowerSaveTempWhitelistAppInternal(String packageName, long duration,
+ int userId) {
+ if (duration > MAX_TEMP_APP_WHITELIST_DURATION) {
+ duration = MAX_TEMP_APP_WHITELIST_DURATION;
+ }
+ try {
+ int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
+ int appId = UserHandle.getAppId(uid);
+ final long timeNow = System.currentTimeMillis();
+ synchronized (this) {
+ long currentEndTime = mTempWhitelistAppIdEndTimes.get(appId);
+ // Set the new end time
+ mTempWhitelistAppIdEndTimes.put(appId, timeNow + duration);
+ if (DEBUG) {
+ Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
+ }
+ if (currentEndTime == 0) {
+ // No pending timeout for the app id, post a delayed message
+ postTempActiveTimeoutMessage(appId, duration);
+ updateTempWhitelistAppIdsLocked();
+ reportTempWhitelistChangedLocked();
+ }
+ }
+ } catch (NameNotFoundException e) {
+ }
+ }
+
+ private void postTempActiveTimeoutMessage(int uid, long delay) {
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
+ delay);
+ }
+
+ void checkTempAppWhitelistTimeout(int uid) {
+ final long timeNow = System.currentTimeMillis();
+ synchronized (this) {
+ long endTime = mTempWhitelistAppIdEndTimes.get(uid);
+ if (endTime == 0) {
+ // Nothing to do
+ return;
+ }
+ if (timeNow >= endTime) {
+ mTempWhitelistAppIdEndTimes.delete(uid);
+ if (DEBUG) {
+ Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
+ }
+ updateTempWhitelistAppIdsLocked();
+ reportTempWhitelistChangedLocked();
+ } else {
+ // Need more time
+ postTempActiveTimeoutMessage(uid, endTime - timeNow);
+ }
+ }
+ }
+
void updateDisplayLocked() {
mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
// We consider any situation where the display is showing something to be it on,
@@ -659,14 +785,41 @@ public class DeviceIdleController extends SystemService {
}
mPowerSaveWhitelistAppIdArray = appids;
if (mLocalPowerManager != null) {
+ if (DEBUG) {
+ Slog.d(TAG, "Setting wakelock whitelist to "
+ + Arrays.toString(mPowerSaveWhitelistAppIdArray));
+ }
mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAppIdArray);
}
}
+ private void updateTempWhitelistAppIdsLocked() {
+ final int size = mTempWhitelistAppIdEndTimes.size();
+ if (mTempWhitelistAppIdArray.length != size) {
+ mTempWhitelistAppIdArray = new int[size];
+ }
+ for (int i = 0; i < size; i++) {
+ mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
+ }
+ if (mLocalPowerManager != null) {
+ if (DEBUG) {
+ Slog.d(TAG, "Setting wakelock temp whitelist to "
+ + Arrays.toString(mTempWhitelistAppIdArray));
+ }
+ mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
+ }
+ }
+
private void reportPowerSaveWhitelistChangedLocked() {
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- getContext().sendBroadcast(intent);
+ getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
+ }
+
+ private void reportTempWhitelistChangedLocked() {
+ Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
}
void readConfigFileLocked() {
@@ -817,11 +970,18 @@ public class DeviceIdleController extends SystemService {
}
if (args != null) {
+ int userId = UserHandle.USER_OWNER;
for (int i=0; i<args.length; i++) {
String arg = args[i];
if ("-h".equals(arg)) {
dumpHelp(pw);
return;
+ } else if ("-u".equals(arg)) {
+ i++;
+ if (i < args.length) {
+ arg = args[i];
+ userId = Integer.parseInt(arg);
+ }
} else if ("-a".equals(arg)) {
// Ignore, we always dump all.
} else if ("step".equals(arg)) {
@@ -873,6 +1033,17 @@ public class DeviceIdleController extends SystemService {
}
}
return;
+ } else if ("tempwhitelist".equals(arg)) {
+ i++;
+ if (i >= args.length) {
+ pw.println("At least one package name must be specified");
+ return;
+ }
+ while (i < args.length) {
+ arg = args[i];
+ i++;
+ addPowerSaveTempWhitelistAppInternal(arg, 10000L, userId);
+ }
} else if (arg.length() > 0 && arg.charAt(0) == '-'){
pw.println("Unknown option: " + arg);
return;
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d214a20176cd..3315c89daa28 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.accounts;
import android.Manifest;
+import android.accounts.AbstractAccountAuthenticator;
import android.accounts.Account;
import android.accounts.AccountAndUser;
import android.accounts.AccountAuthenticatorResponse;
@@ -49,6 +50,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.RegisteredServicesCache;
import android.content.pm.RegisteredServicesCacheListener;
import android.content.pm.ResolveInfo;
+import android.content.pm.Signature;
import android.content.pm.UserInfo;
import android.database.Cursor;
import android.database.DatabaseUtils;
@@ -84,6 +86,11 @@ import com.google.android.collect.Sets;
import java.io.File;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@@ -93,6 +100,7 @@ import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
@@ -166,6 +174,10 @@ public class AccountManagerService
private static final String[] ACCOUNT_TYPE_COUNT_PROJECTION =
new String[] { ACCOUNTS_TYPE, ACCOUNTS_TYPE_COUNT};
private static final Intent ACCOUNTS_CHANGED_INTENT;
+ static {
+ ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
+ ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ }
private static final String COUNT_OF_MATCHING_GRANTS = ""
+ "SELECT COUNT(*) FROM " + TABLE_GRANTS + ", " + TABLE_ACCOUNTS
@@ -177,6 +189,7 @@ public class AccountManagerService
private static final String SELECTION_AUTHTOKENS_BY_ACCOUNT =
AUTHTOKENS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?)";
+
private static final String[] COLUMNS_AUTHTOKENS_TYPE_AND_AUTHTOKEN = {AUTHTOKENS_TYPE,
AUTHTOKENS_AUTHTOKEN};
@@ -205,6 +218,10 @@ public class AccountManagerService
/** protected by the {@link #cacheLock} */
private final HashMap<Account, HashMap<String, String>> authTokenCache =
new HashMap<Account, HashMap<String, String>>();
+
+ /** protected by the {@link #cacheLock} */
+ private final HashMap<Account, WeakReference<TokenCache>> accountTokenCaches = new HashMap<>();
+
/**
* protected by the {@link #cacheLock}
*
@@ -237,12 +254,6 @@ public class AccountManagerService
new AtomicReference<AccountManagerService>();
private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[]{};
- static {
- ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
- ACCOUNTS_CHANGED_INTENT.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
- }
-
-
/**
* This should only be called by system code. One should only call this after the service
* has started.
@@ -425,6 +436,7 @@ public class AccountManagerService
final Account account = new Account(accountName, accountType);
accounts.userDataCache.remove(account);
accounts.authTokenCache.remove(account);
+ accounts.accountTokenCaches.remove(account);
} else {
ArrayList<String> accountNames = accountNamesByType.get(accountType);
if (accountNames == null) {
@@ -1337,9 +1349,10 @@ public class AccountManagerService
@Override
public void invalidateAuthToken(String accountType, String authToken) {
+ int callerUid = Binder.getCallingUid();
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "invalidateAuthToken: accountType " + accountType
- + ", caller's uid " + Binder.getCallingUid()
+ + ", caller's uid " + callerUid
+ ", pid " + Binder.getCallingPid());
}
if (accountType == null) throw new IllegalArgumentException("accountType is null");
@@ -1353,6 +1366,7 @@ public class AccountManagerService
db.beginTransaction();
try {
invalidateAuthTokenLocked(accounts, db, accountType, authToken);
+ invalidateCustomTokenLocked(accounts, accountType, authToken);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
@@ -1363,6 +1377,26 @@ public class AccountManagerService
}
}
+ private void invalidateCustomTokenLocked(
+ UserAccounts accounts,
+ String accountType,
+ String authToken) {
+ if (authToken == null || accountType == null) {
+ return;
+ }
+ // Also wipe out cached token in memory.
+ for (Account a : accounts.accountTokenCaches.keySet()) {
+ if (a.type.equals(accountType)) {
+ WeakReference<TokenCache> tokenCacheRef =
+ accounts.accountTokenCaches.get(a);
+ TokenCache cache = null;
+ if (tokenCacheRef != null && (cache = tokenCacheRef.get()) != null) {
+ cache.remove(authToken);
+ }
+ }
+ }
+ }
+
private void invalidateAuthTokenLocked(UserAccounts accounts, SQLiteDatabase db,
String accountType, String authToken) {
if (authToken == null || accountType == null) {
@@ -1385,14 +1419,41 @@ public class AccountManagerService
String accountName = cursor.getString(1);
String authTokenType = cursor.getString(2);
db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ID + "=" + authTokenId, null);
- writeAuthTokenIntoCacheLocked(accounts, db, new Account(accountName, accountType),
- authTokenType, null);
+ writeAuthTokenIntoCacheLocked(
+ accounts,
+ db,
+ new Account(accountName, accountType),
+ authTokenType,
+ null);
}
} finally {
cursor.close();
}
}
+ private void saveCachedToken(
+ UserAccounts accounts,
+ Account account,
+ String callerPkg,
+ byte[] callerSigDigest,
+ String tokenType,
+ String token,
+ long expiryMillis) {
+
+ if (account == null || tokenType == null || callerPkg == null || callerSigDigest == null) {
+ return;
+ }
+ cancelNotification(getSigninRequiredNotificationId(accounts, account),
+ new UserHandle(accounts.userId));
+ synchronized (accounts.cacheLock) {
+ TokenCache cache = getTokenCacheForAccountLocked(accounts, account);
+ if (cache != null) {
+ cache.put(token, tokenType, callerPkg, callerSigDigest, expiryMillis);
+ }
+ return;
+ }
+ }
+
private boolean saveAuthTokenToDatabase(UserAccounts accounts, Account account, String type,
String authToken) {
if (account == null || type == null) {
@@ -1510,6 +1571,7 @@ public class AccountManagerService
db.update(TABLE_ACCOUNTS, values, ACCOUNTS_ID + "=?", argsAccountId);
db.delete(TABLE_AUTHTOKENS, AUTHTOKENS_ACCOUNTS_ID + "=?", argsAccountId);
accounts.authTokenCache.remove(account);
+ accounts.accountTokenCaches.remove(account);
db.setTransactionSuccessful();
String action = (password == null || password.length() == 0) ?
@@ -1673,9 +1735,14 @@ public class AccountManagerService
}
@Override
- public void getAuthToken(IAccountManagerResponse response, final Account account,
- final String authTokenType, final boolean notifyOnAuthFailure,
- final boolean expectActivityLaunch, Bundle loginOptionsIn) {
+ public void getAuthToken(
+ IAccountManagerResponse response,
+ final Account account,
+ final String authTokenType,
+ final boolean notifyOnAuthFailure,
+ final boolean expectActivityLaunch,
+ final Bundle loginOptions) {
+
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAuthToken: " + account
+ ", response " + response
@@ -1707,19 +1774,33 @@ public class AccountManagerService
final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
authenticatorInfo = mAuthenticatorCache.getServiceInfo(
AuthenticatorDescription.newKey(account.type), accounts.userId);
+
final boolean customTokens =
- authenticatorInfo != null && authenticatorInfo.type.customTokens;
+ authenticatorInfo != null && authenticatorInfo.type.customTokens;
// skip the check if customTokens
final int callerUid = Binder.getCallingUid();
final boolean permissionGranted = customTokens ||
permissionIsGranted(account, authTokenType, callerUid);
- final Bundle loginOptions = (loginOptionsIn == null) ? new Bundle() :
- loginOptionsIn;
+ // Get the calling package. We will use it for the purpose of caching.
+ final String callerPkg = loginOptions.getString(AccountManager.KEY_ANDROID_PACKAGE_NAME);
+ List<String> callerOwnedPackageNames = Arrays.asList(mPackageManager.getPackagesForUid(callerUid));
+ if (callerPkg == null || !callerOwnedPackageNames.contains(callerPkg)) {
+ String msg = String.format(
+ "Uid %s is attempting to illegally masquerade as package %s!",
+ callerUid,
+ callerPkg);
+ throw new SecurityException(msg);
+ }
+
// let authenticator know the identity of the caller
loginOptions.putInt(AccountManager.KEY_CALLER_UID, callerUid);
loginOptions.putInt(AccountManager.KEY_CALLER_PID, Binder.getCallingPid());
+
+ // Distill the caller's package signatures into a single digest.
+ final byte[] callerPkgSigDigest = calculatePackageSignatureDigest(callerPkg);
+
if (notifyOnAuthFailure) {
loginOptions.putBoolean(AccountManager.KEY_NOTIFY_ON_FAILURE, true);
}
@@ -1740,6 +1821,28 @@ public class AccountManagerService
}
}
+ if (customTokens) {
+ /*
+ * Look up tokens in the new cache only if the loginOptions don't have parameters
+ * outside of those expected to be injected by the AccountManager, e.g.
+ * ANDORID_PACKAGE_NAME.
+ */
+ String token = readCachedTokenInternal(
+ accounts,
+ account,
+ authTokenType,
+ callerPkg,
+ callerPkgSigDigest);
+ if (token != null) {
+ Bundle result = new Bundle();
+ result.putString(AccountManager.KEY_AUTHTOKEN, token);
+ result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name);
+ result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type);
+ onResult(response, result);
+ return;
+ }
+ }
+
new Session(accounts, response, account.type, expectActivityLaunch,
false /* stripAuthTokenFromResult */, account.name,
false /* authDetailsRequired */) {
@@ -1786,9 +1889,26 @@ public class AccountManagerService
"the type and name should not be empty");
return;
}
+ Account resultAccount = new Account(name, type);
if (!customTokens) {
- saveAuthTokenToDatabase(mAccounts, new Account(name, type),
- authTokenType, authToken);
+ saveAuthTokenToDatabase(
+ mAccounts,
+ resultAccount,
+ authTokenType,
+ authToken);
+ }
+ long expiryMillis = result.getLong(
+ AbstractAccountAuthenticator.KEY_CUSTOM_TOKEN_EXPIRY, 0L);
+ if (customTokens
+ && expiryMillis > System.currentTimeMillis()) {
+ saveCachedToken(
+ mAccounts,
+ account,
+ callerPkg,
+ callerPkgSigDigest,
+ authTokenType,
+ authToken,
+ expiryMillis);
}
}
@@ -1807,6 +1927,25 @@ public class AccountManagerService
}
}
+ private byte[] calculatePackageSignatureDigest(String callerPkg) {
+ MessageDigest digester;
+ try {
+ digester = MessageDigest.getInstance("SHA-256");
+ PackageInfo pkgInfo = mPackageManager.getPackageInfo(
+ callerPkg, PackageManager.GET_SIGNATURES);
+ for (Signature sig : pkgInfo.signatures) {
+ digester.update(sig.toByteArray());
+ }
+ } catch (NoSuchAlgorithmException x) {
+ Log.wtf(TAG, "SHA-256 should be available", x);
+ digester = null;
+ } catch (NameNotFoundException e) {
+ Log.w(TAG, "Could not find packageinfo for: " + callerPkg);
+ digester = null;
+ }
+ return (digester == null) ? null : digester.digest();
+ }
+
private void createNoCredentialsPermissionNotification(Account account, Intent intent,
int userId) {
int uid = intent.getIntExtra(
@@ -2745,13 +2884,13 @@ public class AccountManagerService
if (result != null) {
boolean isSuccessfulConfirmCreds = result.getBoolean(
AccountManager.KEY_BOOLEAN_RESULT, false);
- boolean isSuccessfulUpdateCreds =
+ boolean isSuccessfulUpdateCreds =
result.containsKey(AccountManager.KEY_ACCOUNT_NAME)
&& result.containsKey(AccountManager.KEY_ACCOUNT_TYPE);
- // We should only update lastAuthenticated time, if
+ // We should only update lastAuthenticated time, if
// mUpdateLastAuthenticatedTime is true and the confirmRequest
// or updateRequest was successful
- boolean needUpdate = mUpdateLastAuthenticatedTime
+ boolean needUpdate = mUpdateLastAuthenticatedTime
&& (isSuccessfulConfirmCreds || isSuccessfulUpdateCreds);
if (needUpdate || mAuthDetailsRequired) {
boolean accountPresent = isAccountPresentForCaller(mAccountName, mAccountType);
@@ -3398,7 +3537,6 @@ public class AccountManagerService
return;
}
}
-
String msg = "caller uid " + uid + " lacks any of " + TextUtils.join(",", permissions);
Log.w(TAG, " " + msg);
throw new SecurityException(msg);
@@ -3796,6 +3934,18 @@ public class AccountManagerService
}
}
+ protected String readCachedTokenInternal(
+ UserAccounts accounts,
+ Account account,
+ String tokenType,
+ String callingPackage,
+ byte[] pkgSigDigest) {
+ synchronized (accounts.cacheLock) {
+ TokenCache cache = getTokenCacheForAccountLocked(accounts, account);
+ return cache.get(tokenType, callingPackage, pkgSigDigest);
+ }
+ }
+
protected void writeAuthTokenIntoCacheLocked(UserAccounts accounts, final SQLiteDatabase db,
Account account, String key, String value) {
HashMap<String, String> authTokensForAccount = accounts.authTokenCache.get(account);
@@ -3877,6 +4027,17 @@ public class AccountManagerService
return authTokensForAccount;
}
+ protected TokenCache getTokenCacheForAccountLocked(UserAccounts accounts, Account account) {
+ WeakReference<TokenCache> cacheRef = accounts.accountTokenCaches.get(account);
+ TokenCache cache;
+ if (cacheRef == null || (cache = cacheRef.get()) == null) {
+ cache = new TokenCache();
+ cacheRef = new WeakReference<>(cache);
+ accounts.accountTokenCaches.put(account, cacheRef);
+ }
+ return cache;
+ }
+
private Context getContextForUser(UserHandle user) {
try {
return mContext.createPackageContextAsUser(mContext.getPackageName(), 0, user);
diff --git a/services/core/java/com/android/server/accounts/TokenCache.java b/services/core/java/com/android/server/accounts/TokenCache.java
new file mode 100644
index 000000000000..70a7010bd00f
--- /dev/null
+++ b/services/core/java/com/android/server/accounts/TokenCache.java
@@ -0,0 +1,163 @@
+/*
+ * 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.server.accounts;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * TokenCaches manage tokens associated with an account in memory.
+ */
+/* default */ class TokenCache {
+
+ private static class Value {
+ public final String token;
+ public final long expiryEpochMillis;
+
+ public Value(String token, long expiryEpochMillis) {
+ this.token = token;
+ this.expiryEpochMillis = expiryEpochMillis;
+ }
+ }
+
+ private static class Key {
+ public final String packageName;
+ public final String tokenType;
+ public final byte[] sigDigest;
+
+ public Key(String tokenType, String packageName, byte[] sigDigest) {
+ this.tokenType = tokenType;
+ this.packageName = packageName;
+ this.sigDigest = sigDigest;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o != null && o instanceof Key) {
+ Key cacheKey = (Key) o;
+ return Objects.equals(packageName, cacheKey.packageName)
+ && Objects.equals(tokenType, cacheKey.tokenType)
+ && Arrays.equals(sigDigest, cacheKey.sigDigest);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return packageName.hashCode() ^ tokenType.hashCode() ^ Arrays.hashCode(sigDigest);
+ }
+ }
+
+ /**
+ * Map associating basic token lookup information with with actual tokens (and optionally their
+ * expiration times).
+ */
+ private HashMap<Key, Value> mCachedTokens = new HashMap<>();
+
+ /**
+ * Map associated tokens with an Evictor that will manage evicting the token from the cache.
+ * This reverse lookup is needed because very little information is given at token invalidation
+ * time.
+ */
+ private HashMap<String, Evictor> mTokenEvictors = new HashMap<>();
+
+ private class Evictor {
+ private final String mToken;
+ private final List<Key> mKeys;
+
+ public Evictor(String token) {
+ mKeys = new ArrayList<>();
+ mToken = token;
+ }
+
+ public void add(Key k) {
+ mKeys.add(k);
+ }
+
+ public void evict() {
+ for (Key k : mKeys) {
+ mCachedTokens.remove(k);
+ }
+ // Clear out the evictor reference.
+ mTokenEvictors.remove(mToken);
+ }
+ }
+
+ /**
+ * Caches the specified token until the specified expiryMillis. The token will be associated
+ * with the given token type, package name, and digest of signatures.
+ *
+ * @param token
+ * @param tokenType
+ * @param packageName
+ * @param sigDigest
+ * @param expiryMillis
+ */
+ public void put(
+ String token,
+ String tokenType,
+ String packageName,
+ byte[] sigDigest,
+ long expiryMillis) {
+ if (token == null || System.currentTimeMillis() > expiryMillis) {
+ return;
+ }
+ Key k = new Key(tokenType, packageName, sigDigest);
+ // Prep evictor. No token should be cached without a corresponding evictor.
+ Evictor evictor = mTokenEvictors.get(token);
+ if (evictor == null) {
+ evictor = new Evictor(token);
+ }
+ evictor.add(k);
+ mTokenEvictors.put(token, evictor);
+ // Then cache values.
+ Value v = new Value(token, expiryMillis);
+ mCachedTokens.put(k, v);
+ }
+
+ /**
+ * Evicts the specified token from the cache. This should be called as part of a token
+ * invalidation workflow.
+ */
+ public void remove(String token) {
+ Evictor evictor = mTokenEvictors.get(token);
+ if (evictor == null) {
+ // This condition is expected if the token isn't cached.
+ return;
+ }
+ evictor.evict();
+ }
+
+ /**
+ * Gets a token from the cache if possible.
+ */
+ public String get(String tokenType, String packageName, byte[] sigDigest) {
+ Key k = new Key(tokenType, packageName, sigDigest);
+ Value v = mCachedTokens.get(k);
+ long currentTime = System.currentTimeMillis();
+ if (v != null && currentTime < v.expiryEpochMillis) {
+ return v.token;
+ } else if (v != null) {
+ remove(v.token);
+ }
+ return null;
+ }
+}
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index fa4d204b2e59..333db5d6dd33 100755
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -518,7 +518,7 @@ public final class ActiveServices {
// r.record is null if findServiceLocked() failed the caller permission check
if (r.record == null) {
throw new SecurityException(
- "Permission Denial: Accessing service " + r.record.name
+ "Permission Denial: Accessing service"
+ " from pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid()
+ " requires " + r.permission);
diff --git a/services/core/java/com/android/server/camera/CameraService.java b/services/core/java/com/android/server/camera/CameraService.java
index 777a9dd1bdcf..9347c241bb4e 100644
--- a/services/core/java/com/android/server/camera/CameraService.java
+++ b/services/core/java/com/android/server/camera/CameraService.java
@@ -20,10 +20,15 @@ import android.content.Context;
import android.content.pm.UserInfo;
import android.hardware.ICameraService;
import android.hardware.ICameraServiceProxy;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Message;
+import android.os.Process;
import android.os.RemoteException;
import android.os.UserManager;
+import android.util.Slog;
+import com.android.server.ServiceThread;
import com.android.server.SystemService;
import java.util.Collection;
@@ -36,7 +41,8 @@ import java.util.Set;
*
* @hide
*/
-public class CameraService extends SystemService {
+public class CameraService extends SystemService implements Handler.Callback {
+ private static final String TAG = "CameraService_proxy";
/**
* This must match the ICameraService.aidl definition
@@ -49,7 +55,14 @@ public class CameraService extends SystemService {
public static final int NO_EVENT = 0; // NOOP
public static final int USER_SWITCHED = 1; // User changed, argument is the new user handle
+ // Handler message codes
+ private static final int MSG_SWITCH_USER = 1;
+
+ private static final int RETRY_DELAY_TIME = 20; //ms
+
private final Context mContext;
+ private final ServiceThread mHandlerThread;
+ private final Handler mHandler;
private UserManager mUserManager;
private final Object mLock = new Object();
@@ -58,18 +71,29 @@ public class CameraService extends SystemService {
private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() {
@Override
public void pingForUserUpdate() {
- // Binder call
- synchronized(mLock) {
- if (mEnabledCameraUsers != null) {
- notifyMediaserver(USER_SWITCHED, mEnabledCameraUsers);
- }
- }
+ notifySwitchWithRetries(30);
}
};
public CameraService(Context context) {
super(context);
mContext = context;
+ mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_DISPLAY, /*allowTo*/false);
+ mHandlerThread.start();
+ mHandler = new Handler(mHandlerThread.getLooper(), this);
+ }
+
+ @Override
+ public boolean handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_SWITCH_USER: {
+ notifySwitchWithRetries(msg.arg1);
+ } break;
+ default: {
+ Slog.e(TAG, "CameraService error, invalid message: " + msg.what);
+ } break;
+ }
+ return true;
}
@Override
@@ -119,12 +143,30 @@ public class CameraService extends SystemService {
return handles;
}
- private void notifyMediaserver(int eventType, Set<Integer> updatedUserHandles) {
+ private void notifySwitchWithRetries(int retries) {
+ synchronized(mLock) {
+ if (mEnabledCameraUsers == null) {
+ return;
+ }
+ if (notifyMediaserver(USER_SWITCHED, mEnabledCameraUsers)) {
+ retries = 0;
+ }
+ }
+ if (retries <= 0) {
+ return;
+ }
+ Slog.i(TAG, "Could not notify camera service of user switch, retrying...");
+ mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_SWITCH_USER, retries - 1, 0, null),
+ RETRY_DELAY_TIME);
+ }
+
+ private boolean notifyMediaserver(int eventType, Set<Integer> updatedUserHandles) {
// Forward the user switch event to the native camera service running in the mediaserver
// process.
IBinder cameraServiceBinder = getBinderService(CAMERA_SERVICE_BINDER_NAME);
if (cameraServiceBinder == null) {
- return; // Camera service not active, cannot evict user clients.
+ Slog.w(TAG, "Could not notify mediaserver, camera service not available.");
+ return false; // Camera service not active, cannot evict user clients.
}
ICameraService cameraServiceRaw = ICameraService.Stub.asInterface(cameraServiceBinder);
@@ -132,8 +174,11 @@ public class CameraService extends SystemService {
try {
cameraServiceRaw.notifySystemEvent(eventType, toArray(updatedUserHandles));
} catch (RemoteException e) {
+ Slog.w(TAG, "Could not notify mediaserver, remote exception: " + e);
// Not much we can do if camera service is dead.
+ return false;
}
+ return true;
}
private static int[] toArray(Collection<Integer> c) {
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 792d4ba08b39..7673af44f5ac 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -283,9 +283,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
/**
* UIDs that have been white-listed to always be able to have network access
* in power save mode.
+ * TODO: An int array might be sufficient
*/
private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray();
+ private final SparseBooleanArray mPowerSaveTempWhitelistAppIds = new SparseBooleanArray();
+
/** Set of ifaces that are metered. */
private ArraySet<String> mMeteredIfaces = new ArraySet<>();
/** Set of over-limit templates that have been notified. */
@@ -371,6 +374,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
}
}
+ void updatePowerSaveTempWhitelistLocked() {
+ try {
+ final int[] whitelist = mDeviceIdleController.getAppIdTempWhitelist();
+ mPowerSaveTempWhitelistAppIds.clear();
+ if (whitelist != null) {
+ for (int uid : whitelist) {
+ mPowerSaveTempWhitelistAppIds.put(uid, true);
+ }
+ }
+ } catch (RemoteException e) {
+ }
+ }
+
public void systemReady() {
if (!isBandwidthControlEnabled()) {
Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy");
@@ -392,6 +408,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
if (mRestrictPower != enabled) {
mRestrictPower = enabled;
updateRulesForGlobalChangeLocked(true);
+ updateRulesForTempWhitelistChangeLocked();
}
}
}
@@ -404,6 +421,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
if (mRestrictBackground || mRestrictPower || mDeviceIdleMode) {
updateRulesForGlobalChangeLocked(true);
+ updateRulesForTempWhitelistChangeLocked();
updateNotificationsLocked();
}
}
@@ -428,6 +446,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
// listen for changes to power save whitelist
final IntentFilter whitelistFilter = new IntentFilter(
PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
+ whitelistFilter.addAction(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler);
// watch for network interfaces to be claimed
@@ -496,8 +515,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
public void onReceive(Context context, Intent intent) {
// on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected
synchronized (mRulesLock) {
- updatePowerSaveWhitelistLocked();
- updateRulesForGlobalChangeLocked(false);
+ if (PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED.equals(intent.getAction())) {
+ updatePowerSaveWhitelistLocked();
+ updateRulesForGlobalChangeLocked(false);
+ } else {
+ updatePowerSaveTempWhitelistLocked();
+ updateRulesForTempWhitelistChangeLocked();
+ }
}
}
};
@@ -2019,6 +2043,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
}
}
+ void updateRulesForTempWhitelistChangeLocked() {
+ final List<UserInfo> users = mUserManager.getUsers();
+ for (UserInfo user : users) {
+ for (int i = mPowerSaveTempWhitelistAppIds.size() - 1; i >= 0; i--) {
+ int appId = mPowerSaveTempWhitelistAppIds.keyAt(i);
+ int uid = UserHandle.getUid(user.id, appId);
+ updateRulesForUidLocked(uid);
+ }
+ }
+ }
+
private static boolean isUidValidForRules(int uid) {
// allow rules on specific system services, and any apps
if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
@@ -2065,8 +2100,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
// derive active rules based on policy and active state
+ int appId = UserHandle.getAppId(uid);
int uidRules = RULE_ALLOW_ALL;
- if (uidIdle && !mPowerSaveWhitelistAppIds.get(UserHandle.getAppId(uid))) {
+ if (uidIdle && !mPowerSaveWhitelistAppIds.get(appId)
+ && !mPowerSaveTempWhitelistAppIds.get(appId)) {
uidRules = RULE_REJECT_ALL;
} else if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
// uid in background, and policy says to block metered data
@@ -2077,7 +2114,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub
uidRules = RULE_REJECT_METERED;
}
} else if (mRestrictPower || mDeviceIdleMode) {
- final boolean whitelisted = mPowerSaveWhitelistAppIds.get(UserHandle.getAppId(uid));
+ final boolean whitelisted = mPowerSaveWhitelistAppIds.get(appId)
+ || mPowerSaveTempWhitelistAppIds.get(appId);
if (!whitelisted && !uidForeground
&& (uidPolicy & POLICY_ALLOW_BACKGROUND_BATTERY_SAVE) == 0) {
// uid is in background, restrict power use mode is on (so we want to
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f9bfe721b5af..47e39631cfca 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3360,6 +3360,46 @@ public class PackageManagerService extends IPackageManager.Stub {
}
@Override
+ public boolean shouldShowRequestPermissionRationale(String permissionName,
+ String packageName, int userId) {
+ if (UserHandle.getCallingUserId() != userId) {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ "canShowRequestPermissionRationale for user " + userId);
+ }
+
+ final int uid = getPackageUid(packageName, userId);
+ if (UserHandle.getAppId(getCallingUid()) != UserHandle.getAppId(uid)) {
+ return false;
+ }
+
+ if (checkPermission(permissionName, packageName, userId)
+ == PackageManager.PERMISSION_GRANTED) {
+ return false;
+ }
+
+ final int flags;
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ flags = getPermissionFlags(permissionName,
+ packageName, userId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ final int fixedFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
+ | PackageManager.FLAG_PERMISSION_POLICY_FIXED
+ | PackageManager.FLAG_PERMISSION_USER_FIXED;
+
+ if ((flags & fixedFlags) != 0) {
+ return false;
+ }
+
+ return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0;
+ }
+
+ @Override
public boolean isProtectedBroadcast(String actionName) {
synchronized (mPackages) {
return mProtectedBroadcasts.contains(actionName);
@@ -4991,7 +5031,7 @@ public class PackageManagerService extends IPackageManager.Stub {
scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK,
scanFlags, currentTime, null);
} catch (PackageManagerException e) {
- Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage());
+ Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage(), e);
// Delete invalid userdata apps
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 7bd5b7882962..b8d06921f235 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -497,6 +497,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* be done once per window. */
private WindowState mWinDismissingKeyguard;
+ /** When window is currently dismissing the keyguard, dismissing the keyguard must handle
+ * the keygaurd secure state change instantly case, e.g. the use case of inserting a PIN
+ * lock SIM card. This variable is used to record the previous keyguard secure state for
+ * monitoring secure state change on window dismissing keyguard. */
+ private boolean mSecureDismissingKeyguard;
+
/** The window that is currently showing "over" the keyguard. If there is an app window
* belonging to another app on top of this the keyguard shows. If there is a fullscreen
* app window under this, still dismiss the keyguard but don't show the app underneath. Show
@@ -2148,7 +2154,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- Window win = new PhoneWindow(context);
+ PhoneWindow win = new PhoneWindow(context);
+ win.setIsStartingWindow(true);
final TypedArray ta = win.getWindowStyle();
if (ta.getBoolean(
com.android.internal.R.styleable.Window_windowDisablePreview, false)
@@ -4272,9 +4279,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDismissKeyguard == DISMISS_KEYGUARD_NONE) {
if (DEBUG_LAYOUT) Slog.v(TAG,
"Setting mDismissKeyguard true by win " + win);
- mDismissKeyguard = mWinDismissingKeyguard == win ?
- DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
+ mDismissKeyguard = (mWinDismissingKeyguard == win
+ && mSecureDismissingKeyguard == mKeyguardSecure)
+ ? DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
mWinDismissingKeyguard = win;
+ mSecureDismissingKeyguard = mKeyguardSecure;
mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
} else if (mAppsToBeHidden.isEmpty() && showWhenLocked) {
if (DEBUG_LAYOUT) Slog.v(TAG,
@@ -4460,6 +4469,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
} else {
mWinDismissingKeyguard = null;
+ mSecureDismissingKeyguard = false;
mKeyguardHidden = false;
if (setKeyguardOccludedLw(false)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index c1fe9843d58e..3af97db93c5d 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -438,6 +438,9 @@ public final class PowerManagerService extends SystemService
// Set of app ids that we will always respect the wake locks for.
int[] mDeviceIdleWhitelist = new int[0];
+ // Set of app ids that are temporarily allowed to acquire wakelocks due to high-pri message
+ int[] mDeviceIdleTempWhitelist = new int[0];
+
private final SparseIntArray mUidState = new SparseIntArray();
// True if theater mode is enabled
@@ -2320,6 +2323,15 @@ public final class PowerManagerService extends SystemService
}
}
+ void setDeviceIdleTempWhitelistInternal(int[] appids) {
+ synchronized (mLock) {
+ mDeviceIdleTempWhitelist = appids;
+ if (mDeviceIdleMode) {
+ updateWakeLockDisabledStatesLocked();
+ }
+ }
+ }
+
void updateUidProcStateInternal(int uid, int procState) {
synchronized (mLock) {
mUidState.put(uid, procState);
@@ -2372,6 +2384,7 @@ public final class PowerManagerService extends SystemService
// for application uids that are not whitelisted.
if (appid >= Process.FIRST_APPLICATION_UID &&
Arrays.binarySearch(mDeviceIdleWhitelist, appid) < 0 &&
+ Arrays.binarySearch(mDeviceIdleTempWhitelist, appid) < 0 &&
mUidState.get(wakeLock.mOwnerUid,
ActivityManager.PROCESS_STATE_CACHED_EMPTY)
> ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) {
@@ -2579,6 +2592,7 @@ public final class PowerManagerService extends SystemService
pw.println(" mBatteryLevelLow=" + mBatteryLevelLow);
pw.println(" mDeviceIdleMode=" + mDeviceIdleMode);
pw.println(" mDeviceIdleWhitelist=" + Arrays.toString(mDeviceIdleWhitelist));
+ pw.println(" mDeviceIdleTempWhitelist=" + Arrays.toString(mDeviceIdleTempWhitelist));
pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
pw.println(" mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime));
@@ -3478,6 +3492,11 @@ public final class PowerManagerService extends SystemService
}
@Override
+ public void setDeviceIdleTempWhitelist(int[] appids) {
+ setDeviceIdleTempWhitelistInternal(appids);
+ }
+
+ @Override
public void updateUidProcState(int uid, int procState) {
updateUidProcStateInternal(uid, procState);
}
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index e5981fb99c07..4b62c401fc72 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -408,7 +408,7 @@ public final class ShutdownThread extends Thread {
}
// If it's to reboot into recovery, invoke uncrypt via init service.
- if (mRebootReason.equals(PowerManager.REBOOT_RECOVERY)) {
+ if (PowerManager.REBOOT_RECOVERY.equals(mRebootReason)) {
uncrypt();
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index f914369df6ef..5d6df2679b81 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -238,6 +238,7 @@ class DisplayContent {
final TaskStack stack = win.getStack();
if (win.isVisibleLw() && stack != null && stack != focusedStack) {
mTmpRect.set(win.mVisibleFrame);
+ // If no intersection, we need mTmpRect to be unmodified.
mTmpRect.intersect(win.mVisibleInsets);
mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 7cdf8b21c955..45450320828b 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -144,7 +144,11 @@ public class TaskStack {
bounds = mTmpRect;
mFullscreen = true;
} else {
- bounds.intersect(mTmpRect); // ensure bounds are entirely within the display rect
+ // ensure bounds are entirely within the display rect
+ if (!bounds.intersect(mTmpRect)) {
+ // Can't set bounds outside the containing display.. Sorry!
+ return false;
+ }
mFullscreen = mTmpRect.equals(bounds);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 5c9f87e08f1a..70194530bb44 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -208,7 +208,7 @@ public class WindowManagerService extends IWindowManager.Stub
static final boolean DEBUG_APP_ORIENTATION = false;
static final boolean DEBUG_CONFIGURATION = false;
static final boolean DEBUG_APP_TRANSITIONS = false;
- static final boolean DEBUG_STARTING_WINDOW = false;
+ static final boolean DEBUG_STARTING_WINDOW = true;
static final boolean DEBUG_WALLPAPER = false;
static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
static final boolean DEBUG_DRAG = false;
@@ -2272,6 +2272,16 @@ public class WindowManagerService extends IWindowManager.Stub
} else if (changingTarget.mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
mLastWallpaperDisplayOffsetY = changingTarget.mWallpaperDisplayOffsetY;
}
+ if (target.mWallpaperXStep >= 0) {
+ mLastWallpaperXStep = target.mWallpaperXStep;
+ } else if (changingTarget.mWallpaperXStep >= 0) {
+ mLastWallpaperXStep = changingTarget.mWallpaperXStep;
+ }
+ if (target.mWallpaperYStep >= 0) {
+ mLastWallpaperYStep = target.mWallpaperYStep;
+ } else if (changingTarget.mWallpaperYStep >= 0) {
+ mLastWallpaperYStep = changingTarget.mWallpaperYStep;
+ }
}
for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
@@ -6223,7 +6233,10 @@ public class WindowManagerService extends IWindowManager.Stub
int bottom = wf.bottom - cr.bottom;
frame.union(left, top, right, bottom);
ws.getStackBounds(stackBounds);
- frame.intersect(stackBounds);
+ if (!frame.intersect(stackBounds)) {
+ // Set frame empty if there's no intersection.
+ frame.setEmpty();
+ }
}
if (ws.mAppToken != null && ws.mAppToken.token == appToken &&
@@ -6270,12 +6283,16 @@ public class WindowManagerService extends IWindowManager.Stub
if (!includeFullDisplay) {
// Constrain frame to the screen size.
- frame.intersect(0, 0, dw, dh);
+ if (!frame.intersect(0, 0, dw, dh)) {
+ frame.setEmpty();
+ }
} else {
// Caller just wants entire display.
frame.set(0, 0, dw, dh);
}
-
+ if (frame.isEmpty()) {
+ return null;
+ }
if (width < 0) {
width = frame.width();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b8b243c2332d..eda7f798e516 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -547,7 +547,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
// Make sure the containing frame is within the content frame so we don't layout
// resized window under screen decorations.
- mContainingFrame.intersect(cf);
+ if (!mContainingFrame.intersect(cf)) {
+ mContainingFrame.set(cf);
+ }
mDisplayFrame.set(mContainingFrame);
} else {
mContainingFrame.set(pf);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index ff3bb283a147..23057c4becb3 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -90,23 +90,24 @@ public class UsageStatsService extends SystemService implements
static final String TAG = "UsageStatsService";
- static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ static final boolean DEBUG = false;
+ private static final boolean COMPRESS_TIME = false;
private static final long TEN_SECONDS = 10 * 1000;
private static final long ONE_MINUTE = 60 * 1000;
private static final long TWENTY_MINUTES = 20 * 60 * 1000;
- private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES;
+ private static final long FLUSH_INTERVAL = COMPRESS_TIME ? TEN_SECONDS : TWENTY_MINUTES;
private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds.
- static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = DEBUG ? ONE_MINUTE * 4
+ static final long DEFAULT_APP_IDLE_THRESHOLD_MILLIS = COMPRESS_TIME ? ONE_MINUTE * 4
: 12 * 60 * ONE_MINUTE; // 12 hours of screen-on time sans dream-time
- static final long DEFAULT_WALLCLOCK_APP_IDLE_THRESHOLD_MILLIS = DEBUG ? ONE_MINUTE * 8
+ static final long DEFAULT_WALLCLOCK_APP_IDLE_THRESHOLD_MILLIS = COMPRESS_TIME ? ONE_MINUTE * 8
: 2L * 24 * 60 * ONE_MINUTE; // 2 days
- static final long DEFAULT_CHECK_IDLE_INTERVAL = DEBUG ? ONE_MINUTE
+ static final long DEFAULT_CHECK_IDLE_INTERVAL = COMPRESS_TIME ? ONE_MINUTE
: 8 * 60 * ONE_MINUTE; // 8 hours
- static final long DEFAULT_PAROLE_INTERVAL = DEBUG ? ONE_MINUTE * 10
+ static final long DEFAULT_PAROLE_INTERVAL = COMPRESS_TIME ? ONE_MINUTE * 10
: 24 * 60 * ONE_MINUTE; // 24 hours between paroles
- static final long DEFAULT_PAROLE_DURATION = DEBUG ? ONE_MINUTE
+ static final long DEFAULT_PAROLE_DURATION = COMPRESS_TIME ? ONE_MINUTE
: 10 * ONE_MINUTE; // 10 minutes
// Handler message types.
@@ -338,7 +339,6 @@ public class UsageStatsService extends SystemService implements
/** Check all running users' apps to see if they enter an idle state. */
void checkIdleStates() {
- if (DEBUG) Slog.d(TAG, "Checking idle state");
final int[] runningUsers;
try {
runningUsers = ActivityManagerNative.getDefault().getRunningUserIds();
@@ -994,6 +994,12 @@ public class UsageStatsService extends SystemService implements
}
@Override
+ public void whitelistAppTemporarily(String packageName, long duration, int userId)
+ throws RemoteException {
+ mDeviceIdleController.addPowerSaveTempWhitelistApp(packageName, duration, userId);
+ }
+
+ @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index a41875f705e7..3fcd7d9257a7 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -2336,12 +2336,12 @@ public class PhoneNumberUtils
* @param phoneNumber A {@code CharSequence} the entirety of which represents a phone number.
* @return A {@code CharSequence} with appropriate annotations.
*/
- public static CharSequence getPhoneTtsSpannable(CharSequence phoneNumber) {
+ public static CharSequence createTtsSpannable(CharSequence phoneNumber) {
if (phoneNumber == null) {
return null;
}
Spannable spannable = Spannable.Factory.getInstance().newSpannable(phoneNumber);
- PhoneNumberUtils.addPhoneTtsSpan(spannable, 0, spannable.length());
+ PhoneNumberUtils.addTtsSpan(spannable, 0, spannable.length());
return spannable;
}
@@ -2353,8 +2353,8 @@ public class PhoneNumberUtils
* @param start The starting character position of the phone number in {@code s}.
* @param endExclusive The position after the ending character in the phone number {@code s}.
*/
- public static void addPhoneTtsSpan(Spannable s, int start, int endExclusive) {
- s.setSpan(getPhoneTtsSpan(s.subSequence(start, endExclusive).toString()),
+ public static void addTtsSpan(Spannable s, int start, int endExclusive) {
+ s.setSpan(createTtsSpan(s.subSequence(start, endExclusive).toString()),
start,
endExclusive,
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
@@ -2366,13 +2366,13 @@ public class PhoneNumberUtils
*
* @param phoneNumber A {@code CharSequence} the entirety of which represents a phone number.
* @return A {@code CharSequence} with appropriate annotations.
- * @deprecated Renamed {@link #getPhoneTtsSpannable}.
+ * @deprecated Renamed {@link #createTtsSpannable}.
*
* @hide
*/
@Deprecated
public static CharSequence ttsSpanAsPhoneNumber(CharSequence phoneNumber) {
- return getPhoneTtsSpannable(phoneNumber);
+ return createTtsSpannable(phoneNumber);
}
/**
@@ -2383,13 +2383,13 @@ public class PhoneNumberUtils
* @param start The starting character position of the phone number in {@code s}.
* @param end The ending character position of the phone number in {@code s}.
*
- * @deprecated Renamed {@link #addPhoneTtsSpan}.
+ * @deprecated Renamed {@link #addTtsSpan}.
*
* @hide
*/
@Deprecated
public static void ttsSpanAsPhoneNumber(Spannable s, int start, int end) {
- addPhoneTtsSpan(s, start, end);
+ addTtsSpan(s, start, end);
}
/**
@@ -2398,7 +2398,7 @@ public class PhoneNumberUtils
* @param phoneNumberString A {@code String} the entirety of which represents a phone number.
* @return A {@code TtsSpan} for {@param phoneNumberString}.
*/
- public static TtsSpan getPhoneTtsSpan(String phoneNumberString) {
+ public static TtsSpan createTtsSpan(String phoneNumberString) {
if (phoneNumberString == null) {
return null;
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index f29a6ed08399..f51cb65485f6 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -264,12 +264,19 @@ public class TelephonyManager {
/**
* The emergency dialer may choose to present activities with intent filters for this
* action as emergency assistance buttons that launch the activity when clicked.
+ *
+ * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_EMERGENCY_ASSISTANCE =
"android.telephony.action.EMERGENCY_ASSISTANCE";
/**
+ * @hide
+ */
+ public static final boolean EMERGENCY_ASSISTANCE_ENABLED = false;
+
+ /**
* The lookup key used with the {@link #ACTION_PHONE_STATE_CHANGED} broadcast
* for a String containing the new call state.
*
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index bf1ea4d0d4e9..3b7aa9f3fecb 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -218,6 +218,12 @@ public class MockPackageManager extends PackageManager {
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public boolean shouldShowRequestPermissionRationale(String permission) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public int checkSignatures(String pkg1, String pkg2) {
throw new UnsupportedOperationException();
diff --git a/tests/CameraPrewarmTest/AndroidManifest.xml b/tests/CameraPrewarmTest/AndroidManifest.xml
index eb402008319d..11b2686d2932 100644
--- a/tests/CameraPrewarmTest/AndroidManifest.xml
+++ b/tests/CameraPrewarmTest/AndroidManifest.xml
@@ -22,13 +22,13 @@
<activity android:name=".CameraActivity"
android:theme="@android:style/Theme.NoTitleBar">
<intent-filter>
- <action android:name="android.media.action.STILL_IMAGE_CAMERA_SECURE" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- <intent-filter>
<action android:name="android.media.action.STILL_IMAGE_CAMERA" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
+ <meta-data
+ android:name="android.media.still_image_camera_preview_service"
+ android:value="com.google.android.test.cameraprewarm.PrewarmService">
+ </meta-data>
</activity>
<activity android:name=".SecureCameraActivity"
@@ -37,16 +37,15 @@
<action android:name="android.media.action.STILL_IMAGE_CAMERA_SECURE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
+ <meta-data
+ android:name="android.media.still_image_camera_preview_service"
+ android:value="com.google.android.test.cameraprewarm.PrewarmService">
+ </meta-data>
</activity>
- <receiver android:name=".PrewarmReceiver" >
- <intent-filter>
- <action android:name="android.media.action.STILL_IMAGE_CAMERA_PREWARM" />
- </intent-filter>
- <intent-filter>
- <action android:name="android.media.action.STILL_IMAGE_CAMERA_COOLDOWN" />
- </intent-filter>
- </receiver>
+ <service android:name=".PrewarmService"
+ android:exported="true">
+ </service>
</application>
</manifest>
diff --git a/tests/CameraPrewarmTest/res/values/strings.xml b/tests/CameraPrewarmTest/res/values/strings.xml
index 11f7ac7b8598..fe39ac1d152e 100644
--- a/tests/CameraPrewarmTest/res/values/strings.xml
+++ b/tests/CameraPrewarmTest/res/values/strings.xml
@@ -16,6 +16,6 @@
-->
<resources>
- <string name="activity_title">Assistant</string>
+ <string name="activity_title">Camera Prewarm test</string>
<string name="search_label">Orilla Search Engine</string>
</resources>
diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java
index 4d22234b1ecc..0b43666a5453 100644
--- a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java
+++ b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/CameraActivity.java
@@ -19,7 +19,6 @@ package com.google.android.test.cameraprewarm;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
-import android.view.WindowManager;
import com.google.android.test.cameraprewarm.R;
@@ -31,7 +30,6 @@ public class CameraActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_activity);
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
Log.i(TAG, "Activity created");
}
}
diff --git a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmService.java
index d49f96d0a38c..d080b1a50d37 100644
--- a/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmReceiver.java
+++ b/tests/CameraPrewarmTest/src/com/google/android/test/cameraprewarm/PrewarmService.java
@@ -16,20 +16,18 @@
package com.google.android.test.cameraprewarm;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.provider.MediaStore;
+import android.service.media.CameraPrewarmService;
import android.util.Log;
-public class PrewarmReceiver extends BroadcastReceiver {
+public class PrewarmService extends CameraPrewarmService {
@Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(MediaStore.ACTION_STILL_IMAGE_CAMERA_PREWARM)) {
- Log.i(CameraActivity.TAG, "Prewarm received");
- } else if (intent.getAction().equals(MediaStore.ACTION_STILL_IMAGE_CAMERA_COOLDOWN)){
- Log.i(CameraActivity.TAG, "Cooldown received");
- }
+ public void onPrewarm() {
+ Log.i("PrewarmService", "Warming up");
+ }
+
+ @Override
+ public void onCooldown(boolean cameraIntentFired) {
+ Log.i("PrewarmService", "Cooling down fired=" + cameraIntentFired);
}
}
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index 3dae917435c2..cbe7c5dacc1e 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -61,6 +61,7 @@ public:
mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL),
mVersionCode(NULL), mVersionName(NULL), mReplaceVersion(false), mCustomPackage(NULL),
mExtraPackages(NULL), mMaxResVersion(NULL), mDebugMode(false), mNonConstantId(false),
+ mSkipSymbolsWithoutDefaultLocalization(false),
mProduct(NULL), mUseCrunchCache(false), mErrorOnFailedInsert(false),
mErrorOnMissingConfigEntry(false), mOutputTextSymbols(NULL),
mSingleCrunchInputFile(NULL), mSingleCrunchOutputFile(NULL),
@@ -191,6 +192,8 @@ public:
void setDebugMode(bool val) { mDebugMode = val; }
bool getNonConstantId() const { return mNonConstantId; }
void setNonConstantId(bool val) { mNonConstantId = val; }
+ bool getSkipSymbolsWithoutDefaultLocalization() const { return mSkipSymbolsWithoutDefaultLocalization; }
+ void setSkipSymbolsWithoutDefaultLocalization(bool val) { mSkipSymbolsWithoutDefaultLocalization = val; }
const char* getProduct() const { return mProduct; }
void setProduct(const char * val) { mProduct = val; }
void setUseCrunchCache(bool val) { mUseCrunchCache = val; }
@@ -315,6 +318,7 @@ private:
const char* mMaxResVersion;
bool mDebugMode;
bool mNonConstantId;
+ bool mSkipSymbolsWithoutDefaultLocalization;
const char* mProduct;
bool mUseCrunchCache;
bool mErrorOnFailedInsert;
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 7dee585fa7be..f832c605376c 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -212,6 +212,9 @@ void usage(void)
" --ignore-assets\n"
" Assets to be ignored. Default pattern is:\n"
" %s\n"
+ " --skip-symbols-without-default-localization\n"
+ " Prevents symbols from being generated for strings that do not have a default\n"
+ " localization\n"
" --no-version-vectors\n"
" Do not automatically generate versioned copies of vector XML resources.\n",
gDefaultIgnoreAssets);
@@ -659,6 +662,8 @@ int main(int argc, char* const argv[])
bundle.setProduct(argv[0]);
} else if (strcmp(cp, "-non-constant-id") == 0) {
bundle.setNonConstantId(true);
+ } else if (strcmp(cp, "-skip-symbols-without-default-localization") == 0) {
+ bundle.setSkipSymbolsWithoutDefaultLocalization(true);
} else if (strcmp(cp, "-shared-lib") == 0) {
bundle.setNonConstantId(true);
bundle.setBuildSharedLibrary(true);
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index beb94fdbcfc5..5d208152e084 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -1604,7 +1604,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil
if (table.hasResources()) {
sp<AaptSymbols> symbols = assets->getSymbolsFor(String8("R"));
- err = table.addSymbols(symbols);
+ err = table.addSymbols(symbols, bundle->getSkipSymbolsWithoutDefaultLocalization());
if (err < NO_ERROR) {
return err;
}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 3b146da630d8..e64fdf7f54b9 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -913,6 +913,7 @@ status_t compileResourceFile(Bundle* bundle,
if (code == ResXMLTree::START_TAG) {
const String16* curTag = NULL;
String16 curType;
+ String16 curName;
int32_t curFormat = ResTable_map::TYPE_ANY;
bool curIsBag = false;
bool curIsBagReplaceOnOverwrite = false;
@@ -1321,6 +1322,10 @@ status_t compileResourceFile(Bundle* bundle,
ssize_t attri = block.indexOfAttribute(NULL, "type");
if (attri >= 0) {
curType = String16(block.getAttributeStringValue(attri, &len));
+ ssize_t nameIdx = block.indexOfAttribute(NULL, "name");
+ if (nameIdx >= 0) {
+ curName = String16(block.getAttributeStringValue(nameIdx, &len));
+ }
ssize_t formatIdx = block.indexOfAttribute(NULL, "format");
if (formatIdx >= 0) {
String16 formatStr = String16(block.getAttributeStringValue(
@@ -1363,6 +1368,9 @@ status_t compileResourceFile(Bundle* bundle,
}
if (name.size() > 0) {
+ if (locale.size() == 0) {
+ outTable->addDefaultLocalization(name);
+ }
if (translatable == false16) {
curIsFormatted = false;
// Untranslatable strings must only exist in the default [empty] locale
@@ -1658,6 +1666,9 @@ status_t compileResourceFile(Bundle* bundle,
hasErrors = localHasErrors = true;
}
else if (err == NO_ERROR) {
+ if (curType == string16 && !curParams.language[0] && !curParams.country[0]) {
+ outTable->addDefaultLocalization(curName);
+ }
if (curIsPseudolocalizable && localeIsDefined(curParams)
&& bundle->getPseudolocalize() > 0) {
// pseudolocalize here
@@ -2622,8 +2633,11 @@ status_t ResourceTable::assignResourceIds()
return firstError;
}
-status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) {
+status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols,
+ bool skipSymbolsWithoutDefaultLocalization) {
const size_t N = mOrderedPackages.size();
+ const String8 defaultLocale;
+ const String16 stringType("string");
size_t pi;
for (pi=0; pi<N; pi++) {
@@ -2664,6 +2678,19 @@ status_t ResourceTable::addSymbols(const sp<AaptSymbols>& outSymbols) {
return UNKNOWN_ERROR;
}
if (Res_GETPACKAGE(rid) + 1 == p->getAssignedId()) {
+
+ if (skipSymbolsWithoutDefaultLocalization &&
+ t->getName() == stringType) {
+
+ // Don't generate symbols for strings without a default localization.
+ if (mHasDefaultLocalization.find(c->getName())
+ == mHasDefaultLocalization.end()) {
+ // printf("Skip symbol [%08x] %s\n", rid,
+ // String8(c->getName()).string());
+ continue;
+ }
+ }
+
typeSymbols->addSymbol(String8(c->getName()), rid, c->getPos());
String16 comment(c->getComment());
@@ -2686,6 +2713,12 @@ ResourceTable::addLocalization(const String16& name, const String8& locale, cons
mLocalizations[name][locale] = src;
}
+void
+ResourceTable::addDefaultLocalization(const String16& name)
+{
+ mHasDefaultLocalization.insert(name);
+}
+
/*!
* Flag various sorts of localization problems. '+' indicates checks already implemented;
diff --git a/tools/aapt/ResourceTable.h b/tools/aapt/ResourceTable.h
index 96442248d296..2c1bec1fb128 100644
--- a/tools/aapt/ResourceTable.h
+++ b/tools/aapt/ResourceTable.h
@@ -235,8 +235,10 @@ public:
const ConfigDescription* config = NULL);
status_t assignResourceIds();
- status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL);
+ status_t addSymbols(const sp<AaptSymbols>& outSymbols = NULL,
+ bool skipSymbolsWithoutDefaultLocalization = false);
void addLocalization(const String16& name, const String8& locale, const SourcePos& src);
+ void addDefaultLocalization(const String16& name);
status_t validateLocalizations(void);
status_t flatten(Bundle* bundle, const sp<const ResourceFilter>& filter,
@@ -588,6 +590,8 @@ private:
// key = string resource name, value = set of locales in which that name is defined
std::map<String16, std::map<String8, SourcePos>> mLocalizations;
+ // set of string resources names that have a default localization
+ std::set<String16> mHasDefaultLocalization;
std::queue<CompileResourceWorkItem> mWorkQueue;
};