blob: 9a1fe6501221a46930acd3b543ae7b39a24647ad [file] [log] [blame]
Neil Fuller3352cfc2019-11-07 15:35:05 +00001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.timezonedetector;
18
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.app.timezonedetector.ITimeZoneDetectorService;
Neil Fuller2c6d5102019-11-29 09:02:39 +000022import android.app.timezonedetector.ManualTimeZoneSuggestion;
Neil Fuller3352cfc2019-11-07 15:35:05 +000023import android.app.timezonedetector.PhoneTimeZoneSuggestion;
24import android.content.ContentResolver;
25import android.content.Context;
26import android.database.ContentObserver;
27import android.os.Handler;
28import android.provider.Settings;
29
30import com.android.internal.annotations.VisibleForTesting;
31import com.android.internal.util.DumpUtils;
Neil Fuller3352cfc2019-11-07 15:35:05 +000032import com.android.server.FgThread;
33import com.android.server.SystemService;
34
35import java.io.FileDescriptor;
36import java.io.PrintWriter;
37import java.util.Objects;
38
39/**
40 * The implementation of ITimeZoneDetectorService.aidl.
41 */
42public final class TimeZoneDetectorService extends ITimeZoneDetectorService.Stub {
43 private static final String TAG = "TimeZoneDetectorService";
44
45 /**
46 * Handles the lifecycle for {@link TimeZoneDetectorService}.
47 */
48 public static class Lifecycle extends SystemService {
49
50 public Lifecycle(@NonNull Context context) {
51 super(context);
52 }
53
54 @Override
55 public void onStart() {
56 TimeZoneDetectorService service = TimeZoneDetectorService.create(getContext());
57
58 // Publish the binder service so it can be accessed from other (appropriately
59 // permissioned) processes.
60 publishBinderService(Context.TIME_ZONE_DETECTOR_SERVICE, service);
61 }
62 }
63
64 @NonNull private final Context mContext;
65 @NonNull private final Handler mHandler;
66 @NonNull private final TimeZoneDetectorStrategy mTimeZoneDetectorStrategy;
67
68 private static TimeZoneDetectorService create(@NonNull Context context) {
69 final TimeZoneDetectorStrategy timeZoneDetectorStrategy =
70 TimeZoneDetectorStrategy.create(context);
71
72 Handler handler = FgThread.getHandler();
73 ContentResolver contentResolver = context.getContentResolver();
74 contentResolver.registerContentObserver(
75 Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true,
76 new ContentObserver(handler) {
77 public void onChange(boolean selfChange) {
Neil Fuller2c6d5102019-11-29 09:02:39 +000078 timeZoneDetectorStrategy.handleAutoTimeZoneDetectionChange();
Neil Fuller3352cfc2019-11-07 15:35:05 +000079 }
80 });
81
82 return new TimeZoneDetectorService(context, handler, timeZoneDetectorStrategy);
83 }
84
85 @VisibleForTesting
86 public TimeZoneDetectorService(@NonNull Context context, @NonNull Handler handler,
87 @NonNull TimeZoneDetectorStrategy timeZoneDetectorStrategy) {
88 mContext = Objects.requireNonNull(context);
89 mHandler = Objects.requireNonNull(handler);
90 mTimeZoneDetectorStrategy = Objects.requireNonNull(timeZoneDetectorStrategy);
91 }
92
93 @Override
Neil Fuller2c6d5102019-11-29 09:02:39 +000094 public void suggestManualTimeZone(@NonNull ManualTimeZoneSuggestion timeZoneSuggestion) {
95 enforceSuggestManualTimeZonePermission();
96 Objects.requireNonNull(timeZoneSuggestion);
97
98 mHandler.post(() -> mTimeZoneDetectorStrategy.suggestManualTimeZone(timeZoneSuggestion));
99 }
100
101 @Override
Neil Fuller3352cfc2019-11-07 15:35:05 +0000102 public void suggestPhoneTimeZone(@NonNull PhoneTimeZoneSuggestion timeZoneSuggestion) {
Neil Fuller2c6d5102019-11-29 09:02:39 +0000103 enforceSuggestPhoneTimeZonePermission();
Neil Fuller3352cfc2019-11-07 15:35:05 +0000104 Objects.requireNonNull(timeZoneSuggestion);
105
106 mHandler.post(() -> mTimeZoneDetectorStrategy.suggestPhoneTimeZone(timeZoneSuggestion));
107 }
108
109 @Override
110 protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw,
111 @Nullable String[] args) {
112 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
113
Neil Fuller2c6d5102019-11-29 09:02:39 +0000114 mTimeZoneDetectorStrategy.dumpState(pw, args);
Neil Fuller3352cfc2019-11-07 15:35:05 +0000115 }
116
Neil Fuller2c6d5102019-11-29 09:02:39 +0000117 private void enforceSuggestPhoneTimeZonePermission() {
Neil Fuller3352cfc2019-11-07 15:35:05 +0000118 mContext.enforceCallingPermission(
119 android.Manifest.permission.SET_TIME_ZONE, "set time zone");
120 }
Neil Fuller2c6d5102019-11-29 09:02:39 +0000121
122 private void enforceSuggestManualTimeZonePermission() {
123 mContext.enforceCallingOrSelfPermission(
124 android.Manifest.permission.SET_TIME_ZONE, "set time zone");
125 }
Neil Fuller3352cfc2019-11-07 15:35:05 +0000126}
127